OPTION(SALOME_BUILD_DOC "Generate SALOME SMESH documentation" ON)
# Advanced options:
-OPTION(SALOME_BUILD_GUI "Enable GUI" ON)
-OPTION(SALOME_SMESH_USE_CGNS "Enable import/export to CGNS format" OFF)
-OPTION(SALOME_SMESH_USE_TBB "Enable parallel computation" OFF)
-OPTION(SALOME_SMESH_DYNLOAD_LOCAL "Load plug-ins' symbols locally (Linux only)" ON)
+OPTION(SALOME_BUILD_GUI "Enable GUI" ON)
+OPTION(SALOME_SMESH_USE_CGNS "Enable import/export to CGNS format" OFF)
+OPTION(SALOME_SMESH_USE_TBB "Enable parallel computation" OFF)
+OPTION(SALOME_SMESH_DYNLOAD_LOCAL "Load plug-ins' symbols locally (Linux only)" ON)
+OPTION(SMESH_USE_MESHGEMS_HYPOSET "Prefer MeshGems algorithms in sets of hypotheses" OFF)
CMAKE_DEPENDENT_OPTION(SALOME_SMESH_BUILD_FRENCH_DOC "Generate SALOME SMESH French documentation" OFF
"SALOME_BUILD_DOC" OFF)
ADD_DEFINITIONS(-DDYNLOAD_LOCAL)
ENDIF(SALOME_SMESH_DYNLOAD_LOCAL)
+IF(SMESH_USE_MESHGEMS_HYPOSET)
+ SET(SMESH_USE_MESHGEMS_HYPOSET_VAR "true")
+ELSE(SMESH_USE_MESHGEMS_HYPOSET)
+ SET(SMESH_USE_MESHGEMS_HYPOSET_VAR "false")
+ENDIF(SMESH_USE_MESHGEMS_HYPOSET)
+
#On Linux use Fortran to compile MEFISTO2D
IF(NOT WIN32)
ENABLE_LANGUAGE(Fortran)
ADD_DEFINITIONS(-DENABLE_MEFISTO)
ENDIF(NOT WIN32)
-MARK_AS_ADVANCED(SALOME_BUILD_GUI SALOME_SMESH_USE_CGNS SALOME_SMESH_USE_TBB SALOME_SMESH_DYNLOAD_LOCAL)
+MARK_AS_ADVANCED(SALOME_BUILD_GUI SALOME_SMESH_USE_CGNS SALOME_SMESH_USE_TBB SALOME_SMESH_DYNLOAD_LOCAL SMESH_USE_MESHGEMS_HYPOSET)
# Prerequisites
# =============
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-import os, sys
+"""
+Set-up additional environment needed for SMESH module and meshing plugins.
+"""
+
+import os
+import os.path as osp
+import sys
+from xml.dom.minidom import parse
from setenv import add_path, get_lib_dir, salome_subdir
# -----------------------------------------------------------------------------
def set_env(args):
- """Add to the PATH-variables modules specific paths"""
- psep = os.pathsep
- python_version="python%d.%d" % sys.version_info[0:2]
+ """Set-up additional environment needed for SMESH module and plugins"""
+ py_version = 'python{}.{}'.format(*sys.version_info[:2])
+
+ # search and set-up meshing plugins
+ plugins = []
+ resource_dirs = []
+ for var in [i for i in os.environ if i.endswith('_ROOT_DIR') and os.environ[i]]:
+ plugin_root = os.environ[var]
+ plugin_name = var[:-9] # plugin name as extracted from environment variable
+ plugin_lname = plugin_name.lower() # plugin name in lowercase
+ # look for NAMEOFPlugin.xml file among resource files
+ # resource dir must be <plugin_root>/share/salome/resources/<plugin_name_lowercase>
+ resource_dir = osp.join(plugin_root, 'share', salome_subdir, 'resources', plugin_lname)
+ if not os.access(resource_dir, os.F_OK):
+ continue # directory does not exist or isn't accessible
- if "SALOME_StdMeshersResources" not in os.environ:
- os.environ["SALOME_StdMeshersResources"] \
- = os.path.join(os.environ["SMESH_ROOT_DIR"],"share",salome_subdir,"resources","smesh")
- pass
+ for resource_file in [i for i in os.listdir(resource_dir) \
+ if osp.isfile(os.path.join(resource_dir, i))]:
+ # look for resource file (XML) to extract valid plugin name
+ if resource_file.lower() == f'{plugin_lname}.xml':
+ try:
+ # get plugin name from 'resources' attribute of 'meshers-group' xml node
+ # as name extracted from environment variable can be in wrong case
+ xml_doc = parse(osp.join(resource_dir, resource_file))
+ plugin_name = xml_doc.getElementsByTagName('meshers-group')[0].getAttribute('resources')
- # find plugins
- plugin_list = ["StdMeshers"]
- resource_path_list = []
- for env_var in list(os.environ.keys()):
- value = os.environ[env_var]
- if env_var[-9:] == "_ROOT_DIR" and value:
- plugin_root = value
- plugin = env_var[:-9] # plugin name may have wrong case
+ # add plugin to the list of available meshing plugins
+ plugins.append(plugin_name)
+ resource_dirs.append(resource_dir)
- # look for NAMEOFPlugin.xml file among resource files
- resource_dir = os.path.join(plugin_root,"share",salome_subdir,"resources",plugin.lower())
- if not os.access( resource_dir, os.F_OK ): continue
- for resource_file in os.listdir( resource_dir ):
- if not resource_file.endswith( ".xml") or \
- resource_file.lower() != plugin.lower() + ".xml":
- continue
- # use "resources" attribute of "meshers-group" as name of plugin in a right case
- from xml.dom.minidom import parse
- xml_doc = parse( os.path.join( resource_dir, resource_file ))
- meshers_nodes = xml_doc.getElementsByTagName("meshers-group")
- if not meshers_nodes or not meshers_nodes[0].hasAttribute("resources"): continue
- plugin = meshers_nodes[0].getAttribute("resources")
- if plugin in plugin_list: continue
+ # setup environment needed for plugin
+ add_path(osp.join(plugin_root, 'bin', salome_subdir), 'PATH')
+ add_path(osp.join(plugin_root, get_lib_dir(), salome_subdir), 'PATH' \
+ if sys.platform == 'win32' else 'LD_LIBRARY_PATH')
+ add_path(osp.join(plugin_root, 'bin', salome_subdir), 'PYTHONPATH')
+ add_path(osp.join(plugin_root, get_lib_dir(), salome_subdir), 'PYTHONPATH')
+ add_path(osp.join(plugin_root, get_lib_dir(), py_version, 'site-packages',
+ salome_subdir), 'PYTHONPATH')
- # add paths of plugin
- plugin_list.append(plugin)
- if "SALOME_"+plugin+"Resources" not in os.environ:
- resource_path = os.path.join(plugin_root,"share",salome_subdir,"resources",plugin.lower())
- os.environ["SALOME_"+plugin+"Resources"] = resource_path
- resource_path_list.append( resource_path )
- add_path(os.path.join(plugin_root,get_lib_dir(),python_version, "site-packages",salome_subdir), "PYTHONPATH")
- add_path(os.path.join(plugin_root,get_lib_dir(),salome_subdir), "PYTHONPATH")
+ break # one resource file is enough!
+ except:
+ continue # invalid resource valid
- if sys.platform == "win32":
- add_path(os.path.join(plugin_root,get_lib_dir(),salome_subdir), "PATH")
- add_path(os.path.join(plugin_root,"bin",salome_subdir), "PYTHONPATH")
- else:
- add_path(os.path.join(plugin_root,get_lib_dir(),salome_subdir), "LD_LIBRARY_PATH")
- add_path(os.path.join(plugin_root,"bin",salome_subdir), "PYTHONPATH")
- add_path(os.path.join(plugin_root,"bin",salome_subdir), "PATH")
- pass
- pass
- break
- os.environ["SMESH_MeshersList"] = ":".join(plugin_list)
- os.environ["SalomeAppConfig"] = os.environ["SalomeAppConfig"] + psep + psep.join(resource_path_list)
+ # full list of known meshers
+ os.environ['SMESH_MeshersList'] = os.pathsep.join(['StdMeshers'] + plugins)
+ # access to resources
+ os.environ['SalomeAppConfig'] = os.pathsep.join(os.environ['SalomeAppConfig'].split(os.pathsep) + resource_dirs)
# create a sphere
sphere = geompy.MakeSphereR( 50 )
-geompy.addToStudy( sphere, "sphere" )
+
+# cut the sphere by a box
+box = geompy.MakeBoxDXDYDZ( 100, 100, 100 )
+partition = geompy.MakePartition([ sphere ], [ box ], theName="partition")
# create a mesh and assign a "Body Fitting" algo
-mesh = smesh.Mesh( sphere )
+mesh = smesh.Mesh( partition )
cartAlgo = mesh.BodyFitted()
# define a cartesian grid using Coordinates
print("nb hexahedra",mesh.NbHexas())
print("nb tetrahedra",mesh.NbTetras())
print("nb polyhedra",mesh.NbPolyhedrons())
+print("nb faces",mesh.NbFaces())
+print()
+
+# activate creation of faces
+cartHyp.SetToCreateFaces( True )
+
+mesh.Compute()
+print("nb hexahedra",mesh.NbHexas())
+print("nb tetrahedra",mesh.NbTetras())
+print("nb polyhedra",mesh.NbPolyhedrons())
+print("nb faces",mesh.NbFaces())
+print()
+# enable consideration of shared faces
+cartHyp.SetToConsiderInternalFaces( True )
+mesh.Compute()
+print("nb hexahedra",mesh.NbHexas())
+print("nb tetrahedra",mesh.NbTetras())
+print("nb polyhedra",mesh.NbPolyhedrons())
+print("nb faces",mesh.NbFaces())
+print()
# define the grid by setting different spacing in 2 sub-ranges of geometry
spaceFuns = ["5","10+10*t"]
mesh.Triangle()
mesh.Quadrangle(face1)
-mesh.Compute()
algo3D = mesh.Tetrahedron()
thickness = 20
numberOfLayers = 10
stretchFactor = 1.5
-layersHyp = algo3D.ViscousLayers(thickness,numberOfLayers,stretchFactor,ignoreFaces)
+groupName = "Boundary layers"
+layersHyp = algo3D.ViscousLayers(thickness,numberOfLayers,stretchFactor,
+ ignoreFaces, # optional
+ groupName = groupName) # optional
mesh.Compute()
+# retrieve boundary prisms created by mesh.Compute()
+boundaryGroup = mesh.GetGroupByName( layersHyp.GetGroupName() )[0]
+print( "Nb boundary prisms", boundaryGroup.Size() )
+
mesh.MakeGroup("Tetras",SMESH.VOLUME,SMESH.FT_ElemGeomType,"=",SMESH.Geom_TETRA)
mesh.MakeGroup("Pyras",SMESH.VOLUME,SMESH.FT_ElemGeomType,"=",SMESH.Geom_PYRAMID)
mesh.MakeGroup("Prims",SMESH.VOLUME,SMESH.FT_ElemGeomType,"=",SMESH.Geom_PENTA)
mesh = smesh.Mesh(face1,"VicsousLayers2D")
mesh.Segment().NumberOfSegments( 5 )
-# viscous layers should be created on 1 edge, as we set 3 edges to ignore
-vlHyp = mesh.Triangle().ViscousLayers2D( 2, 3, 1.5, edgeIds, isEdgesToIgnore=True )
-
+# viscous layers will be created on 1 edge, as we set 3 edges to ignore
+vlHyp = mesh.Triangle().ViscousLayers2D( 2, 3, 1.5,
+ edgeIds, isEdgesToIgnore=True, # optional
+ groupName=groupName) # optional
mesh.Compute()
-# viscous layers should be created on 3 edges, as we pass isEdgesToIgnore=False
+# retrieve boundary elements created by mesh.Compute()
+quadrangles = mesh.GetGroupByName( vlHyp.GetGroupName() )[0]
+print( "Nb boundary quadrangles", quadrangles.Size() )
+
+# viscous layers will be created on 3 edges, as we pass isEdgesToIgnore=False
vlHyp.SetEdges( edgeIds, False )
mesh.Compute()
boundary faces/edges of the shape of this sub-mesh, at same time
possibly being internal faces/edges within the whole model.
+* **Create groups from layers** - activates creation of a group containing elements of the layers.
+
.. image:: ../images/viscous_layers_on_submesh.png
:align: center
* :ref:`Extrusion 3D <prism_3d_algo_page>` - for meshing prismatic 3D shapes with hexahedra and prisms.
* :ref:`Quadrangle: Medial Axis Projection <quad_from_ma_algo_page>` - for quadrangle meshing of faces with sinuous borders and rings.
* **Polygon per Face** meshing algorithm - generates one mesh face (either a triangle, a quadrangle or a polygon) per a geometrical face using all nodes from the face boundary.
+ * **Polyhedron per Solid** meshing algorithm - generates one mesh volume (of a classical type or a polyhedron) per a geometrical solid using all faces of the solid boundary. It does not require that 2D mesh is generated on geometrical faces. It creates one mesh edge per geometrical edges and applies **Polygon per Face** to faces if they are not meshed by optional algorithms of lower dimensions.
* :ref:`Projection algorithms <projection_algos_page>` - for meshing by projection of another mesh.
* :ref:`Import algorithms <import_algos_page>` - for meshing by importing elements from another mesh.
* :ref:`Radial Prism <radial_prism_algo_page>` - for meshing 3D geometrical objects with cavities with hexahedra and prisms.
.. centered::
Implement Edges switched off to the left and on to the right
+* **Create Faces** check-box activates creation on mesh faces.
+* **Consider Shared and Internal Faces** check-box activates treatment of faces shared by solids and internal. By default the algorithm considers only outer boundaries of the geometry.
+* **Apply Threshold to Shared / Internal Faces** check-box activates application of **Threshold** to cells cut by shared and internal faces, that can cause appearance of holes inside the mesh.
* **Definition mode** allows choosing how Cartesian structured grid is defined. Location of nodes along each grid axis is defined individually:
* You can specify the **Coordinates** of grid nodes. **Insert** button inserts a node at **Step** distance (negative or positive) from the selected node. **Delete** button removes the selected node. Double click on a coordinate in the list enables its edition. **Note** that node coordinates are measured along directions of axes that can differ from the directions of the Global Coordinate System.
List of sets of hypotheses. Tag *[custom]* is automatically added to the sets defined by the user.
.. note::
- * *"Automatic"* in the names of predefined sets of hypotheses does not actually mean that they are suitable for meshing any geometry.
* The list of sets of hypotheses can be shorter than in the above image depending on the geometry dimension.
* **Default Number of Segments** - defines the default number of segments in :ref:`Number of Segments <number_of_segments_anchor>` hypothesis.
+.. _use_meshgems_pref:
+
+ * **Use MeshGems meshers when assigning set of hypotheses** - if activated, commercial meshers of MeshGems suite are used instead of a free mesher NETGEN when assigning a set of hypotheses in Create Mesh/Sub-mesh dialog.
+
* **Mesh loading**
* **No mesh loading from study file at hypothesis modification** - if activated, the mesh data will not be loaded from the study file when a hypothesis is modified. This allows saving time by omitting loading data of a large mesh that is planned to be recomputed with other parameters.
void SetMethod( in VLExtrusionMethod how );
VLExtrusionMethod GetMethod();
+
+ void SetGroupName(in string name);
+ string GetGroupName();
};
/*!
*/
void SetStretchFactor(in double factor) raises (SALOME::SALOME_Exception);
double GetStretchFactor();
+
+ void SetGroupName(in string name);
+ string GetGroupName();
};
/*!
boolean GetFixedPoint(out SMESH::PointStruct p);
/*!
- * Enables implementation of geometrical edges into the mesh. If this feature
+ * Enable implementation of geometrical edges into the mesh. If this feature
* is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
* they don't coincide with the grid lines
*/
boolean GetToAddEdges();
/*!
- * Returns axes at which a number of generated hexahedra is maximal
+ * Enable treatment of geom faces, either shared by solids or internal.
+ */
+ void SetToConsiderInternalFaces(in boolean toTreat);
+ boolean GetToConsiderInternalFaces();
+
+ /*!
+ * Enable applying size threshold to grid cells cut by internal geom faces.
+ */
+ void SetToUseThresholdForInternalFaces(in boolean toUse);
+ boolean GetToUseThresholdForInternalFaces();
+
+ /*!
+ * Enable creation of mesh faces.
+ */
+ void SetToCreateFaces(in boolean toCreate);
+ boolean GetToCreateFaces();
+
+ /*!
+ * Return axes at which a number of generated hexahedra is maximal
*/
void ComputeOptimalAxesDirs(in GEOM::GEOM_Object shape,
in boolean isOrthogonal,
out SMESH::DirStruct x,
out SMESH::DirStruct y,
- out SMESH::DirStruct z )
+ out SMESH::DirStruct z )
raises (SALOME::SALOME_Exception);
/*!
- * \brief Computes node coordinates by spacing functions
+ * \brief Compute node coordinates by spacing functions
* \param x0 - lower coordinate
* \param x1 - upper coordinate
* \param spaceFuns - space functions
{
};
+ /*!
+ * StdMeshers_PolyhedronPerSolid_3D: interface of "Polyhedron Per Solid" 3D algorithm
+ */
+ interface StdMeshers_PolyhedronPerSolid_3D : SMESH::SMESH_3D_Algo
+ {
+ };
+
/*!
* StdMeshers_Hexa_3D: interface of "Hexahedron (i,j,k)" algorithm
*/
};
typedef sequence<ComputeError> compute_error_array;
+ /*!
+ * Way to initialize hypothesis
+ */
+ struct HypInitParams
+ {
+ short way; // 0 - by mesh, 1 - by geometry size + prefered parameters, 2 - by averageLength
+ double averageLength;
+ boolean quadDominated;
+ };
interface SMESH_Gen : Engines::EngineComponent, SALOMEDS::Driver
{
in string theLibName )
raises ( SALOME::SALOME_Exception );
+ /*!
+ * Create a hypothesis and initialize it by average length
+ */
+ SMESH_Hypothesis CreateHypothesisByAverageLength( in string theHypName,
+ in string theLibName,
+ in double theAverageLength,
+ in boolean theQuadDominated)
+ raises ( SALOME::SALOME_Exception );
+
/*!
* Return a hypothesis holding parameter values corresponding either to the mesh
* existing on the given geometry or to size of the geometry.
in string theLibName,
in SMESH_Mesh theMesh,
in GEOM::GEOM_Object theGeom,
- in boolean byMesh)
+ in HypInitParams theWay)
raises ( SALOME::SALOME_Exception );
/*!
#
SET(SMESH_RESOURCES_FILES
+ ModuleMesh.png
+ advanced_mesh_info.png
+ bare_border_face.png
+ bare_border_volume.png
+ copy_mesh.png
+ copy_mesh_with_geom.png
delete.png
+ mesh.png
+ mesh_0D_elem.png
+ mesh_0D_on_all_nodes.png
+ mesh_2d_from_3d.png
+ mesh_add.png
mesh_add_sub.png
mesh_algo_hexa.png
mesh_algo_mefisto.png
mesh_algo_regular.png
mesh_algo_tetra.png
mesh_angle.png
+ mesh_angle_measure.png
mesh_area.png
mesh_aspect.png
mesh_aspect_3d.png
+ mesh_ball.png
mesh_biquad_quadrangle.png
mesh_biquad_triangle.png
+ mesh_bounding_box.png
+ mesh_build_compound.png
mesh_choose.png
mesh_choose_all.png
mesh_clear.png
mesh_compute.png
- mesh_evaluate.png
- mesh_order.png
+ mesh_conv_to_quad.png
+ mesh_cutGroups.png
+ mesh_cutquad.png
+ mesh_deflection.png
+ mesh_deleteGroups.png
mesh_diagonal.png
+ mesh_duplicate_elem_only.png
+ mesh_duplicate_group_boundary.png
+ mesh_duplicate_nodes.png
+ mesh_duplicate_nodes_with_elem.png
mesh_edit.png
- mesh_hexa.png
- mesh_hypo_area.png
- mesh_hypo_length.png
- mesh_hypo_segment.png
- mesh_hypo_volume.png
- mesh_hypo_edit.png
- mesh_plus.png
- mesh_minus.png
- mesh_info.png
- advanced_mesh_info.png
- standard_mesh_info.png
+ mesh_edit_group.png
mesh_elem_info.png
mesh_equal_edge.png
mesh_equal_face.png
mesh_equal_node.png
mesh_equal_volume.png
- mesh_whatis.png
- mesh_init.png
- mesh_length.png
- mesh_length_2d.png
+ mesh_evaluate.png
+ mesh_extmeth_face_offset.png
+ mesh_extmeth_node_offset.png
+ mesh_extmeth_surf_offset_smooth.png
+ mesh_extractGroup.png
+ mesh_extrusion.png
+ mesh_extrusionpath.png
+ mesh_face_groups_by_edges.png
mesh_find_elem_by_point.png
mesh_free_edges.png
mesh_free_edges_2d.png
+ mesh_free_faces.png
mesh_free_nodes.png
+ mesh_group.png
+ mesh_groups_from_gemetry.png
+ mesh_hexa.png
+ mesh_hide.png
+ mesh_hypo_area.png
+ mesh_hypo_edit.png
+ mesh_hypo_layer_distribution.png
+ mesh_hypo_length.png
+ mesh_hypo_segment.png
+ mesh_hypo_source_3d.png
+ mesh_hypo_source_edge.png
+ mesh_hypo_source_face.png
+ mesh_hypo_viscous_layers.png
+ mesh_hypo_volume.png
+ mesh_info.png
+ mesh_init.png
+ mesh_intersectGroups.png
+ mesh_length.png
+ mesh_length_2d.png
+ mesh_line.png
+ mesh_line_n.png
+ mesh_make_group.png
mesh_max_element_length_2d.png
mesh_max_element_length_3d.png
- mesh_multi_edges.png
- mesh_multi_edges_2d.png
- mesh_line_n.png
- mesh_line.png
+ mesh_measure_area.png
+ mesh_measure_basic_props.png
+ mesh_measure_length.png
+ mesh_measure_volume.png
+ mesh_merge_elements.png
+ mesh_merge_nodes.png
+ mesh_min_dist.png
+ mesh_minus.png
mesh_move_node.png
mesh_move_without_node.png
+ mesh_multi_edges.png
+ mesh_multi_edges_2d.png
+ mesh_node_to_point.png
mesh_octahedron.png
+ mesh_offset.png
+ mesh_order.png
mesh_orientation.png
- mesh.png
+ mesh_pattern.png
+ mesh_pentahedron.png
mesh_plugins_meshcut.png
+ mesh_plus.png
+ mesh_points.png
mesh_polygon.png
mesh_polyhedron.png
- mesh_pyramid_n.png
+ mesh_precompute.png
mesh_pyramid.png
- mesh_quad_n.png
+ mesh_pyramid_n.png
mesh_quad.png
+ mesh_quad_edge.png
+ mesh_quad_hexahedron.png
+ mesh_quad_n.png
+ mesh_quad_pentahedron.png
+ mesh_quad_polygon.png
+ mesh_quad_pyramid.png
+ mesh_quad_quadrangle.png
+ mesh_quad_tetrahedron.png
+ mesh_quad_triangle.png
mesh_quadrangle_quadpref.png
mesh_quadrangle_quadpref_reversed.png
mesh_quadrangle_reduced.png
mesh_quadrangle_standard.png
mesh_quadrangle_triapref.png
+ mesh_quality.png
mesh_rem_element.png
mesh_rem_node.png
mesh_rem_orphan_nodes.png
+ mesh_remove.png
+ mesh_renumbering_elements.png
+ mesh_renumbering_nodes.png
+ mesh_revolution.png
+ mesh_rotation.png
+ mesh_sew_bordertoside.png
+ mesh_sew_conform_freeborders.png
+ mesh_sew_freeborders.png
+ mesh_sew_sideelements.png
mesh_shading.png
+ mesh_show.png
mesh_shrink.png
mesh_skew.png
+ mesh_smoothing.png
+ mesh_symmetry_axis.png
+ mesh_symmetry_plane.png
+ mesh_symmetry_point.png
mesh_taper.png
mesh_tetra.png
+ mesh_translation_points.png
+ mesh_translation_vector.png
+ mesh_tree_algo.png
+ mesh_tree_algo_0D.png
+ mesh_tree_algo_existing_2D.png
mesh_tree_algo_hexa.png
mesh_tree_algo_mefisto.png
mesh_tree_algo_polygon.png
- mesh_tree_algo.png
- mesh_tree_algo_0D.png
+ mesh_tree_algo_prism.png
+ mesh_tree_algo_projection_2d.png
mesh_tree_algo_quad.png
+ mesh_tree_algo_radial_prism.png
+ mesh_tree_algo_radial_quadrangle_1D2D.png
mesh_tree_algo_regular.png
mesh_tree_algo_tetra.png
+ mesh_tree_group.png
+ mesh_tree_group_on_filter.png
+ mesh_tree_hypo.png
mesh_tree_hypo_area.png
+ mesh_tree_hypo_cartesian.png
+ mesh_tree_hypo_import_source_1d.png
+ mesh_tree_hypo_import_source_2d.png
+ mesh_tree_hypo_layers_distribution.png
+ mesh_tree_hypo_layers_distribution_2d.png
mesh_tree_hypo_length.png
- mesh_tree_hypo.png
+ mesh_tree_hypo_projection_2d.png
+ mesh_tree_hypo_projection_3d.png
+ mesh_tree_hypo_quadratic.png
mesh_tree_hypo_segment.png
+ mesh_tree_hypo_source_3d_shape.png
+ mesh_tree_hypo_source_edge.png
+ mesh_tree_hypo_source_face.png
+ mesh_tree_hypo_viscous_layers.png
mesh_tree_hypo_volume.png
- mesh_tree_hypo_cartesian.png
- mesh_tree_mesh.png
mesh_tree_importedmesh.png
- mesh_tree_mesh_warn.png
+ mesh_tree_mesh.png
mesh_tree_mesh_geom_modif.png
+ mesh_tree_mesh_partial.png
+ mesh_tree_mesh_warn.png
+ mesh_triangle.png
mesh_triangle_n.png
mesh_triquad_hexahedron.png
- mesh_triangle.png
+ mesh_union2tri.png
+ mesh_unionGroups.png
+ mesh_uniontri.png
mesh_update.png
- mesh_vertex_n.png
mesh_vertex.png
- mesh_0D_elem.png
- mesh_0D_on_all_nodes.png
+ mesh_vertex_n.png
mesh_volume_3d.png
- bare_border_volume.png
- bare_border_face.png
- over_constrained_volume.png
- over_constrained_face.png
+ mesh_whatis.png
mesh_wireframe.png
- mesh_points.png
mesh_wrap.png
- mesh_group.png
- mesh_tree_group.png
- mesh_tree_group_on_filter.png
- mesh_edit_group.png
- mesh_make_group.png
- mesh_groups_from_gemetry.png
- mesh_union2tri.png
- mesh_uniontri.png
- mesh_cutquad.png
- mesh_smoothing.png
- mesh_renumbering_nodes.png
- mesh_renumbering_elements.png
- mesh_extrusion.png
- mesh_extrusionpath.png
- mesh_revolution.png
- ModuleMesh.png
- mesh_unionGroups.png
- mesh_intersectGroups.png
- mesh_cutGroups.png
- mesh_deleteGroups.png
- mesh_translation_vector.png
- mesh_translation_points.png
- mesh_rotation.png
- mesh_symmetry_point.png
- mesh_symmetry_axis.png
- mesh_symmetry_plane.png
- mesh_sew_freeborders.png
- mesh_sew_conform_freeborders.png
- mesh_sew_bordertoside.png
- mesh_sew_sideelements.png
- mesh_merge_nodes.png
- mesh_merge_elements.png
- select1.png
open.png
- mesh_pattern.png
- mesh_pentahedron.png
+ over_constrained_face.png
+ over_constrained_volume.png
pattern_sample_2d.png
pattern_sample_3D.png
- mesh_add.png
- mesh_remove.png
- mesh_quad_edge.png
- mesh_quad_triangle.png
- mesh_quad_quadrangle.png
- mesh_quad_polygon.png
- mesh_quad_tetrahedron.png
- mesh_quad_pyramid.png
- mesh_quad_pentahedron.png
- mesh_quad_hexahedron.png
- mesh_conv_to_quad.png
- mesh_tree_hypo_layers_distribution.png
- mesh_tree_algo_radial_prism.png
- mesh_tree_algo_radial_quadrangle_1D2D.png
- mesh_tree_algo_existing_2D.png
- mesh_tree_algo_prism.png
- mesh_tree_algo_projection_2d.png
- mesh_hypo_source_edge.png
- mesh_hypo_source_3d.png
- mesh_hypo_layer_distribution.png
- mesh_hypo_source_face.png
- mesh_tree_hypo_source_face.png
- mesh_tree_hypo_source_edge.png
- mesh_tree_hypo_source_3d_shape.png
- mesh_tree_hypo_projection_3d.png
- mesh_tree_hypo_projection_2d.png
- mesh_tree_hypo_quadratic.png
- mesh_build_compound.png
- copy_mesh.png
- copy_mesh_with_geom.png
- mesh_node_to_point.png
- mesh_tree_mesh_partial.png
- mesh_extractGroup.png
- mesh_precompute.png
- mesh_2d_from_3d.png
- mesh_free_faces.png
+ reorient_faces_face.png
+ reorient_faces_point.png
+ reorient_faces_volume.png
scale.png
scale_along_axes.png
- split_into_tetra.png
+ select1.png
split_biquad.png
- mesh_duplicate_nodes.png
- mesh_duplicate_nodes_with_elem.png
- mesh_duplicate_elem_only.png
- mesh_duplicate_group_boundary.png
- mesh_bounding_box.png
- mesh_hypo_viscous_layers.png
- mesh_tree_hypo_viscous_layers.png
- mesh_min_dist.png
- reorient_faces_point.png
- reorient_faces_face.png
- reorient_faces_volume.png
- mesh_ball.png
- mesh_measure_basic_props.png
- mesh_measure_length.png
- mesh_measure_area.png
- mesh_measure_volume.png
- mesh_extmeth_node_offset.png
- mesh_extmeth_surf_offset_smooth.png
- mesh_extmeth_face_offset.png
- mesh_quality.png
- mesh_show.png
- mesh_hide.png
- mesh_deflection.png
- mesh_offset.png
- mesh_face_groups_by_edges.png
- mesh_angle_measure.png
+ split_into_tetra.png
+ standard_mesh_info.png
)
INSTALL(FILES ${SMESH_RESOURCES_FILES} DESTINATION ${SALOME_SMESH_INSTALL_RES_DATA})
<parameter name="info_dump_ctrl" value="true" />
<parameter name="segmentation" value="10"/>
<parameter name="nb_segments_per_edge" value="15"/>
+ <parameter name="use-meshgems-hypo-sets" value="@SMESH_USE_MESHGEMS_HYPOSET_VAR@"/>
<parameter name="forget_mesh_on_hyp_modif" value="true"/>
<parameter name="quadratic_mode" value="0"/>
<parameter name="max_angle" value="2"/>
<hypothesis type ="CartesianParameters3D"
label-id ="Body Fitting Parameters"
icon-id ="mesh_hypo_length.png"
- context ="GLOBAL"
dim ="3"/>
</hypotheses>
<algo>MEFISTO_2D=Triangle(algo=smeshBuilder.MEFISTO)</algo>
<hypo>LengthFromEdges=LengthFromEdges()</hypo>
<hypo>MaxElementArea=MaxElementArea(SetMaxElementArea())</hypo>
- <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetEdges(1),SetEdges(2))</hypo>
+ <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetEdges(1),SetEdges(2),SetGroupName())</hypo>
</python-wrap>
</algorithm>
<python-wrap>
<algo>Quadrangle_2D=Quadrangle(algo=smeshBuilder.QUADRANGLE)</algo>
<hypo>QuadrangleParams=QuadrangleParameters(SetQuadType(),SetTriaVertex(),SetEnforcedNodes(1),SetEnforcedNodes(2),SetCorners())</hypo>
- <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
+ <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetEdges(1),SetEdges(2),SetGroupName())</hypo>
</python-wrap>
</algorithm>
dim ="2">
<python-wrap>
<algo>QuadFromMedialAxis_1D2D=Quadrangle(algo=smeshBuilder.QUAD_MA_PROJ)</algo>
- <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
+ <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetEdges(1),SetEdges(2),SetGroupName())</hypo>
<hypo>NumberOfLayers2D=NumberOfLayers(SetNumberOfLayers())</hypo>
</python-wrap>
</algorithm>
dim ="2">
<python-wrap>
<algo>PolygonPerFace_2D=Polygon()</algo>
- <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
+ <hypo>ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetEdges(1),SetEdges(2),SetGroupName())</hypo>
+ </python-wrap>
+ </algorithm>
+
+ <algorithm type ="PolyhedronPerSolid_3D"
+ label-id ="Polyhedron per Solid"
+ icon-id ="mesh_algo_polygon.png"
+ opt-hypos="ViscousLayers"
+ input ="POLYGON,QUAD,TRIA,EDGE"
+ dim ="3">
+ <python-wrap>
+ <algo>PolyhedronPerSolid_3D=Polyhedron()</algo>
+ <hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())</hypo>
</python-wrap>
</algorithm>
dim ="3">
<python-wrap>
<algo>Hexa_3D=Hexahedron(algo=smeshBuilder.Hexa)</algo>
- <hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod())</hypo>
+ <hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod(),SetGroupName())</hypo>
</python-wrap>
</algorithm>
support-submeshes="false"
output ="HEXA"
need-hyp ="true"
- context ="GLOBAL"
dim ="3">
<python-wrap>
<algo>Cartesian_3D=BodyFitted()</algo>
<hypotheses-set-group>
- <hypotheses-set name="Automatic Tetrahedralization"
- hypos="MaxLength"
- algos="Regular_1D, @MEFISTO2D_NAME@, NETGEN_3D"/>
+ <hypotheses-set name="Tetrahedralization"
+ use-common-size="true"
+ hypos="MG-CADSurf Parameters"
+ algos="MG-CADSurf, MG-Tetra"
+ alt-hypos="NETGEN_Parameters"
+ alt-algos="NETGEN_2D3D"
+ intern-edge-hypos="LocalLength"
+ intern-edge-algos="Regular_1D"/>
- <hypotheses-set name="Automatic Hexahedralization"
+ <hypotheses-set name="Mapped Hexahedralization"
hypos="NumberOfSegments"
algos="Regular_1D, Quadrangle_2D, Hexa_3D"/>
- <hypotheses-set name="Automatic Triangulation"
- hypos="MaxLength"
- algos="Regular_1D, @MEFISTO2D_NAME@"/>
-
- <hypotheses-set name="Automatic Quadrangulation"
+ <hypotheses-set name="Free Hexahedralization"
+ use-common-size="true"
+ quad-dominated="true"
+ hypos="MG-CADSurf Parameters"
+ algos="MG-CADSurf, MG-Hexa"
+ alt-hypos="None"
+ alt-algos="None"
+ intern-edge-hypos="LocalLength"
+ intern-edge-algos="Regular_1D"/>
+
+ <hypotheses-set name="Triangulation"
+ use-common-size="true"
+ hypos="MG-CADSurf Parameters"
+ algos="MG-CADSurf"
+ alt-hypos="NETGEN_Parameters_2D"
+ alt-algos="NETGEN_2D"/>
+
+ <hypotheses-set name="Mapped Quadrangulation"
hypos="NumberOfSegments"
algos="Regular_1D, Quadrangle_2D"/>
+ <hypotheses-set name="Free Quadrangulation"
+ use-common-size="true"
+ quad-dominated="true"
+ hypos="MG-CADSurf Parameters"
+ algos="MG-CADSurf"
+ alt-hypos="NETGEN_Parameters_2D"
+ alt-algos="NETGEN_2D"/>
+
</hypotheses-set-group>
</meshers>
// Case 1 Case 2
// | | | | |
// | | | | |
- // +-----+------+ +-----+------+
+ // +-----+------+ +-----+------+
// | | | |
// | | | |
// result should be 2 in both cases
//
int aResult0 = 0, aResult1 = 0;
- // last node, it is a medium one in a quadratic edge
+ // last node, it is a medium one in a quadratic edge
const SMDS_MeshNode* aLastNode = anEdge->GetNode( anEdge->NbNodes() - 1 );
const SMDS_MeshNode* aNode0 = anEdge->GetNode( 0 );
const SMDS_MeshNode* aNode1 = anEdge->GetNode( 1 );
// }
// }
// { // polygons
-
+
// }
if( myPrecision >= 0 )
{
double aVal = 0;
myCurrElement = myMesh->FindElement( theId );
- if ( myCurrElement && myCurrElement->GetVtkType() == VTK_QUAD )
- {
- // issue 21723
- vtkUnstructuredGrid* grid = const_cast<SMDS_Mesh*>( myMesh )->GetGrid();
- if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() ))
- aVal = Round( vtkMeshQuality::QuadAspectRatio( avtkCell ));
- }
- else
- {
- TSequenceOfXYZ P;
- if ( GetPoints( myCurrElement, P ))
- aVal = Round( GetValue( P ));
- }
+ TSequenceOfXYZ P;
+ if ( GetPoints( myCurrElement, P ))
+ aVal = Round( GetValue( P ));
return aVal;
}
//
// alpha = sqrt( 1/32 )
// L = max( L1, L2, L3, L4, D1, D2 )
- // C1 = sqrt( ( L1^2 + L1^2 + L1^2 + L1^2 ) / 4 )
+ // C1 = sqrt( L1^2 + L1^2 + L1^2 + L1^2 )
// C2 = min( S1, S2, S3, S4 )
// Li - lengths of the edges
// Di - lengths of the diagonals
Max( aLen[ 2 ],
Max( aLen[ 3 ],
Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) );
- double C1 = sqrt( ( aLen[0] * aLen[0] +
- aLen[1] * aLen[1] +
- aLen[2] * aLen[2] +
- aLen[3] * aLen[3] ) / 4. );
+ double C1 = sqrt( aLen[0] * aLen[0] +
+ aLen[1] * aLen[1] +
+ aLen[2] * aLen[2] +
+ aLen[3] * aLen[3] );
double C2 = Min( anArea[ 0 ],
Min( anArea[ 1 ],
Min( anArea[ 2 ], anArea[ 3 ] ) ) );
//
// alpha = sqrt( 1/32 )
// L = max( L1, L2, L3, L4, D1, D2 )
- // C1 = sqrt( ( L1^2 + L1^2 + L1^2 + L1^2 ) / 4 )
+ // C1 = sqrt( L1^2 + L1^2 + L1^2 + L1^2 )
// C2 = min( S1, S2, S3, S4 )
// Li - lengths of the edges
// Di - lengths of the diagonals
// Si - areas of the triangles
const double alpha = sqrt( 1 / 32. );
double L = Max( aLen[ 0 ],
- Max( aLen[ 1 ],
- Max( aLen[ 2 ],
- Max( aLen[ 3 ],
- Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) );
- double C1 = sqrt( ( aLen[0] * aLen[0] +
- aLen[1] * aLen[1] +
- aLen[2] * aLen[2] +
- aLen[3] * aLen[3] ) / 4. );
+ Max( aLen[ 1 ],
+ Max( aLen[ 2 ],
+ Max( aLen[ 3 ],
+ Max( aDia[ 0 ], aDia[ 1 ] ) ) ) ) );
+ double C1 = sqrt( aLen[0] * aLen[0] +
+ aLen[1] * aLen[1] +
+ aLen[2] * aLen[2] +
+ aLen[3] * aLen[3] );
double C2 = Min( anArea[ 0 ],
- Min( anArea[ 1 ],
- Min( anArea[ 2 ], anArea[ 3 ] ) ) );
+ Min( anArea[ 1 ],
+ Min( anArea[ 2 ], anArea[ 3 ] ) ) );
if ( C2 <= theEps )
return theInf;
return alpha * L * C1 / C2;
SMDS_MeshElement* aVol = (SMDS_MeshElement*)volItr->next();
TItrMapOfVolume itr = mapOfVol.insert( std::make_pair( aVol, 0 )).first;
(*itr).second++;
- }
+ }
}
int nbVol = 0;
TItrMapOfVolume volItr = mapOfVol.begin();
TItrMapOfVolume volEnd = mapOfVol.end();
for ( ; volItr != volEnd; ++volItr )
if ( (*volItr).second >= nbNode )
- nbVol++;
+ nbVol++;
// face is not free if number of volumes constructed on their nodes more than one
return (nbVol < 2);
}
double dot = v1 * v2; // cos * |v1| * |v2|
double l1 = v1.SquareMagnitude();
double l2 = v2.SquareMagnitude();
- return (( dot * cos >= 0 ) &&
+ return (( dot * cos >= 0 ) &&
( dot * dot ) / l1 / l2 >= ( cos * cos ));
}
}
bool isOutOfFace (const gp_Pnt& p);
bool isOutOfEdge (const gp_Pnt& p);
bool isOutOfVertex(const gp_Pnt& p);
+ bool isOutOfNone (const gp_Pnt& p) { return true; }
bool isBox (const TopoDS_Shape& s);
bool (Classifier::* myIsOutFun)(const gp_Pnt& p);
{
isNodeOut = false;
if ( okShape )
- *okShape = myWorkClassifiers[i]->Shape();
+ *okShape = myClassifiers[i].Shape();
break;
}
}
{
Standard_Real u1,u2,v1,v2;
Handle(Geom_Surface) surf = BRep_Tool::Surface( TopoDS::Face( theShape ));
- surf->Bounds( u1,u2,v1,v2 );
- myProjFace.Init(surf, u1,u2, v1,v2, myTol );
- myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace;
+ if ( surf.IsNull() )
+ myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone;
+ else
+ {
+ surf->Bounds( u1,u2,v1,v2 );
+ myProjFace.Init(surf, u1,u2, v1,v2, myTol );
+ myIsOutFun = & ElementsOnShape::Classifier::isOutOfFace;
+ }
break;
}
case TopAbs_EDGE:
{
Standard_Real u1, u2;
Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge( theShape ), u1, u2);
- myProjEdge.Init(curve, u1, u2);
- myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge;
+ if ( curve.IsNull() )
+ myIsOutFun = & ElementsOnShape::Classifier::isOutOfNone;
+ else
+ {
+ myProjEdge.Init(curve, u1, u2);
+ myIsOutFun = & ElementsOnShape::Classifier::isOutOfEdge;
+ }
break;
}
case TopAbs_VERTEX:
}
#endif
if ( !anIsNodeNum )
- aNodeIds.swap( *(aBallInfo->myConn ));
+ aNodeIds.assign( aBallInfo->myConn->begin(), aBallInfo->myConn->end());
// allocate array of diameters
vtkIdType maxID = myMesh->MaxElementID() + aNbBalls;
#include "SMDS_MeshNode.hxx"
#include "SMDS_SetIterator.hxx"
#include "SMESHDS_Mesh.hxx"
+#include "MED_Common.hxx"
#include <med.h>
#include "SMESH_DriverMED.hxx"
#include "Driver_SMESHDS_Mesh.h"
-#include "MED_Common.hxx"
+//#include "MED_Common.hxx"
#include <string>
#include <list>
#include <set>
#include <map>
-#include <hdf5.h>
+#include <med.h>
#ifdef WIN32
#pragma warning(disable:4099)
{
typedef enum {eFAUX, eVRAI} EBooleen;
typedef double TFloat;
-#if defined(HAVE_F77INT64)
- typedef long TInt;
-#else
- typedef int TInt;
-#endif
+// #if defined(HAVE_F77INT64)
+// typedef long TInt;
+// #else
+// typedef int TInt;
+// #endif
+ typedef med_int TInt;
typedef hid_t TIdt;
typedef herr_t TErr;
{
friend std::ostream& operator <<(std::ostream& f, const R4 & P )
{ f << P.x << ' ' << P.y << ' ' << P.z << ' ' << P.omega; return f; }
- friend istream& operator >>(istream& f, R4 & P)
+ friend std::istream& operator >>(std::istream& f, R4 & P)
{ f >> P.x >> P.y >> P.z >> P.omega ; return f; }
friend std::ostream& operator <<(std::ostream& f, const R4 * P )
{ f << P->x << ' ' << P->y << ' ' << P->z << ' ' << P->omega; return f; }
- friend istream& operator >>(istream& f, R4 * P)
+ friend std::istream& operator >>(std::istream& f, R4 * P)
{ f >> P->x >> P->y >> P->z >> P->omega ; return f; }
public:
#include <VTKViewer_CellCenters.h>
+#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkDataSet.h>
-#include <vtkPolyData.h>
-#include <vtkObjectFactory.h>
-#include <vtkInformation.h>
-#include <vtkInformationVector.h>
-
#include <vtkFloatArray.h>
-#include <vtkCellArray.h>
-#include <vtkMaskPoints.h>
#include <vtkGlyph3D.h>
#include <vtkGlyphSource2D.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkMaskPoints.h>
+#include <vtkObjectFactory.h>
+#include <vtkPolyData.h>
+#include <vtkPolygon.h>
#include <QColor>
vtkPoints* aPoints = theFace->GetPoints();
// here we get first 3 points from the face and calculate the normal as a cross-product of vectors
- double x0 = aPoints->GetPoint(0)[0], y0 = aPoints->GetPoint(0)[1], z0 = aPoints->GetPoint(0)[2];
- double x1 = aPoints->GetPoint(1)[0], y1 = aPoints->GetPoint(1)[1], z1 = aPoints->GetPoint(1)[2];
- double x2 = aPoints->GetPoint(2)[0], y2 = aPoints->GetPoint(2)[1], z2 = aPoints->GetPoint(2)[2];
+ // double x0 = aPoints->GetPoint(0)[0], y0 = aPoints->GetPoint(0)[1], z0 = aPoints->GetPoint(0)[2];
+ // double x1 = aPoints->GetPoint(1)[0], y1 = aPoints->GetPoint(1)[1], z1 = aPoints->GetPoint(1)[2];
+ // double x2 = aPoints->GetPoint(2)[0], y2 = aPoints->GetPoint(2)[1], z2 = aPoints->GetPoint(2)[2];
+
+ // theNormal[0] = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
+ // theNormal[1] = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
+ // theNormal[2] = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
- theNormal[0] = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
- theNormal[1] = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
- theNormal[2] = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
+ // issue #18665: Polyhedron volume calculation
+ vtkPolygon::ComputeNormal( aPoints, theNormal );
double* aBounds = theFace->GetBounds();
theSize = pow( pow( aBounds[1] - aBounds[0], 2 ) +
void SMDS_BallElement::init(const SMDS_MeshNode * node, double diameter )
{
- int nodeVtkID = node->GetVtkID();
+ vtkIdType nodeVtkID = node->GetVtkID();
int vtkID = getGrid()->InsertNextLinkedCell( toVtkType( SMDSEntity_Ball ), 1, &nodeVtkID );
setVtkID( vtkID );
getGrid()->SetBallDiameter( GetVtkID(), diameter );
if ( !myPolyedre )
return 0.;
+ SaveFacet savedFacet( myCurFace );
+
// split a polyhedron into tetrahedrons
- SaveFacet savedFacet( myCurFace );
+ bool oriOk = true;
SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
- XYZ origin( 1 + 1e-6, 22 + 2e-6, 333 + 3e-6 ); // for invalid poly: avoid lying on a facet plane
for ( int f = 0; f < NbFaces(); ++f )
{
me->setFace( f );
area = area + p1.Crossed( p2 );
p1 = p2;
}
- V += ( p1 - origin ).Dot( area );
+ V += p1.Dot( area );
+ oriOk = oriOk && IsFaceExternal( f );
}
V /= 6;
+ if ( !oriOk && V > 0 )
+ V *= -1;
}
else
{
XYZ aVec13( p3 - p1 );
XYZ cross = aVec12.Crossed( aVec13 );
- if ( myCurFace.myNbNodes >3*iQuad ) {
- XYZ p4 ( myCurFace.myNodes[3*iQuad] );
+ for ( int i = 3*iQuad; i < myCurFace.myNbNodes; i += iQuad )
+ {
+ XYZ p4 ( myCurFace.myNodes[i] );
XYZ aVec14( p4 - p1 );
XYZ cross2 = aVec13.Crossed( aVec14 );
cross = cross + cross2;
+ aVec13 = aVec14;
}
double size = cross.Magnitude();
using namespace std;
+// Environment variable separator
+#ifdef WIN32
+ #define env_sep ';'
+#else
+ #define env_sep ':'
+#endif
+
//=============================================================================
/*!
* Constructor
while ( from < meshers.size() )
{
// cut off plugin name
- pos = meshers.find( ':', from );
+ pos = meshers.find( env_sep, from );
if ( pos != string::npos )
plugin = meshers.substr( from, pos-from );
else
*/
virtual bool SetParametersByMesh(const SMESH_Mesh* theMesh, const TopoDS_Shape& theShape)=0;
+ enum InitWay { BY_MESH, BY_GEOM, BY_AVERAGE_LENGTH };
struct TDefaults
{
+ InitWay _way;
double _elemLength;
int _nbSegments;
+ bool _quadDominated;
+ double _diagonal;
TopoDS_Shape* _shape; // future shape of the mesh being created
+
+ TDefaults():
+ _way(BY_GEOM), _elemLength(0),_nbSegments(0),_quadDominated(false),_diagonal(0),_shape(0) {}
};
/*!
* \brief Initialize my parameter values by default parameters.
{
if(MYDEBUG) MESSAGE("SMESH_Mesh::~SMESH_Mesh");
- // avoid usual removal of elements while processing RemoveHypothesis( algo ) event
- SMESHDS_SubMeshIteratorPtr smIt = _myMeshDS->SubMeshes();
- while ( smIt->more() )
- const_cast<SMESHDS_SubMesh*>( smIt->next() )->Clear();
+ if ( _myDocument ) // avoid destructing _myMeshDS from ~SMESH_Gen()
+ _myDocument->RemoveMesh( _id );
+ _myDocument = 0;
+
+ // remove self from studyContext
+ if ( _gen )
+ {
+ StudyContextStruct * studyContext = _gen->GetStudyContext();
+ studyContext->mapMesh.erase( _id );
+ }
+
+ _myMeshDS->ClearMesh();
// issue 0020340: EDF 1022 SMESH : Crash with FindNodeClosestTo in a second new study
// Notify event listeners at least that something happens
if ( _callUp) delete _callUp;
_callUp = 0;
- // remove self from studyContext
- if ( _gen )
- {
- StudyContextStruct * studyContext = _gen->GetStudyContext();
- studyContext->mapMesh.erase( _id );
- }
- if ( _myDocument )
- _myDocument->RemoveMesh( _id );
- _myDocument = 0;
-
if ( _myMeshDS ) {
// delete _myMeshDS, in a thread in order not to block closing a study with large meshes
#ifndef WIN32
if ( !GetMeshDS()->IsUsedHypothesis( hyp ))
return;
- bool toCallBack = true;
- if ( _callUp && hyp && NbNodes() == 0 ) // for not loaded mesh (#16648)
+ int nbEntities = ( _myMeshDS->NbNodes() + _myMeshDS->NbElements() );
+ if ( hyp && _callUp && !_callUp->IsLoaded() ) // for not loaded mesh (#16648)
{
- _callUp->HypothesisModified( hyp->GetID() );
- toCallBack = ( NbNodes() > 0 );
+ _callUp->HypothesisModified( hyp->GetID(), /*updateIcons=*/true );
+ nbEntities = ( _myMeshDS->NbNodes() + _myMeshDS->NbElements() ); // after loading mesh
}
SMESH_Algo *algo;
HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
GetMeshDS()->Modified();
- if ( _callUp && hyp && toCallBack )
- _callUp->HypothesisModified( hyp->GetID() );
+ int newNbEntities = ( _myMeshDS->NbNodes() + _myMeshDS->NbElements() );
+ if ( hyp && _callUp )
+ _callUp->HypothesisModified( hyp->GetID(), newNbEntities != nbEntities );
}
//=============================================================================
#include <map>
#include <list>
#include <vector>
+#include <ostream>
#ifdef WIN32
#pragma warning(disable:4251) // Warning DLL Interface ...
struct TCallUp // callback from SMESH to SMESH_I level
{
- virtual void RemoveGroup (const int theGroupID)=0;
- virtual void HypothesisModified (int theHypID)=0;
- virtual void Load ()=0;
+ virtual void RemoveGroup( const int theGroupID )=0;
+ virtual void HypothesisModified( int hypID, bool updateIcons )=0;
+ virtual void Load()=0;
+ virtual bool IsLoaded()=0;
virtual ~TCallUp() {}
};
void SetCallUp( TCallUp * upCaller );
bool IsOrderOK( const SMESH_subMesh* smBefore,
const SMESH_subMesh* smAfter ) const;
- std::ostream& Dump(ostream & save);
+ std::ostream& Dump(std::ostream & save);
private:
myIsQuad = elem->IsQuadratic();
if ( myType == SMDSAbs_Volume && !basicOnly )
{
- vector<int> quant = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
- myPolyhedQuantities.swap( quant );
+ myPolyhedQuantities = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
}
}
}
set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };
nReplaceMap.clear();
- if ( theFirstNode1 != theFirstNode2 )
- nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
- if ( theSecondNode1 != theSecondNode2 )
- nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
+ //if ( theFirstNode1 != theFirstNode2 )
+ nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
+ //if ( theSecondNode1 != theSecondNode2 )
+ nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
set< SMESH_TLink > linkSet; // set of nodes where order of nodes is ignored
linkSet.insert( SMESH_TLink( theFirstNode1, theSecondNode1 ));
(LOCALIZED("add element in subshape already belonging to a subshape"));
}
}
+ else
+ {
+ ++myNbElements;
+ }
elem->setShapeID( myIndex );
- myNbElements++;
// remember element with smallest ID to optimize iteration on them
add( elem );
(LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
return; // already in
}
+ else
+ {
+ ++myNbNodes;
+ }
N->setShapeID( myIndex );
- myNbNodes++;
// remember node with smallest ID to optimize iteration on them
add( N );
if ( aDesk ) {
QList<SUIT_ViewWindow*> wndList = aDesk->windows();
SUIT_ViewWindow* wnd;
- foreach(wnd, wndList)
+ foreach ( wnd, wndList )
{
- connectView(wnd);
+ connectView( wnd );
// remove actors whose objects are removed in GetSMESHGen()->UpdateStudy()
SMESH::UpdateActorsAfterUpdateStudy(wnd);
"SMESH", "nb_segments_per_edge" );
setPreferenceProperty( nbSeg, "min", 1 );
setPreferenceProperty( nbSeg, "max", 10000000 );
+ addPreference( tr( "PREF_USE_MESHGEMS_HYPOSET" ), segGroup, LightApp_Preferences::Bool, "SMESH", "use-meshgems-hypo-sets" );
int loadGroup = addPreference( tr( "SMESH_PREF_MESH_LOADING" ), genTab );
addPreference( tr( "PREF_FORGET_MESH_AT_HYP_MODIF" ), loadGroup, LightApp_Preferences::Bool,
*/
//================================================================================
-static SMESH::ElementType elementType(GEOM::GEOM_Object_var geom)
+SMESH::ElementType SMESHGUI_GroupOnShapeOp::ElementType(GEOM::GEOM_Object_var geom)
{
if ( !geom->_is_nil() ) {
switch ( geom->GetShapeType() ) {
GEOM::ListOfLong_var ids = aGroupOp->GetObjects( geom );
if ( ids->length() && !mainShape->_is_nil() && !aShapeOp->_is_nil() ) {
GEOM::GEOM_Object_wrap member = aShapeOp->GetSubShape( mainShape, ids[0] );
- return elementType( member );
+ return ElementType( member );
}
}
}
GEOM::ListOfLong_var ids = aShapeOp->SubShapeAllIDs( geom, GEOM::SHAPE, false );
if ( ids->length() ) {
GEOM::GEOM_Object_wrap member = aShapeOp->GetSubShape( geom, ids[0] );
- return elementType( member );
+ return ElementType( member );
}
}
}
if ( geom->_is_nil() ) continue;
// group type
- SMESH::ElementType elemType = isNode ? SMESH::NODE : elementType( geom );
+ SMESH::ElementType elemType = isNode ? SMESH::NODE : ElementType( geom );
if ( elemType == SMESH::ALL )
continue;
virtual LightApp_Dialog* dlg() const;
static QString GetDefaultName(const QString& theOperation);
+ static SMESH::ElementType ElementType(GEOM::GEOM_Object_var geom);
public slots:
#include "SMESHGUI.h"
#include "SMESHGUI_HypothesesUtils.h"
-#include "SMESHGUI_Utils.h"
#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
#include "SMESH_Actor.h"
+#include "SMESH_TypeDefs.hxx"
// SALOME KERNEL includes
#include <SALOMEDSClient_Study.hxx>
Dlg->setWindowTitle( caption() );
Dlg->setObjectName( theHypName );
Dlg->setHIcon( icon() );
- Dlg->setType( type() );
+ if ( theHypName == HypothesesSet::getCommonHypoSetHypoType() )
+ Dlg->setType( tr( HypothesesSet::getCommonHypoSetHypoType()) );
+ else
+ Dlg->setType( type() );
retrieveParams();
- Dlg->show();
+ Dlg->show(); // w/o this Dlg blocks selection
Dlg->resize( Dlg->minimumSizeHint() );
+ Dlg->exec(); // w/o this we cant wait until edition ends when applying a hypo-set
}
else {
emit finished( QDialog::Accepted );
GroupC1Layout->setMargin( MARGIN );
ListOfStdParams::const_iterator anIt = params.begin(), aLast = params.end();
- for( int i=0; anIt!=aLast; anIt++, i++ )
+ for( int i = 0; anIt != aLast; anIt++, i++ )
{
- QLabel* lab = new QLabel( (*anIt).myName, GroupC1 );
- GroupC1Layout->addWidget( lab, i, 0 );
+ QLabel* lab = anIt->hasName() ? new QLabel( anIt->myName, GroupC1 ) : NULL;
+ if ( lab )
+ GroupC1Layout->addWidget( lab, i, 0 );
myParamLabels << lab;
QWidget* w = getCustomWidget( *anIt, GroupC1, i );
default:;
} // switch( (*anIt).myValue.type() )
- if( w )
+ if ( w )
{
- GroupC1Layout->addWidget( w, i, 1 );
+ if ( lab )
+ GroupC1Layout->addWidget( w, i, 1 );
+ else
+ GroupC1Layout->addWidget( w, i, 0, 1, 2 );
changeWidgets().append( w );
}
}
myDlg->close();
//delete myDlg; since WA_DeleteOnClose==true
myDlg = 0;
+
+ SMESH::UpdateActorsAfterUpdateStudy();// remove actors of removed groups (#16522)
if (SVTK_ViewWindow* vf = SMESH::GetCurrentVtkView()) {
vf->Repaint();
}
delete myCreator;
}
+void SMESHGUI_HypothesisDlg::showEvent(QShowEvent *event)
+{
+ // resize( minimumSizeHint() );
+ // adjustSize();
+
+ QtxDialog::showEvent( event );
+}
+
void SMESHGUI_HypothesisDlg::setCustomFrame( QFrame* f )
{
if( f )
{
}
-HypothesesSet::HypothesesSet( const QString& theSetName )
- : myHypoSetName( theSetName ),
- myIsAlgo( false ),
- myIsCustom( false )
-{
-}
-
-HypothesesSet::HypothesesSet( const QString& theSetName,
- const QStringList& theHypoList,
- const QStringList& theAlgoList )
- : myHypoSetName( theSetName ),
- myHypoList( theHypoList ),
- myAlgoList( theAlgoList ),
+// HypothesesSet::HypothesesSet( const QString& theSetName )
+// : myHypoSetName( theSetName ),
+// myIsAlgo( false ),
+// myIsCustom( false )
+// {
+// }
+
+HypothesesSet::HypothesesSet( const QString& theSetName,
+ bool useCommonSize, bool isQuadDominated,
+ const QStringList& mainHypos, const QStringList& mainAlgos,
+ const QStringList& altHypos, const QStringList& altAlgos,
+ const QStringList& intHypos, const QStringList& intAlgos )
+ : myUseCommonSize( useCommonSize ),
+ myQuadDominated( isQuadDominated ),
+ myHypoSetName( theSetName ),
+ myHypoList { mainHypos, altHypos, intHypos },
+ myAlgoList { mainAlgos, altAlgos, intAlgos },
myIsAlgo( false ),
- myIsCustom( false )
+ myIsCustom( false ),
+ myIndex( 0 )
{
+ for ( myHypType = MAIN; myHypType < NB_HYP_TYPES; SMESHUtils::Increment( myHypType ))
+ for ( int isAlgo = myIsAlgo = 0; isAlgo < 2; myIsAlgo = ++isAlgo )
+ {
+ QStringList& hyps = *list();
+ for ( int i = 0; i < hyps.count(); ++i )
+ hyps[ i ] = hyps[ i ].trimmed();
+ }
}
-QStringList* HypothesesSet::list(bool is_algo) const
+QStringList* HypothesesSet::list( bool is_algo, SetType setType) const
{
- return const_cast<QStringList*>( &( is_algo ? myAlgoList : myHypoList ) );
+ return const_cast<QStringList*>( &( is_algo ? myAlgoList[setType] : myHypoList[setType] ));
}
QStringList* HypothesesSet::list() const
{
- return list( myIsAlgo );
+ return list( myIsAlgo, myHypType );
}
QString HypothesesSet::name() const
return myHypoSetName;
}
-void HypothesesSet::set( bool isAlgo, const QStringList& lst )
-{
- *list(isAlgo) = lst;
-}
+// void HypothesesSet::set( bool isAlgo, const QStringList& lst )
+// {
+// *list(isAlgo) = lst;
+// }
-int HypothesesSet::count( bool isAlgo ) const
-{
- return list(isAlgo)->count();
-}
+// int HypothesesSet::count( bool isAlgo, SetType setType ) const
+// {
+// return list(isAlgo,setType)->count();
+// }
-bool HypothesesSet::isAlgo() const
-{
- return myIsAlgo;
-}
+// bool HypothesesSet::isAlgo() const
+// {
+// return myIsAlgo;
+// }
-void HypothesesSet::init( bool isAlgo )
+void HypothesesSet::init( bool isAlgo, SetType setType )
{
+ myHypType = setType;
myIsAlgo = isAlgo;
myIndex = 0;
}
return myIsCustom;
}
+void HypothesesSet::setAlgoAvailable( SetType type, bool isAvailable )
+{
+ if ( MAIN <= type && type < NB_HYP_TYPES )
+ myIsAlgoAvailable[ type ] = isAvailable;
+}
+
+bool HypothesesSet::getAlgoAvailable( SetType type )
+{
+ bool isAva = false;
+ if ( MAIN <= type && type < NB_HYP_TYPES )
+ isAva = myIsAlgoAvailable[ type ];
+ return isAva;
+}
+
+HypothesesSet::SetType HypothesesSet::getPreferredHypType()
+{
+ SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+ int useAltHypos = !resMgr->booleanValue( "SMESH", "use-meshgems-hypo-sets", false );
+ return ( HypothesesSet::SetType ) useAltHypos;
+}
+
int HypothesesSet::maxDim() const
{
HypothesesSet * thisSet = (HypothesesSet*) this;
int dim = -1;
- for ( int isAlgo = 0; isAlgo < 2; ++isAlgo )
- {
- for ( thisSet->init( isAlgo ); thisSet->more(); thisSet->next() )
- if ( HypothesisData* hypData = SMESH::GetHypothesisData( thisSet->current() ))
- for ( int i = 0; i < hypData->Dim.count(); ++i )
- dim = qMax( dim, hypData->Dim[i] );
- }
+ for ( int setType = 0; setType < 2; ++setType )
+ for ( int isAlgo = 0; isAlgo < 2; ++isAlgo )
+ {
+ for ( thisSet->init( isAlgo, SetType( setType )); thisSet->more(); thisSet->next() )
+ if ( HypothesisData* hypData = SMESH::GetHypothesisData( thisSet->current() ))
+ for ( int i = 0; i < hypData->Dim.count(); ++i )
+ dim = qMax( dim, hypData->Dim[i] );
+ }
return dim;
}
+
+const char* HypothesesSet::getCommonHypoSetHypoType()
+{
+ return "AverageLengthForHypoSet";
+}
const char* text() const {
((QByteArray&) myTextAsBytes) = myText.toUtf8(); return myTextAsBytes.constData();
}
+ void setNoName() { myName.clear(); } // ==> widget occupies both columns
+ bool hasName() const { return !myName.isEmpty(); }
};
typedef QList<StdParam> ListOfStdParams;
void setHIcon( const QPixmap& );
void setCustomFrame( QFrame* );
void setType( const QString& );
+ void showEvent(QShowEvent *event);
protected slots:
virtual void accept();
class HypothesesSet
{
public:
- HypothesesSet( const QString& );
- HypothesesSet( const QString&, const QStringList&, const QStringList& );
+
+ enum SetType { MAIN, ALT, INTERN, NB_HYP_TYPES }; //!< hypos/algos type: main, alternative, internal-edges
+
+ //HypothesesSet( const QString& );
+ HypothesesSet( const QString& name,
+ bool useCommonSize, bool isQuadDominated,
+ const QStringList& mainHypos, const QStringList& mainAlgos,
+ const QStringList& altHypos, const QStringList& altAlgos,
+ const QStringList& intHypos, const QStringList& intAlgos );
QString name() const;
- void set( bool, const QStringList& );
- int count( bool ) const;
+ bool toUseCommonSize() const { return myUseCommonSize; }
+ bool isQuadDominated() const { return myQuadDominated; }
+ bool hasAlgo( SetType type ) const { return !myAlgoList[ type ].isEmpty(); }
+ //int count( bool, SetType ) const;
+
+ int maxDim() const;
void setIsCustom( bool );
bool getIsCustom() const;
- int maxDim() const;
- bool isAlgo() const;
+ void setAlgoAvailable( SetType type, bool isAvailable );
+ bool getAlgoAvailable( SetType type );
+
+ static SetType getPreferredHypType();
+ static const char* getCommonHypoSetHypoType();
+
+ //bool isAlgo() const;
// CASCADE-like iteration
- void init( bool );
+ void init( bool, SetType );
bool more() const;
void next();
QString current() const;
private:
- QStringList* list(bool) const;
+ QStringList* list(bool,SetType) const;
QStringList* list() const;
private:
+ bool myUseCommonSize; // Average size is asked only and used to create default hypotheses
+ bool myQuadDominated;
QString myHypoSetName;
- QStringList myHypoList, myAlgoList;
+ QStringList myHypoList[3], myAlgoList[3]; // per SetType
+ bool myIsAlgoAvailable[3]; // current state depending on geometry etc
+
+ // iteration
+ SetType myHypType;
bool myIsAlgo, myIsCustom;
int myIndex;
};
#define LoadLib( name ) LoadLibrary( name )
#define GetProc GetProcAddress
#define UnLoadLib( handle ) FreeLibrary( handle );
+ #define env_sep ";"
#else // WIN32
#define LibHandle void*
#ifdef DYNLOAD_LOCAL
#endif // DYNLOAD_LOCAL
#define GetProc dlsym
#define UnLoadLib( handle ) dlclose( handle );
+ #define env_sep ":"
#endif // WIN32
#ifdef _DEBUG_
if (cenv)
HypsXml.sprintf("%s", cenv);
- QStringList HypsXmlList = HypsXml.split(":", QString::SkipEmptyParts);
+ QStringList HypsXmlList = HypsXml.split(env_sep, QString::SkipEmptyParts);
if (HypsXmlList.count() == 0) {
SUIT_MessageBox::critical(SMESHGUI::desktop(),
QObject::tr("SMESH_WRN_WARNING"),
hypoSet != myListOfHypothesesSets.end();
++hypoSet ) {
HypothesesSet* aSet = *hypoSet;
- if ( aSet && ( aSet->count( true ) || aSet->count( false )) &&
- aSet->maxDim() <= maxDim)
+ if ( aSet && 0 <= aSet->maxDim() && aSet->maxDim() <= maxDim )
{
aSetNameList.append( mangledHypoSetName( aSet ));
}
SMESH::SMESH_Hypothesis_ptr );
typedef std::vector<_PTR(SObject)> SObjectList;
+ SMESHGUI_EXPORT
SObjectList GetMeshesUsingAlgoOrHypothesis( SMESH::SMESH_Hypothesis_ptr );
SMESHGUI_EXPORT
#include <QtxToolButton.h>
// Qt includes
+#include <QCheckBox>
#include <QComboBox>
#include <QCursor>
#include <QGridLayout>
// mesh type
QLabel* anMeshTypeLbl = new QLabel( tr( "MESH_TYPE" ), this );
myMeshType = new QComboBox( this );
-
+ // groups
+ myCreateGroupsCheck = new QCheckBox( tr( "CREATE_ALL_GROUPS" ), this );
+ myCreateGroupsCheck->setChecked( true );
+
// Create tab widget
-
+
myTabWg = new QTabWidget( mainFrame() );
myTabs[ Dim0D ] = new SMESHGUI_MeshTab( myTabWg );
myTabs[ Dim1D ] = new SMESHGUI_MeshTab( myTabWg );
aLay->addWidget( objectWg( Geom, Control ), 2, 2 );
aLay->addWidget( anMeshTypeLbl, 3, 0 );
aLay->addWidget( myMeshType, 3, 2 );
- aLay->addWidget( myTabWg, 5, 0, 1, 3 );
- aLay->addWidget( myHypoSetButton, 6, 0, 1, 3 );
- aLay->setRowMinimumHeight( 3, 20 );
+ aLay->addWidget( myCreateGroupsCheck, 4, 0, 1, 3 );
+ aLay->addWidget( myTabWg, 6, 0, 1, 3 );
+ aLay->addWidget( myHypoSetButton, 7, 0, 1, 3 );
+ aLay->setRowMinimumHeight( 4, 20 );
myMeshType->clear();
{
setWindowTitle( tr( theIsMesh ? "EDIT_MESH" : "EDIT_SUBMESH") );
}
-
+ myCreateGroupsCheck-> setVisible( theToCreate && theIsMesh );
}
//================================================================================
myHypoSetButton->setPopupMode( QToolButton::InstantPopup );
}
aHypoSetPopup->clear();
- for ( int i = 0, n = theSets.count(); i < n; i++ ) {
- aHypoSetPopup->addAction( theSets[ i ] );
+ for ( int i = 0, n = theSets.count(); i < n; i++ )
+ {
+ QAction* action = new QAction( tr( theSets[ i ].toUtf8().data() ));
+ action->setData( theSets[ i ] );
+ aHypoSetPopup->addAction( action );
}
myHypoSetButton->setEnabled( !aHypoSetPopup->isEmpty() );
}
//================================================================================
void SMESHGUI_MeshDlg::onHypoSetPopup( QAction* a )
{
- emit hypoSet( a->text() );
+ emit hypoSet( a->data().toString() );
}
//================================================================================
else
myMeshType->setCurrentIndex( 0 );
}
+
+//================================================================================
+/*!
+ * \brief Return state of "Create all Groups on Geometry" check-box
+ */
+//================================================================================
+
+bool SMESHGUI_MeshDlg::toCreateAllGroups()
+{
+ return myCreateGroupsCheck->isChecked();
+}
#include <QStringList>
#include <QMap>
-class SMESHGUI_MeshTab;
class QAction;
+class QCheckBox;
class QComboBox;
class QListWidget;
class QMenu;
class QTabWidget;
class QToolButton;
class QtxToolButton;
+class SMESHGUI_MeshTab;
/*!
* \brief Dialog for mech creation or editing
void setCurrentMeshType( const int );
int currentMeshType();
+ bool toCreateAllGroups();
+
signals:
void hypoSet( const QString& );
void geomSelectionByMesh( bool );
QToolButton* myHypoSetButton;
QMenu* myGeomPopup;
QComboBox* myMeshType;
+ QCheckBox* myCreateGroupsCheck;
};
/*!
#include "SMESHGUI.h"
#include "SMESHGUI_GEOMGenUtils.h"
+#include "SMESHGUI_GroupOnShapeDlg.h"
#include "SMESHGUI_Hypotheses.h"
#include "SMESHGUI_HypothesesUtils.h"
#include "SMESHGUI_MeshDlg.h"
#include "SMESHGUI_ShapeByMeshDlg.h"
#include "SMESHGUI_Utils.h"
#include "SMESH_NumberFilter.hxx"
+#include "SMESH_TypeDefs.hxx"
#include "SMESH_TypeFilter.hxx"
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
// SALOME GEOM includes
-#include <GEOM_SelectionFilter.h>
#include <GEOMBase.h>
-#include <GeometryGUI.h>
-#include <GEOM_wrap.hxx>
#include <GEOMImpl_Types.hxx>
+#include <GEOM_SelectionFilter.h>
+#include <GEOM_wrap.hxx>
+#include <GeometryGUI.h>
// SALOME GUI includes
-#include <SalomeApp_Tools.h>
-#include <SalomeApp_Application.h>
#include <LightApp_Application.h>
#include <LightApp_SelectionMgr.h>
#include <LightApp_UpdateFlags.h>
+#include <SALOME_InteractiveObject.hxx>
+#include <SALOME_ListIO.hxx>
#include <SUIT_MessageBox.h>
#include <SUIT_OverrideCursor.h>
+#include <SUIT_ResourceMgr.h>
#include <SUIT_Session.h>
-#include <SALOME_InteractiveObject.hxx>
-#include <SALOME_ListIO.hxx>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_Tools.h>
// SALOME KERNEL includes
#include <SALOMEDS_SComponent.hxx>
#include <SALOMEDS_wrap.hxx>
// Qt includes
-#include <QStringList>
-#include <QLineEdit>
#include <QApplication>
+#include <QLineEdit>
+#include <QStringList>
// OCCT includes
-#include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Shell.hxx>
-#include <TopExp_Explorer.hxx>
#include <BRep_Tool.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopoDS.hxx>
//================================================================================
/*!
SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), aMess );
}
+ myHypoSet = 0;
+
return aResult;
}
selectionDone();
+ myHypoSet = 0;
myHasConcurrentSubBefore = false;
myObjectToSelect.clear();
}
//================================================================================
/*!
* \brief Creates selection filter
- * \param theId - identifier of current selection widget
- * \retval SUIT_SelectionFilter* - pointer to the created filter or null
+ * \param theId - identifier of current selection widget
+ * \retval SUIT_SelectionFilter* - pointer to the created filter or null
*
* Creates selection filter in accordance with identifier of current selection widget
*/
bool isApplicable = false;
if ( myGeomEntry == myLastGeomEntry && !myGeomEntry.isEmpty() ) {
- THypLabelIsAppMap::const_iterator lab2isApp = myHypMapIsApplicable.find( theAlgoData->Label );
+ THypLabelIsAppMap::const_iterator lab2isApp = myHypMapIsApplicable.find( theAlgoData->TypeName );
if ( lab2isApp != myHypMapIsApplicable.end() ) {
isApplicable = lab2isApp.value();
return isApplicable;
toCheckIsApplicableToAll = ( myGeom->GetType() == GEOM_GROUP );
isApplicable = SMESH::IsApplicable( theAlgoData->TypeName, myGeom, toCheckIsApplicableToAll );
- myHypMapIsApplicable.insert( theAlgoData->Label, isApplicable );
+ myHypMapIsApplicable.insert( theAlgoData->TypeName, isApplicable );
return isApplicable;
}
*/
//================================================================================
SMESH::SMESH_Hypothesis_var
-SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
- const QString& aServerLib ) const
+SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
+ const QString& aServerLib,
+ const SMESH::HypInitParams* aParams ) const
{
if ( aHypType.isEmpty() || aServerLib.isEmpty() )
return SMESH::SMESH_Hypothesis::_nil();
}
}
- SMESH::SMESH_Hypothesis_var hyp =
- SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toUtf8().data(),
- aServerLib.toUtf8().data(),
- aMesh,
- aGeomVar,
- /*byMesh = */isSubMesh);
- if ( hyp->_is_nil() && isSubMesh )
+ SMESH::HypInitParams initParams;
+ enum { BY_MESH, BY_GEOM, BY_AVERAGE_LENGTH }; // same as ::SMESH_Hypothesis::InitWay
+ if ( aParams )
+ {
+ initParams = *aParams;
+ }
+ else
+ {
+ initParams.way = isSubMesh ? BY_MESH : BY_GEOM;
+ }
+
+ SMESH::SMESH_Hypothesis_var hyp;
+ if ( initParams.way == BY_AVERAGE_LENGTH )
+ hyp = SMESHGUI::GetSMESHGen()->CreateHypothesisByAverageLength( aHypType.toUtf8().data(),
+ aServerLib.toUtf8().data(),
+ initParams.averageLength,
+ initParams.quadDominated );
+ else
+ hyp = SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toUtf8().data(),
+ aServerLib.toUtf8().data(),
+ aMesh,
+ aGeomVar,
+ initParams );
+ if ( hyp->_is_nil() && initParams.way == BY_MESH )
+ {
+ initParams.way = BY_GEOM;
hyp = SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toLatin1().data(),
aServerLib.toUtf8().data(),
aMesh,
aGeomVar,
- /*byMesh = */false);
+ initParams );
+ }
+ if ( hyp->_is_nil() && initParams.way == BY_GEOM )
+ {
+ initParams.way = BY_AVERAGE_LENGTH;
+ initParams.averageLength = 1.;
+ hyp = SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toLatin1().data(),
+ aServerLib.toUtf8().data(),
+ aMesh,
+ aGeomVar,
+ initParams );
+ }
return hyp;
}
//================================================================================
/*!
- * Create hypothesis and update dialog.
- * \param theDim - dimension of hypothesis to be created
- * \param theType - hypothesis category (algorithm, hypothesis, additional hypothesis)
- * \param theTypeName - specifies hypothesis to be created
+ * \brief Return names of all existing hypotheses
*/
//================================================================================
-void SMESHGUI_MeshOp::createHypothesis(const int theDim,
- const int theType,
- const QString& theTypeName)
-{
- HypothesisData* aData = SMESH::GetHypothesisData(theTypeName);
- if (!aData)
- return;
-
- myDim = theDim;
- myType = theType;
- // get a unique hyp name
+QStringList SMESHGUI_MeshOp::getHypoNames()
+{
QStringList aHypNames;
+
TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin();
for ( ; aDimIter != myExistingHyps.end(); aDimIter++) {
const TType2HypList& aType2HypList = aDimIter.value();
}
}
}
- QString aHypName = GetUniqueName( aHypNames, aData->Label);
+ return aHypNames;
+}
+
+//================================================================================
+/*!
+ * Create hypothesis and update dialog.
+ * \param theDim - dimension of hypothesis to be created
+ * \param theType - hypothesis category (algorithm, hypothesis, additional hypothesis)
+ * \param theTypeName - specifies hypothesis to be created
+ */
+//================================================================================
+void SMESHGUI_MeshOp::createHypothesis(const int theDim,
+ const int theType,
+ const QString& theTypeName)
+{
+ HypothesisData* aData = SMESH::GetHypothesisData(theTypeName);
+ if (!aData)
+ return;
+
+ myDim = theDim;
+ myType = theType;
+
+ // get a unique hyp name
+ QString aHypName = GetUniqueName( getHypoNames(), aData->Label);
// existing hypos
bool dialog = false;
return;
}
+//================================================================================
+/*!
+ * \brief Create a sub-mesh on internal edges in the case where the global algorithm
+ * is of type 1D-2D[-3D] so that the internal edges would remain not meshed.
+ */
+//================================================================================
+
+void SMESHGUI_MeshOp::createSubMeshOnInternalEdges( SMESH::SMESH_Mesh_ptr theMesh,
+ GEOM::GEOM_Object_ptr theMainShape )
+{
+ if ( theMesh->_is_nil() || theMainShape->_is_nil() )
+ return;
+
+ if ( isAccessibleDim( 1 ))
+ return; // global 1D algorithm is/can be assigned
+
+ const HypothesesSet::SetType internSet = HypothesesSet::INTERN;
+ bool toCreate = true;
+ bool toCreateMandatory = ( myHypoSet &&
+ myAverageSize > 0 &&
+ ( myHypoSet->init( /*algo=*/ true, internSet ), myHypoSet->more()) &&
+ ( myHypoSet->init( /*algo=*/false, internSet ), myHypoSet->more()));
+ if ( !toCreateMandatory ) // ask the user
+ toCreate = false; // can't pass both mesh and geometry to Create Submesh operation (so far?)
+ // toCreate = SUIT_MessageBox::warning( SMESHGUI::desktop(),
+ // QObject::tr("SMESH_WRN_WARNING"),
+ // QObject::tr("SMESH_CREATE_SUBMESH_ON_INTERNAL_EDGES"),
+ // QObject::tr("SMESH_BUT_YES"),
+ // QObject::tr("SMESH_BUT_NO"), 1, 0);
+ if ( !toCreate )
+ return;
+
+ TopoDS_Shape shape;
+ if ( !GEOMBase::GetShape( theMainShape, shape ))
+ return;
+
+ std::vector< TopoDS_Shape > internalEdges;
+ for ( TopExp_Explorer edge( shape, TopAbs_EDGE, TopAbs_WIRE ); edge.More(); edge.Next() )
+ internalEdges.push_back( edge.Current() );
+
+ if ( internalEdges.empty() )
+ return;
+
+ TopTools_IndexedMapOfShape shapeIDs;
+ TopExp::MapShapes( shape, shapeIDs );
+
+ std::set< int > intIDSet;
+ for ( size_t i = 0; i < internalEdges.size(); ++i )
+ intIDSet.insert( shapeIDs.FindIndex( internalEdges[ i ]));
+
+ GEOM::GEOM_Gen_var geomGen = theMainShape->GetGen();
+ if (geomGen->_is_nil()) return;
+
+ GEOM::GEOM_Object_var edgeGroup;
+ GEOM::GEOM_IShapesOperations_wrap sOp = geomGen->GetIShapesOperations();
+ GEOM::GEOM_IGroupOperations_wrap gOp = geomGen->GetIGroupOperations();
+ GEOM::ListOfGO_var geomGroups = sOp->GetExistingSubObjects( theMainShape,
+ /*groupsOnly=*/true );
+ for ( CORBA::ULong i = 0; i < geomGroups->length(); ++i )
+ {
+ GEOM::ListOfLong_var ids = gOp->GetObjects( geomGroups[ i ]);
+ std::set< int > idSet( & ids[0], & ids[0] + ids->length() );
+ if ( idSet == intIDSet )
+ {
+ edgeGroup = geomGroups[ i ];
+ break;
+ }
+ }
+
+ if ( edgeGroup->_is_nil() )
+ {
+ GEOM::GEOM_Object_var edgeGroup = gOp->CreateGroup( theMainShape, TopAbs_EDGE );
+
+ GEOM::ListOfLong_var edgeIDs = new GEOM::ListOfLong;
+ edgeIDs->length( internalEdges.size() );
+ std::set< int >::iterator id = intIDSet.begin();
+ for ( size_t i = 0; i < intIDSet.size(); ++i, ++id )
+ edgeIDs[ i ] = *id;
+ gOp->UnionIDs( edgeGroup, edgeIDs );
+
+ SALOMEDS::SObject_wrap so = geomGen->AddInStudy( edgeGroup, "Internal edges", theMainShape );
+ }
+
+ if ( !toCreateMandatory )
+ {
+ // show Create Sub-mesh dislog
+ // _PTR(SObject) aMeshSO = SMESH::FindSObject( theMesh );
+ // selectionMgr()->clearFilters();
+ // selectObject( pSubmesh );
+ // SMESHGUI::GetSMESHGUI()->switchToOperation( SMESHOp::OpEditMeshOrSubMesh );
+ return;
+ }
+
+ // create a sub-mesh using myAverageSize w/o GUI
+
+ SMESH::SMESH_subMesh_var subMesh = theMesh->GetSubMesh( edgeGroup, "" );
+
+ for ( int isAlgo = 1; isAlgo >= 0; --isAlgo )
+ for ( myHypoSet->init( isAlgo, internSet ); myHypoSet->more(); myHypoSet->next() )
+ {
+ QString aHypoTypeName = myHypoSet->current();
+ HypothesisData* aHypData = SMESH::GetHypothesisData( aHypoTypeName );
+ if ( !aHypData )
+ continue;
+
+ myDim = aHypData->Dim[0];
+ if ( myDim != 1 )
+ continue;
+
+ // create or/and set
+ SMESH::SMESH_Hypothesis_var newHypo;
+ if ( isAlgo )
+ {
+ myAvailableHypData[ myDim ][ Algo ].clear();
+ myAvailableHypData[ myDim ][ Algo ] << aHypData;
+ QStringList hypList; hypList << aHypoTypeName;
+ myDlg->tab( myDim )->setAvailableHyps( Algo, hypList );
+ setCurrentHyp( myDim, Algo, 0 );
+ newHypo = getAlgo( myDim );
+ }
+ else
+ {
+ SMESH::HypInitParams params = { 2, myAverageSize, false };
+ newHypo = getInitParamsHypothesis( aHypData->TypeName, aHypData->ServerLibName, & params );
+ QString hypName = GetUniqueName( getHypoNames(), aHypData->Label );
+ SALOMEDS::SObject_wrap so =
+ SMESHGUI::GetSMESHGen()->PublishInStudy( SALOMEDS::SObject::_nil(), newHypo,
+ hypName.toUtf8().data() );
+ }
+ SMESH::AddHypothesisOnSubMesh( subMesh, newHypo );
+ }
+
+ return;
+}
+
+//================================================================================
+/*!
+ * \brief Ask the user to enter an average size which will be used to create
+ * hypotheses of a hypo-set basing on this size
+ * \param [out] averageSize - average element size
+ * \return bool - false if the user canceled the dialog
+ */
+//================================================================================
+
+bool SMESHGUI_MeshOp::getAverageSize( double & averageSize )
+{
+ HypothesisData* hypData = SMESH::GetHypothesisData( "MaxLength" );
+ if ( !hypData )
+ return false;
+
+ SMESH::SMESH_Hypothesis_var hyp = getInitParamsHypothesis( hypData->TypeName,
+ hypData->ServerLibName );
+ if ( hyp->_is_nil() )
+ return false;
+
+ SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( hypData->TypeName );
+ if ( !aCreator )
+ return false;
+
+ initHypCreator( aCreator );
+ myDlg->setEnabled( false );
+
+ aCreator->edit( hyp.in(), HypothesesSet::getCommonHypoSetHypoType(),
+ dlg(), this, SLOT( onHypoEdited( int )));
+
+ StdMeshers::StdMeshers_MaxLength_var lenHyp = StdMeshers::StdMeshers_MaxLength::_narrow( hyp );
+ if ( lenHyp->_is_nil() )
+ return false;
+
+ averageSize = lenHyp->GetLength();
+ return true;
+}
+
//================================================================================
/*!
* \brief Creates and selects hypothesis of hypotheses set
void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
{
HypothesesSet* aHypoSet = SMESH::GetHypothesesSet(theSetName);
+ myHypoSet = aHypoSet;
if (!aHypoSet)
return;
onAlgoSelected( -1, dim );
}
+ HypothesesSet::SetType setType = aHypoSet->getPreferredHypType();
+ if ( !aHypoSet->getAlgoAvailable( setType ))
+ {
+ setType = ( setType == HypothesesSet::ALT ) ? HypothesesSet::MAIN : HypothesesSet::ALT;
+ if ( !aHypoSet->getAlgoAvailable( setType ))
+ return;
+ }
+
+ myAverageSize = -1;
+ if ( aHypoSet->toUseCommonSize() && !getAverageSize( myAverageSize ))
+ return;
+
for ( int isAlgo = 1; isAlgo >= 0; --isAlgo )
- for ( aHypoSet->init( isAlgo ); aHypoSet->more(); aHypoSet->next() )
+ for ( aHypoSet->init( isAlgo, setType ); aHypoSet->more(); aHypoSet->next() )
{
QString aHypoTypeName = aHypoSet->current();
HypothesisData* aHypData = SMESH::GetHypothesisData( aHypoTypeName );
if (!aHypData)
continue;
- int aDim = aHypData->Dim[0];
+ myDim = aHypData->Dim[0];
// create or/and set
if ( isAlgo )
{
- int index = myAvailableHypData[aDim][Algo].indexOf( aHypData );
+ int index = myAvailableHypData[myDim][Algo].indexOf( aHypData );
if ( index >= 0 )
{
- setCurrentHyp( aDim, Algo, index );
- onAlgoSelected( index, aDim );
+ setCurrentHyp( myDim, Algo, index );
+ onAlgoSelected( index, myDim );
}
}
else
{
- bool mainHyp = true;
- int index = myAvailableHypData[aDim][MainHyp].indexOf( aHypData );
+ myType = MainHyp;
+ int index = myAvailableHypData[myDim][MainHyp].indexOf( aHypData );
if ( index < 0 )
{
- mainHyp = false;
- index = myAvailableHypData[aDim][AddHyp].indexOf( aHypData );
+ myType = AddHyp;
+ index = myAvailableHypData[myDim][AddHyp].indexOf( aHypData );
}
if ( index >= 0 )
- createHypothesis( aDim, mainHyp ? MainHyp : AddHyp, aHypoTypeName );
+ {
+ if ( myAverageSize > 0 )
+ {
+ SMESH::HypInitParams params = { 2, myAverageSize, aHypoSet->isQuadDominated() };
+ SMESH::SMESH_Hypothesis_var hyp =
+ getInitParamsHypothesis( aHypData->TypeName, aHypData->ServerLibName, & params );
+
+ QString hypName = GetUniqueName( getHypoNames(), aHypData->Label );
+ SALOMEDS::SObject_wrap so =
+ SMESHGUI::GetSMESHGen()->PublishInStudy( SALOMEDS::SObject::_nil(), hyp,
+ hypName.toUtf8().data() );
+ onHypoCreated(2);
+ }
+ else
+ {
+ createHypothesis( myDim, myType, aHypoTypeName );
+ }
+ }
}
}
+
return;
}
namePrefix += "_";
}
QStringList::Iterator it = aList.begin();
- for ( int i = 0; it!=aList.end(); it++, ++i )
+ for ( int i = 0; it != aList.end(); it++, ++i )
{
QString aGeomEntry = *it;
_PTR(SObject) pGeom = SMESH::getStudy()->FindObjectID( aGeomEntry.toUtf8().data() );
if ( !anAlgoVar->_is_nil() )
SMESH::AddHypothesisOnMesh( aMesh, anAlgoVar );
}
+
+
+ if ( myDlg->toCreateAllGroups() && !aGeomVar->_is_nil() )
+ {
+ // Create groups on all geom groups
+
+ GEOM::GEOM_Gen_var geomGen = aGeomVar->GetGen();
+ GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
+ GEOM::ListOfGO_var geomGroups = op->GetExistingSubObjects( aGeomVar,
+ /*groupsOnly=*/false );
+ SMESH::SMESH_GroupOnGeom_var meshGroup;
+ for ( CORBA::ULong iG = 0; iG < geomGroups->length(); ++iG )
+ {
+ SMESH::ElementType elemType = SMESHGUI_GroupOnShapeOp::ElementType( geomGroups[ iG ] );
+ if ( elemType == SMESH::ALL )
+ continue;
+ if ( elemType == SMESH::ELEM0D )
+ elemType = SMESH::NODE;
+
+ CORBA::String_var name = geomGroups[ iG ]->GetName();
+ meshGroup = aMesh->CreateGroupFromGEOM( elemType, name, geomGroups[ iG ]);
+ // if ( elemType != SMESH::NODE )
+ // meshGroup = aMesh->CreateGroupFromGEOM( SMESH::NODE, name, geomGroups[ iG ]);
+ }
+ }
+
+ createSubMeshOnInternalEdges( aMesh, aGeomVar );
+
}
+
return true;
}
else if (aGEOMs.count() > 1)
{
// create a GEOM group
- GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen( mainGeom );
+ GEOM::GEOM_Gen_var geomGen = mainGeom->GetGen();
if ( !geomGen->_is_nil() ) {
GEOM::GEOM_IGroupOperations_ptr op = geomGen->GetIGroupOperations();
if ( !op->_is_nil() )
}
}
+ if ( aSubMeshVar->_is_nil() )
+ {
+ GEOM::GEOM_Object_var mainGeom = aMesh->GetShapeToMesh();
+ createSubMeshOnInternalEdges( aMesh, mainGeom );
+ }
+
myHasConcurrentSubBefore =
checkSubMeshConcurrency( aMesh, aSubMeshVar, /*askUser=*/!myHasConcurrentSubBefore );
for ( ; inHypoSetName != aHypothesesSetsList.end(); ++inHypoSetName )
{
HypothesesSet* currentHypoSet = SMESH::GetHypothesesSet( *inHypoSetName );
- bool isAvailable = false;
- for ( currentHypoSet->init( true ); currentHypoSet->more(); currentHypoSet->next() )
+ HypothesesSet::SetType sType;
+ for ( sType = HypothesesSet::MAIN; sType <= HypothesesSet::ALT; SMESHUtils::Increment( sType ))
{
- isAvailable = false;
- if ( HypothesisData* algoDataIn = SMESH::GetHypothesisData( currentHypoSet->current() )) {
- for (int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++) {
- int aCurrentAvailableAlgo = myAvailableHypData[i][Algo].indexOf( algoDataIn );
- if ( aCurrentAvailableAlgo > -1 ) {
- isAvailable = true;
- break;
+ bool isAvailable = false;
+ for ( currentHypoSet->init( true, sType ); currentHypoSet->more(); currentHypoSet->next() )
+ {
+ isAvailable = false;
+ if ( HypothesisData* algoDataIn = SMESH::GetHypothesisData( currentHypoSet->current() )) {
+ for ( int dim = SMESH::DIM_0D; dim <= myMaxShapeDim; dim++) {
+ int aCurrentAvailableAlgo = myAvailableHypData[dim][Algo].indexOf( algoDataIn );
+ if ( aCurrentAvailableAlgo > -1 ) {
+ isAvailable = true;
+ break;
+ }
}
+ if ( !isAvailable )
+ break;
}
- if ( !isAvailable )
- break;
}
+ currentHypoSet->setAlgoAvailable( sType, isAvailable );
}
- if ( isAvailable )
+ if ( currentHypoSet->hasAlgo( HypothesesSet::MAIN ) &&
+ currentHypoSet->hasAlgo( HypothesesSet::ALT ))
+ {
+ HypothesesSet::SetType setType = HypothesesSet::getPreferredHypType();
+ if ( !currentHypoSet->getAlgoAvailable( setType ))
+ continue; // not add if a preferred type not available currently
+ }
+
+ if ( currentHypoSet->getAlgoAvailable( HypothesesSet::MAIN ) ||
+ currentHypoSet->getAlgoAvailable( HypothesesSet::ALT ))
+ {
aFilteredHypothesesSetsList.append( *inHypoSetName );
+ }
}
myDlg->setHypoSets( aFilteredHypothesesSetsList );
}
bool createMesh( QString&, QStringList& );
bool createSubMesh( QString&, QStringList& );
bool editMeshOrSubMesh( QString& );
+ void createSubMeshOnInternalEdges( SMESH::SMESH_Mesh_ptr mesh,
+ GEOM::GEOM_Object_ptr mainShape );
bool checkSubMeshConcurrency( SMESH::SMESH_Mesh_ptr mesh,
SMESH::SMESH_subMesh_ptr submesh,
bool askUser=false);
int find( const SMESH::SMESH_Hypothesis_var&,
const THypList& ) const;
SMESH::SMESH_Hypothesis_var getInitParamsHypothesis( const QString&,
- const QString& ) const;
+ const QString&,
+ const SMESH::HypInitParams* prm=0) const;
void initHypCreator( SMESHGUI_GenericHypothesisCreator* aCreator );
+ bool getAverageSize( double & averageSize );
bool isSubshapeOk() const;
char* isSubmeshIgnored() const;
_PTR(SObject) getSubmeshByGeom() const;
void updateMeshTypeList();
void updateHypoSets();
void setFilteredAlgoData();
+ QStringList getHypoNames();
private:
bool myIgnoreAlgoSelection;
int myDim, myType, myMaxShapeDim;
+ HypothesesSet* myHypoSet; // applied hypo-set
+ double myAverageSize; // entered at hypo-set processing
+
QString myObjectToSelect;
};
return;
}
+ //================================================================================
+ /*!
+ * \brief Remove/update actors while module activation
+ *
+ * At module activation, groups and sub-meshes can be removed on engine side due
+ * to modification of meshed geometry, while their actors can remain.
+ * Here we remove/update SMESH_Actor's of changed objects. State (emptiness) of objects
+ * is defined by their icons in the Object Browser
+ */
+ //================================================================================
+
+ void UpdateActorsAfterUpdateStudy()
+ {
+ SUIT_Study* study = SMESH::GetActiveStudy();
+ if ( SUIT_Desktop* desk = study->application()->desktop() )
+ {
+ QList<SUIT_ViewWindow*> wndList = desk->windows();
+ SUIT_ViewWindow* wnd;
+ foreach ( wnd, wndList )
+ SMESH::UpdateActorsAfterUpdateStudy(wnd);
+ }
+ }
+
//================================================================================
/*!
* \brief Notify the user on problems during visualization
SMESHGUI_EXPORT
void UpdateActorsAfterUpdateStudy( SUIT_ViewWindow* wnd );
+
+ SMESHGUI_EXPORT
+ void UpdateActorsAfterUpdateStudy();
};
#endif // SMESHGUI_VTKUTILS_H
{
if (atts.value("name") != "")
{
- QString hypos = atts.value("hypos").remove( ' ' );
- QString algos = atts.value("algos").remove( ' ' );
+ bool useCommonSize = ( atts.value("use-common-size") == "true" );
+ bool isQuadDominated = ( atts.value("quad-dominated") == "true" );
+ QString hypos = atts.value("hypos");
+ QString algos = atts.value("algos");
+ QString altHypos = atts.value("alt-hypos");
+ QString altAlgos = atts.value("alt-algos");
+ QString intHypos = atts.value("intern-edge-hypos");
+ QString intAlgos = atts.value("intern-edge-algos");
bool badSet = hypos.contains( BAD_HYP_FLAG ) || algos.contains( BAD_HYP_FLAG );
if ( !badSet )
- myListOfHypothesesSets.append( new HypothesesSet ( atts.value("name"),
- hypos.split( ',', QString::SkipEmptyParts ),
- algos.split( ',', QString::SkipEmptyParts ) ) );
+ myListOfHypothesesSets.append
+ ( new HypothesesSet ( atts.value("name"),
+ useCommonSize, isQuadDominated,
+ hypos.split ( ',', QString::SkipEmptyParts ),
+ algos.split ( ',', QString::SkipEmptyParts ),
+ altHypos.split( ',', QString::SkipEmptyParts ),
+ altAlgos.split( ',', QString::SkipEmptyParts ),
+ intHypos.split( ',', QString::SkipEmptyParts ),
+ intAlgos.split( ',', QString::SkipEmptyParts )));
}
}
else if ( qName == "python-wrap" ||
<source>PREF_NB_SEGMENTS</source>
<translation>Default Number of Segments</translation>
</message>
+ <message>
+ <source>PREF_USE_MESHGEMS_HYPOSET</source>
+ <translation>Use MeshGems meshers when assigning set of hypotheses</translation>
+ </message>
<message>
<source>SMESH_PREF_MESH_LOADING</source>
<translation>Mesh loading</translation>
</message>
<message>
<source>HYPOTHESES_SETS</source>
- <translation>Assign a set of hypotheses</translation>
+ <translation>Assign a set of automatic hypotheses</translation>
</message>
<message>
<source>MESH</source>
<source>NAME</source>
<translation>Name</translation>
</message>
+ <message>
+ <source>CREATE_ALL_GROUPS</source>
+ <translation>Create all Groups on Geometry</translation>
+ </message>
</context>
<context>
<name>SMESHGUI_MeshOp</name>
<translation>Option value</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_GenericHypothesisCreator</name>
+ <message>
+ <source>AverageLengthForHypoSet</source>
+ <translation>Mean Size</translation>
+ </message>
+</context>
</TS>
</message>
<message>
<source>GMF_BINARY_FILES_FILTER</source>
- <translation>Fichier GMF binaires</translation>
+ <translation>Fichiers GMF binaires</translation>
</message>
<message>
<source>STL_BIN_FILES_FILTER</source>
</message>
<message>
<source>MIN_ELEM_EDGE</source>
- <translation>Longueur arête Minimum</translation>
+ <translation>Longueur arête minimum</translation>
</message>
<message>
<source>ASPECTRATIO_3D_ELEMENTS</source>
</message>
<message>
<source>EDITERR_NO_MEDIUM_ON_GEOM</source>
- <translation>Certain noeuds milieux (affichés en magenta) ne sont pas placés
+ <translation>Certain nœuds milieux (affichés en magenta) ne sont pas placés
sur la géométrie pour éviter d'obtenir des élements distordus.</translation>
</message>
<message>
</message>
<message>
<source>DEFLECTION2D_FACES</source>
- <translation>Deflection 2D</translation>
+ <translation>Déflection 2D</translation>
</message>
<message>
<source>LENGTH_EDGES</source>
</message>
<message>
<source>MAX_ELEMENT_LENGTH_2D</source>
- <translation>Diamètre d'éléments 2D</translation>
+ <translation>Diamètre des éléments 2D</translation>
</message>
<message>
<source>MAX_ELEMENT_LENGTH_3D</source>
- <translation>Diamètre Element 3D</translation>
+ <translation>Diamètre des éléments 3D</translation>
</message>
<message>
<source>DEFLECTION_2D</source>
- <translation>Deflection 2D</translation>
+ <translation>Déflection 2D</translation>
</message>
<message>
<source>MEN_ADD</source>
</message>
<message>
<source>MEN_CONV_TO_QUAD</source>
- <translation>Convertir vers/de quadratique</translation>
+ <translation>Convertir vers/depuis quadratique</translation>
</message>
<message>
<source>MEN_2D_FROM_3D</source>
</message>
<message>
<source>MEN_0D_ON_ALL_NODES</source>
- <translation>Eléments 0D sur des noeuds</translation>
+ <translation>Eléments 0D sur des nœuds</translation>
</message>
<message>
<source>MEN_BALL</source>
<message>
<source>STB_OVERALL_MESH_QUALITY</source>
<translation>Qualité du maillage global</translation>
- </message>
+ </message>
<message>
<source>STB_SPLIT_TO_TETRA</source>
<translation>Eclater en tétraèdres</translation>
</message>
<message>
<source>SMESH_EXPORT_MED_VERSION_COLLISION</source>
- <translation>La version MED du fichier "%1" n'est pas connue
+ <translation>La version MED du fichier "%1" n'est pas connue
ou ne correspond pas à la version choisie.
Ecraser le fichier ?</translation>
</message>
<message>
<source>SMESH_FILE_EXISTS</source>
<translation>Le fichier "%1" existe déjà.
-Voulez-vous le réécrire ou y ajouter
-les données exportées ?</translation>
+Voulez-vous le réécrire ou y ajouter les données exportées ?</translation>
</message>
<message>
<source>SMESH_FONT_ARIAL</source>
</message>
<message>
<source>STB_0D_ON_ALL_NODES</source>
- <translation>Créer des éléments 0D sur des noeuds</translation>
+ <translation>Créer des éléments 0D sur des nœuds</translation>
</message>
<message>
<source>STB_ELEMS0D</source>
</message>
<message>
<source>TOP_0D_ON_ALL_NODES</source>
- <translation>Créer des éléments 0D sur des noeuds</translation>
+ <translation>Créer des éléments 0D sur des nœuds</translation>
</message>
<message>
<source>TOP_ELEM0D</source>
<source>PREF_SHOW_WARN</source>
<translation>Affiche un avertissement quand un groupe est exporté</translation>
</message>
+ <message>
+ <source>PREF_ZTOLERANCE</source>
+ <translation>Tolérance sur Z pour l'export en MED</translation>
+ </message>
<message>
<source>PREF_GROUP_SEGMENT_LENGTH</source>
<translation>Paramètres automatiques</translation>
<source>PREF_NB_SEGMENTS</source>
<translation>Nombre de segments par défaut</translation>
</message>
+ <message>
+ <source>PREF_USE_MESHGEMS_HYPOSET</source>
+ <translation>Utiliser les mailleurs MeshGems pour définir les hypothèses automatiques</translation>
+ </message>
<message>
<source>SMESH_PREF_MESH_LOADING</source>
<translation>Chargement de maillage</translation>
<source>PREF_DISPLAY_MODE</source>
<translation>Mode de visualisation par défaut</translation>
</message>
+ <message>
+ <source>PREF_FITALL_ON_DISPLAYONLY</source>
+ <translation>Ajuster la vue en cas d'affichage unique</translation>
+ </message>
<message>
<source>PREF_ELEMENTS</source>
<translation>Eléments</translation>
<name>SMESHGUI_Add0DElemsOnAllNodesDlg</name>
<message>
<source>CAPTION</source>
- <translation>Créer des éléments 0D sur des noeuds</translation>
+ <translation>Créer des éléments 0D sur des nœuds</translation>
</message>
<message>
<source>OBJ_BTN</source>
</message>
<message>
<source>EDIT_SELECTED_NODE_GROUP</source>
- <translation>Editer le groupe sélectionné de noeuds coïncidents</translation>
+ <translation>Editer le groupe sélectionné de nœuds coïncidents</translation>
</message>
<message>
<source>EDIT_SELECTED_ELEM_GROUP</source>
</message>
<message>
<source>SEPARATE_CORNERS_AND_MEDIUM</source>
- <translation>Pas de fusion du coin et des noeuds moyens des cellules quadratiques</translation>
+ <translation>Pas de fusion du coin et des nœuds moyens des cellules quadratiques</translation>
</message>
<message>
<source>AVOID_MAKING_HOLES</source>
</message>
<message>
<source>KEEP_NODES</source>
- <translation>Les noeuds à conserver pendant la fusion</translation>
+ <translation>Les nœuds à conserver pendant la fusion</translation>
</message>
<message>
<source>GROUP_SUBMESH</source>
<name>SMESHGUI_ExtrusionDlg</name>
<message>
<source>EXTRUSION_0D</source>
- <translation>Extrusion de noeuds</translation>
+ <translation>Extrusion de nœuds</translation>
</message>
<message>
<source>EXTRUSION_1D</source>
</message>
<message>
<source>NUMBEROFNODESINELEMENT</source>
- <translation>Nombre de noeuds dans l'élément</translation>
+ <translation>Nombre de nœuds dans l'élément</translation>
</message>
<message>
<source>COPY_FROM</source>
</message>
<message>
<source>HYPOTHESES_SETS</source>
- <translation>Attribuer un jeu d'hypothèses</translation>
+ <translation>Définir des hypothèses automatiques</translation>
</message>
<message>
<source>MESH</source>
<source>NAME</source>
<translation>Nom</translation>
</message>
+ <message>
+ <source>CREATE_ALL_GROUPS</source>
+ <translation>Créer tous les groupes définis dans la géométrie</translation>
+ </message>
+ <message>
+ <source>3D: Tetrahedralization</source>
+ <translation>3D : Tétraèdres</translation>
+ </message>
+ <message>
+ <source>3D: Mapped Hexahedralization</source>
+ <translation>3D : Hexaèdres réglés</translation>
+ </message>
+ <message>
+ <source>3D: Free Hexahedralization</source>
+ <translation>3D : Hexaèdres libres</translation>
+ </message>
+ <message>
+ <source>2D: Triangulation</source>
+ <translation>2D : Triangles</translation>
+ </message>
+ <message>
+ <source>2D: Mapped Quadrangulation</source>
+ <translation>2D : Quadrangles réglés</translation>
+ </message>
+ <message>
+ <source>2D: Free Quadrangulation</source>
+ <translation>2D : Quadrangles libres</translation>
+ </message>
</context>
<context>
<name>SMESHGUI_MeshOp</name>
</message>
<message>
<source>MT_HEXAHEDRAL</source>
- <translation>Hexahèdre</translation>
+ <translation>Hexaèdre</translation>
</message>
<message>
<source>MT_TETRAHEDRAL</source>
</message>
<message>
<source>CONCURRENT_SUBMESH_APPEARS</source>
- <translation>
+ <translation>
L'algorithme assigné a la même priorité que celui assigné à un
sous-maillage adjacent; ainsi l'algorithme à utiliser pour mailler la
frontière partagée par les deux sous-maillages n'est pas défini.
</message>
<message>
<source>ERROR_OF_OPENING</source>
- <translation>Il est impossible d'ouvrir le fichier.
+ <translation>Il est impossible d'ouvrir le fichier.
Vérifiez s'il existe et si vous avez l'autorisation</translation>
</message>
<message>
</message>
<message>
<source>ERR_READ_TOO_FEW_POINTS</source>
- <translation>Il est impossible de charger le motif.
+ <translation>Il est impossible de charger le motif.
Il y a trop peu de points dans le fichier </translation>
</message>
<message>
<message>
<source>SUBSHAPES_NOT_FOUND_MSG</source>
<translation>
-Some sub-shapes not found in the new geometry. They are listed
+Some sub-shapes not found in the new geometry. They are listed
below along with dependent mesh objects that are marked with
with red in the Object Browser.</translation>
</message>
<translation>Valeur de l'option'</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_GenericHypothesisCreator</name>
+ <message>
+ <source>AverageLengthForHypoSet</source>
+ <translation>Taille moyenne</translation>
+ </message>
+</context>
</TS>
gp_XY seg = uv - gc;
tria->Edges( linkIDs, ori );
-#if OCC_VERSION_LARGE <= 0x07030000
- int triaID = _triaDS->IndexOf( *tria );
-#else
- int triaID = tria - & ( _triaDS->GetElement( 0 ));
-#endif
+
+ const BRepMesh_Triangle* prevTria = tria;
tria = 0;
for ( int i = 0; i < 3; ++i )
double uSeg = ( uv1 - gc ) ^ lin / crossSegLin;
if ( 0. <= uSeg && uSeg <= 1. )
{
- tria = & _triaDS->GetElement( triIDs.Index( 1 + ( triIDs.Index(1) == triaID )));
+ tria = & _triaDS->GetElement( triIDs.Index( 1 ));
+ if ( tria == prevTria )
+ tria = & _triaDS->GetElement( triIDs.Index( 2 ));
if ( tria->Movability() != BRepMesh_Deleted )
break;
}
file.remove();
file.openForWriting();
file.write( text.c_str(), text.size() );
- cout << "exec(open('" << fileName << "', 'rb').read())";
+ std::cout << "exec(open('" << fileName << "', 'rb').read())";
}
${OMNIORB_INCLUDE_DIR}
${OpenCASCADE_INCLUDE_DIR}
${HDF5_INCLUDE_DIRS}
+ ${MEDFILE_INCLUDE_DIRS}
${VTK_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
{
- // some methods of SMESH_Mesh interface needs special conversion
+ // some methods of SMESH_Mesh interface need special conversion
// to methods of Mesh python class
//
// 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
// if GetGroups() is just after Compute(), this can mean that the groups
// were created by some algorithm and hence Compute() should not be discarded
std::list< Handle(_pyCommand) >& cmdList = theGen->GetCommands();
- std::list< Handle(_pyCommand) >::iterator cmd = cmdList.begin();
+ std::list< Handle(_pyCommand) >::reverse_iterator cmd = cmdList.rbegin();
while ( (*cmd)->GetMethod() == "GetGroups" )
++cmd;
if ( myLastComputeCmd == (*cmd))
continue;
// check if a cmd is a sole command setting its parameter;
// don't use method name for search as it can change
- map<TCollection_AsciiString, list<Handle(_pyCommand)> >::iterator
- m2cmds = myMeth2Commands.begin();
+ map<_AString, list<Handle(_pyCommand)> >::iterator m2cmds = myMeth2Commands.begin();
for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds )
{
list< Handle(_pyCommand)>& cmds = m2cmds->second;
return hyp._retn();
}
+//================================================================================
+/*!
+ * \brief Return a hypothesis initialized by given average length.
+ * \param theHypType - hypothesis type name
+ * \param theLibName - plugin library name
+ * \param theAverageLength - average length
+ * \param theQuadDominated - is quad-dominated flag
+ * \retval SMESH::SMESH_Hypothesis_ptr - the new hypothesis
+ */
+//================================================================================
+
+SMESH::SMESH_Hypothesis_ptr
+SMESH_Gen_i::CreateHypothesisByAverageLength( const char* theHypType,
+ const char* theLibName,
+ CORBA::Double theAverageLength,
+ CORBA::Boolean theQuadDominated)
+ throw ( SALOME::SALOME_Exception )
+{
+ SMESH::HypInitParams initParams = { ::SMESH_Hypothesis::BY_AVERAGE_LENGTH,
+ theAverageLength, theQuadDominated };
+
+ SMESH::SMESH_Hypothesis_var hyp =
+ GetHypothesisParameterValues( theHypType, theLibName,
+ SMESH::SMESH_Mesh::_nil(),
+ GEOM::GEOM_Object::_nil(),
+ initParams );
+ SALOMEDS::SObject_wrap so = PublishHypothesis( hyp );
+
+ TPythonDump() << hyp << " = " << this << ".CreateHypothesisByAverageLength( '"
+ << theHypType << "', '"
+ << theLibName << "', "
+ << theAverageLength << ", "
+ << theQuadDominated << " )";
+
+ return hyp._retn();
+}
+
//================================================================================
/*!
* \brief Return a hypothesis holding parameter values corresponding either to the mesh
//================================================================================
SMESH::SMESH_Hypothesis_ptr
-SMESH_Gen_i::GetHypothesisParameterValues (const char* theHypType,
- const char* theLibName,
- SMESH::SMESH_Mesh_ptr theMesh,
- GEOM::GEOM_Object_ptr theGeom,
- CORBA::Boolean byMesh)
+SMESH_Gen_i::GetHypothesisParameterValues( const char* theHypType,
+ const char* theLibName,
+ SMESH::SMESH_Mesh_ptr theMesh,
+ GEOM::GEOM_Object_ptr theGeom,
+ const SMESH::HypInitParams& theParams)
throw ( SALOME::SALOME_Exception )
{
Unexpect aCatch(SALOME_SalomeException);
+
+ const bool byMesh = ( theParams.way == ::SMESH_Hypothesis::BY_MESH );
if ( byMesh && CORBA::is_nil( theMesh ) )
return SMESH::SMESH_Hypothesis::_nil();
if ( byMesh && CORBA::is_nil( theGeom ) )
if ( hyp->SetParametersByMesh( mesh, shape ))
return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
}
- else {
- double diagonal = 0;
- if ( mesh )
- diagonal = mesh->GetShapeDiagonalSize();
- else
- diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+ else
+ {
::SMESH_Hypothesis::TDefaults dflts;
- dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
- dflts._nbSegments = myGen.GetDefaultNbSegments();
- dflts._shape = &shape;
- // let the temporary hypothesis initialize it's values
+ dflts._way = ( ::SMESH_Hypothesis::InitWay) theParams.way;
+ dflts._nbSegments = myGen.GetDefaultNbSegments();
+ dflts._elemLength = theParams.averageLength;
+ dflts._quadDominated = theParams.quadDominated;
+ if ( theParams.way == ::SMESH_Hypothesis::BY_GEOM )
+ {
+ if ( mesh )
+ dflts._diagonal = mesh->GetShapeDiagonalSize();
+ else
+ dflts._diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+ dflts._elemLength = dflts._diagonal / myGen.GetBoundaryBoxSegmentation();
+ dflts._shape = &shape;
+ }
+
+ // let the hypothesis initialize it's values
if ( hyp->SetParametersByDefaults( dflts, mesh ))
return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
}
const char* theLibName)
throw ( SALOME::SALOME_Exception );
+ SMESH::SMESH_Hypothesis_ptr CreateHypothesisByAverageLength( const char* theHypType,
+ const char* theLibName,
+ CORBA::Double theAverageLength,
+ CORBA::Boolean theQuadDominated)
+ throw ( SALOME::SALOME_Exception );
+
// Return hypothesis of given type holding parameter values of the existing mesh
- SMESH::SMESH_Hypothesis_ptr GetHypothesisParameterValues (const char* theHypType,
- const char* theLibName,
- SMESH::SMESH_Mesh_ptr theMesh,
- GEOM::GEOM_Object_ptr theGeom,
- CORBA::Boolean byMesh)
+ SMESH::SMESH_Hypothesis_ptr
+ GetHypothesisParameterValues (const char* theHypType,
+ const char* theLibName,
+ SMESH::SMESH_Mesh_ptr theMesh,
+ GEOM::GEOM_Object_ptr theGeom,
+ const SMESH::HypInitParams& theWay)
throw ( SALOME::SALOME_Exception );
/*
const char* theName = 0);
void UpdateIcons(SMESH::SMESH_Mesh_ptr theMesh);
void HighLightInvalid(CORBA::Object_ptr theObject, bool isInvalid);
+ bool IsInvalid(SALOMEDS::SObject_ptr theObject);
bool AddHypothesisToShape(SMESH::SMESH_Mesh_ptr theMesh,
GEOM::GEOM_Object_ptr theShapeObject,
SMESH::SMESH_Hypothesis_ptr theHyp);
SetName( aRootSO, aRootNames[aType] );
// Add new group to corresponding sub-tree
- int isEmpty = false;
+ int isEmpty = ( theMesh->NbNodes() == 0 );
std::string pm[2] = { "ICON_SMESH_TREE_GROUP", "ICON_SMESH_TREE_MESH_WARN" };
- if ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ))
- {
- pm[0] = "ICON_SMESH_TREE_GROUP_ON_FILTER";
- }
- else if ( SMESH::DownCast< SMESH_Group_i* > ( theGroup ))
+ if ( !isEmpty )
{
- if ( theGroup->GetType() == SMESH::NODE )
- isEmpty = ( theMesh->NbNodes() == 0 );
- else
+ if ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup )) // on filter
+ {
+ pm[0] = "ICON_SMESH_TREE_GROUP_ON_FILTER";
+
+ if ( theGroup->GetType() != SMESH::NODE )
+ {
+ isEmpty = true;
+ SMESH::array_of_ElementType_var allElemTypes = theMesh->GetTypes();
+ for ( size_t i =0; i < allElemTypes->length() && isEmpty; ++i )
+ isEmpty = ( allElemTypes[i] != theGroup->GetType() );
+ }
+ }
+ else // standalone or on geometry
{
- SMESH::array_of_ElementType_var allElemTypes = theMesh->GetTypes();
- for ( size_t i =0; i < allElemTypes->length() && isEmpty; ++i )
- isEmpty = ( allElemTypes[i] != theGroup->GetType() );
+ isEmpty = ( theGroup->Size() == 0 );
}
}
aGroupSO = publish ( theGroup, aRootSO, 0, pm[isEmpty].c_str() );
//=======================================================================
//function : PublishHypothesis
-//purpose :
+//purpose :
//=======================================================================
SALOMEDS::SObject_ptr
- SMESH_Gen_i::PublishHypothesis (SMESH::SMESH_Hypothesis_ptr theHyp,
- const char* theName)
+SMESH_Gen_i::PublishHypothesis (SMESH::SMESH_Hypothesis_ptr theHyp,
+ const char* theName)
{
- if(MYDEBUG) MESSAGE("PublishHypothesis")
+ if(MYDEBUG) MESSAGE("PublishHypothesis");
if ( !myIsEnablePublish )
return SALOMEDS::SObject::_nil();
if (theHyp->_is_nil())
}
}
+//=======================================================================
+//function : IsInvalid
+//purpose : Check object validity == absence of AttributeTextColor=(178,34,34)
+//=======================================================================
+
+bool SMESH_Gen_i::IsInvalid( SALOMEDS::SObject_ptr theSObject )
+{
+ bool isValid = true;
+ if ( !theSObject->_is_nil() )
+ {
+ SALOMEDS::GenericAttribute_wrap attr;
+ SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder();
+ if ( studyBuilder->FindAttribute( theSObject, attr.inout(), "AttributeTextColor" ))
+ {
+ SALOMEDS::AttributeTextColor_wrap colorAttr = attr;
+ SALOMEDS::Color color = colorAttr->TextColor();
+ isValid = ( color.R != 178 || color.G != 34 || color.B != 34 );
+ }
+ }
+ return isValid;
+}
+
//=======================================================================
//function : GetMeshOrSubmeshByShape
//purpose :
{
::SMESH_Group* aGroup = GetSmeshGroup();
if (aGroup)
- return CORBA::string_dup (aGroup->GetName());
+ return CORBA::string_dup( aGroup->GetName() );
return CORBA::string_dup( "NO_NAME" );
}
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
Standard_Real f,l;
BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
if ( paramOnEdge < f || paramOnEdge > l )
- THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
-
+ {
+ SMESH_Comment txt("Invalid paramOnEdge. It must vary in range [ ");
+ txt << f << ", " << l << " ]";
+ THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
+ }
mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
myMesh->SetIsModified( true );
v > surf.LastVParameter() );
if ( isOut ) {
-#ifdef _DEBUG_
- MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
- << " u( " << surf.FirstUParameter()
- << "," << surf.LastUParameter()
- << ") v( " << surf.FirstVParameter()
- << "," << surf.LastVParameter() << ")" );
-#endif
- THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
+ SMESH_Comment txt("Invalid UV. U must vary in range [ ");
+ txt << surf.FirstUParameter() << ", " << surf.LastUParameter() << " ], ";
+ txt << "V must vary in range [ ";
+ txt << surf.FirstVParameter() << ", " << surf.LastVParameter() << " ]";
+ THROW_SALOME_CORBA_EXCEPTION(txt.c_str(), SALOME::BAD_PARAM);
}
mesh->SetNodeOnFace( node, FaceID, u, v );
_impl = NULL;
_gen_i = gen_i;
_id = _idGenerator++;
+ _nbInvalidHypos= -1;
_editor = NULL;
_previewEditor = NULL;
_preMeshInfo = NULL;
if ( _preMeshInfo )
_preMeshInfo->ForgetOrLoad();
+ const int prevNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
+
std::string error;
SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
anErrorText = error.c_str();
if ( !SMESH_Hypothesis::IsStatusFatal(status) )
{
_gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
- _gen_i->UpdateIcons( mesh );
+
+ int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements();
+ if ( newNbMeshEnt != prevNbMeshEnt )
+ _gen_i->UpdateIcons( mesh );
}
if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
SMESH_Mesh_i* _mesh;
TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
- virtual void HypothesisModified (int theHypID) { _mesh->onHypothesisModified( theHypID ); }
+ virtual void HypothesisModified( int hypID,
+ bool updIcons) { _mesh->onHypothesisModified( hypID,
+ updIcons ); }
virtual void Load () { _mesh->Load(); }
+ virtual bool IsLoaded() { return _mesh->IsLoaded(); }
};
}
//================================================================================
/*!
- * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
+ * \brief callback from _impl to
+ * 1) forget not loaded mesh data (issue 0021208)
+ * 2) mark hypothesis as valid
*/
//================================================================================
-void SMESH_Mesh_i::onHypothesisModified(int theHypID)
+void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
{
if ( _preMeshInfo )
_preMeshInfo->ForgetOrLoad();
- SMESH::SMESH_Mesh_var mesh = _this();
- _gen_i->UpdateIcons( mesh );
+ if ( theUpdateIcons )
+ {
+ SMESH::SMESH_Mesh_var mesh = _this();
+ _gen_i->UpdateIcons( mesh );
+ }
- // mark a hypothesis as valid after edition
- SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
- SALOMEDS::SObject_wrap hypRoot;
- if ( !smeshComp->_is_nil() &&
- smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
+ if ( _nbInvalidHypos != 0 )
{
- SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
- for ( ; anIter->More(); anIter->Next() )
+ // mark a hypothesis as valid after edition
+ int nbInvalid = 0;
+ SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
+ SALOMEDS::SObject_wrap hypRoot;
+ if ( !smeshComp->_is_nil() &&
+ smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
{
- SALOMEDS::SObject_wrap hypSO = anIter->Value();
- CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
- SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
- if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
- _gen_i->HighLightInvalid( hyp, false );
+ SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
+ for ( ; anIter->More(); anIter->Next() )
+ {
+ SALOMEDS::SObject_wrap hypSO = anIter->Value();
+ CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO );
+ SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
+ if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
+ _gen_i->HighLightInvalid( hyp, false );
+ else
+ nbInvalid += _gen_i->IsInvalid( hypSO );
+ }
}
+ _nbInvalidHypos = nbInvalid;
}
}
const std::map<int, SMESH::SMESH_GroupBase_ptr>& getGroups() { return _mapGroups; }
// return existing group objects
- void onHypothesisModified(int theHypID);
+ void onHypothesisModified(int theHypID, bool updateIcons);
// callback from _impl to forget not loaded mesh data (issue 0021208)
- void checkMeshLoaded();
-
/*!
* \brief Update data if geometry changes
*
*/
TListOfListOfInt findConcurrentSubMeshes();
-private:
+ private:
static int _idGenerator;
::SMESH_Mesh* _impl; // :: force no namespace here
SMESH_Gen_i* _gen_i;
int _id; // id given by creator (unique within the creator instance)
+ int _nbInvalidHypos;
std::map<int, SMESH::SMESH_subMesh_ptr> _mapSubMeshIor;
std::map<int, SMESH::SMESH_GroupBase_ptr> _mapGroups;
std::map<int, SMESH::SMESH_Hypothesis_ptr> _mapHypo;
MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
// read nb nodes
- int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo ));
+ int nbNodes = Max( 0, aMed->GetNbNodes( medMeshInfo ));
if ( nbNodes > 0 )
{
setNb( SMDSEntity_Node, nbNodes);
void printException( const char* text )
{
#ifdef _DEBUG_
- cout << "Exception in SMESH_Gen_i::DumpPython(): " << text << endl;
+ std::cout << "Exception in SMESH_Gen_i::DumpPython(): " << text << std::endl;
#endif
}
//function : DumpPython
//purpose :
//=======================================================================
-Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Boolean isPublished,
+Engines::TMPFile* SMESH_Gen_i::DumpPython( CORBA::Boolean isPublished,
CORBA::Boolean isMultiFile,
CORBA::Boolean& isValidScript)
{
Algorithm type: Polygon Per Face 2D algorithm, see :class:`~StdMeshersBuilder.StdMeshersBuilder_PolygonPerFace`
"""
+POLYHEDRON = "PolyhedronPerSolid_3D"
+"""
+Algorithm type: Polyhedron Per Solid 3D algorithm, see :class:`~StdMeshersBuilder.StdMeshersBuilder_PolyhedronPerSolid`
+"""
+
# import items of enums
for e in StdMeshers.QuadType._items: exec('%s = StdMeshers.%s'%(e,e))
for e in StdMeshers.VLExtrusionMethod._items: exec('%s = StdMeshers.%s'%(e,e))
hyp.SetLength(length)
if not UseExisting:
# set preestimated length
+ import SMESH
gen = self.mesh.smeshpyD
initHyp = gen.GetHypothesisParameterValues("MaxLength", "libStdMeshersEngine.so",
self.mesh.GetMesh(), self.mesh.GetShape(),
- False) # <- byMesh
+ SMESH.HypInitParams( 1, 1.0, False ))
preHyp = initHyp._narrow(StdMeshers.StdMeshers_MaxLength)
if preHyp:
hyp.SetPreestimatedLength( preHyp.GetPreestimatedLength() )
pass
+class StdMeshersBuilder_PolyhedronPerSolid(Mesh_Algorithm):
+ """ Defines a Polyhedron Per Solid 3D algorithm.
+ It is created by calling smeshBuilder.Mesh.Polyhedron(geom=0)
+ """
+
+ meshMethod = "Polyhedron"
+ """
+ name of the dynamic method in smeshBuilder.Mesh class
+ """
+ algoType = POLYHEDRON
+ """
+ type of algorithm used with helper function in smeshBuilder.Mesh class
+ """
+ isDefault = True
+ """
+ flag pointing whether this algorithm should be used by default in dynamic method
+ of smeshBuilder.Mesh class
+ """
+ docHelper = "Create polyhedron 3D algorithm for solids"
+ """
+ doc string of the method
+ """
+
+ def __init__(self, mesh, geom=0):
+ """
+ Private constructor.
+
+ Parameters:
+ mesh: parent mesh object algorithm is assigned to
+ geom: geometry (shape/sub-shape) algorithm is assigned to;
+ if it is :code:`0` (default), the algorithm is assigned to the main shape
+ """
+ Mesh_Algorithm.__init__(self)
+ self.Create(mesh, geom, self.algoType)
+ pass
+
+ pass
+
class StdMeshersBuilder_UseExistingElements_1D(Mesh_Algorithm):
""" Defines a Use Existing Elements 1D algorithm.
return hyp
+ def GetHypothesisParameterValues( self, hypType, libName, mesh, shape, initParams ):
+ """
+ Create hypothesis initialized according to parameters
+
+ Parameters:
+ hypType (string): hypothesis type
+ libName (string): plug-in library name
+ mesh: optional mesh by which a hypotheses can initialize self
+ shape: optional geometry by size of which a hypotheses can initialize self
+ initParams: structure SMESH.HypInitParams defining how to initialize a hypothesis
+
+ Returns:
+ created hypothesis instance
+ """
+ if isinstance( mesh, Mesh ):
+ mesh = mesh.GetMesh()
+ if isinstance( initParams, (bool,int)):
+ initParams = SMESH.HypInitParams( not initParams, 1.0, not mesh )
+ return SMESH._objref_SMESH_Gen.GetHypothesisParameterValues(self, hypType, libName,
+ mesh, shape, initParams )
+
def GetMeshInfo(self, obj):
"""
Get the mesh statistic.
tgeo = str(shape.GetShapeType())
if tgeo == "VERTEX":
typ = NODE
- elif tgeo == "EDGE":
+ elif tgeo == "EDGE" or tgeo == "WIRE":
typ = EDGE
elif tgeo == "FACE" or tgeo == "SHELL":
typ = FACE
if genObj and hasattr( genObj, "UnRegister" ):
genObj.UnRegister()
-for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
+for pluginName in os.environ[ "SMESH_MeshersList" ].split( os.pathsep ):
"""
Bind methods creating mesher plug-ins to the Mesh class
"""
return shape.GetStudyEntry()
def ViscousLayers(self, thickness, numberOfLayers, stretchFactor,
- faces=[], isFacesToIgnore=True, extrMethod=StdMeshers.SURF_OFFSET_SMOOTH ):
+ faces=[], isFacesToIgnore=True,
+ extrMethod=StdMeshers.SURF_OFFSET_SMOOTH, groupName=""):
"""
Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
near mesh boundary. This hypothesis can be used by several 3D algorithms:
- StdMeshers.NODE_OFFSET method extrudes nodes along average normal of
surrounding mesh faces by the layers thickness. Thickness of
layers can be limited to avoid creation of invalid prisms.
+ groupName: name of a group to contain elements of layers. If not provided,
+ no group is created. The group is created upon mesh generation.
+ It can be retrieved by calling
+ ::
+
+ group = mesh.GetGroupByName( groupName, SMESH.VOLUME )[0]
+
+ Returns:
+ StdMeshers.StdMeshers_ViscousLayers hypothesis
"""
-
+
if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
raise TypeError("ViscousLayers are supported by 3D algorithms only")
if not "ViscousLayers" in self.GetCompatibleHypothesis():
hyp.SetStretchFactor( stretchFactor )
hyp.SetFaces( faces, isFacesToIgnore )
hyp.SetMethod( extrMethod )
+ hyp.SetGroupName( groupName )
self.mesh.AddHypothesis( hyp, self.geom )
return hyp
def ViscousLayers2D(self, thickness, numberOfLayers, stretchFactor,
- edges=[], isEdgesToIgnore=True ):
+ edges=[], isEdgesToIgnore=True, groupName="" ):
"""
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:
the value of **isEdgesToIgnore** parameter.
isEdgesToIgnore: if *True*, the Viscous layers are not generated on the
edges specified by the previous parameter (**edges**).
+ groupName: name of a group to contain elements of layers. If not provided,
+ no group is created. The group is created upon mesh generation.
+ It can be retrieved by calling
+ ::
+
+ group = mesh.GetGroupByName( groupName, SMESH.FACE )[0]
+
+ Returns:
+ StdMeshers.StdMeshers_ViscousLayers2D hypothesis
"""
if not isinstance(self.algo, SMESH._objref_SMESH_2D_Algo):
hyp.SetNumberLayers(numberOfLayers)
hyp.SetStretchFactor(stretchFactor)
hyp.SetEdges(edges, isEdgesToIgnore)
+ hyp.SetGroupName( groupName )
self.mesh.AddHypothesis( hyp, self.geom )
return hyp
StdMeshers_Cartesian_3D.hxx
StdMeshers_QuadFromMedialAxis_1D2D.hxx
StdMeshers_PolygonPerFace_2D.hxx
+ StdMeshers_PolyhedronPerSolid_3D.hxx
)
IF(SALOME_SMESH_ENABLE_MEFISTO)
StdMeshers_Adaptive1D.cxx
StdMeshers_QuadFromMedialAxis_1D2D.cxx
StdMeshers_PolygonPerFace_2D.cxx
+ StdMeshers_PolyhedronPerSolid_3D.cxx
)
IF(SALOME_SMESH_ENABLE_MEFISTO)
SMESH_Gen * gen)
: SMESH_Hypothesis(hypId, gen),
_sizeThreshold( 4.0 ), // default according to the customer specification
- _toAddEdges( false )
+ _toAddEdges( false ),
+ _toConsiderInternalFaces( false ),
+ _toUseThresholdForInternalFaces( false ),
+ _toCreateFaces( false )
{
_name = "CartesianParameters3D"; // used by "Cartesian_3D"
_param_algo_dim = 3; // 3D
return _toAddEdges;
}
+//=======================================================================
+//function : SetToConsiderInternalFaces
+//purpose : Enables treatment of geom faces either shared by solids or internal
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToConsiderInternalFaces(bool toTreat)
+{
+ if ( _toConsiderInternalFaces != toTreat )
+ {
+ _toConsiderInternalFaces = toTreat;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=======================================================================
+//function : SetToUseThresholdForInternalFaces
+//purpose : Enables applying size threshold to grid cells cut by internal geom faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToUseThresholdForInternalFaces(bool toUse)
+{
+ if ( _toUseThresholdForInternalFaces != toUse )
+ {
+ _toUseThresholdForInternalFaces = toUse;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
+//=======================================================================
+//function : SetToCreateFaces
+//purpose : Enables creation of mesh faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D::SetToCreateFaces(bool toCreate)
+{
+ if ( _toCreateFaces != toCreate )
+ {
+ _toCreateFaces = toCreate;
+ NotifySubMeshesHypothesisModification();
+ }
+}
+
//=======================================================================
//function : IsDefined
//purpose : Return true if parameters are well defined
for ( int i = 0; i < 3; ++i )
save << _fixedPoint[i] << " ";
+ save << " " << _toConsiderInternalFaces
+ << " " << _toUseThresholdForInternalFaces
+ << " " << _toCreateFaces;
+
return save;
}
for ( int i = 0; i < 3 && ok ; ++i )
ok = static_cast<bool>( load >> _fixedPoint[i]);
+ if ( load >> _toConsiderInternalFaces )
+ {
+ load >> _toUseThresholdForInternalFaces;
+ load >> _toCreateFaces;
+ }
+
return load;
}
void SetToAddEdges(bool toAdd);
bool GetToAddEdges() const;
+ /*!
+ * \brief Enables treatment of geom faces either shared by solids or internal.
+ */
+ void SetToConsiderInternalFaces(bool toTreat);
+ bool GetToConsiderInternalFaces() const { return _toConsiderInternalFaces; }
+
+ /*!
+ * \brief Enables applying size threshold to grid cells cut by internal geom faces.
+ */
+ void SetToUseThresholdForInternalFaces(bool toUse);
+ bool GetToUseThresholdForInternalFaces() const { return _toUseThresholdForInternalFaces; }
+
+ /*!
+ * \brief Enables creation of mesh faces.
+ */
+ void SetToCreateFaces(bool toCreate);
+ bool GetToCreateFaces() const { return _toCreateFaces; }
+
+
/*!
* \brief Return true if parameters are well defined
*/
double _sizeThreshold;
bool _toAddEdges;
+ bool _toConsiderInternalFaces;
+ bool _toUseThresholdForInternalFaces;
+ bool _toCreateFaces;
};
#endif
// Module : SMESH
//
#include "StdMeshers_Cartesian_3D.hxx"
+#include "StdMeshers_CartesianParameters3D.hxx"
+#include "ObjectPool.hxx"
#include "SMDS_MeshNode.hxx"
+#include "SMDS_VolumeTool.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Block.hxx"
#include "SMESH_Comment.hxx"
+#include "SMESH_ControlsDef.hxx"
#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_subMesh.hxx"
#include "SMESH_subMeshEventListener.hxx"
-#include "StdMeshers_CartesianParameters3D.hxx"
+#include "StdMeshers_FaceSide.hxx"
#include <utilities.h>
#include <Utils_ExceptHandlers.hxx>
#include <limits>
+#include <boost/container/flat_map.hpp>
+
//#undef WITH_TBB
#ifdef WITH_TBB
// Windows 10 = 0x0A00
#define WINVER 0x0A00
#define _WIN32_WINNT 0x0A00
-
#endif
#include <tbb/parallel_for.h>
#endif
using namespace std;
+using namespace SMESH;
#ifdef _DEBUG_
//#define _MY_DEBUG_
namespace
{
- typedef int TGeomID;
+ typedef int TGeomID; // IDs of sub-shapes
//=============================================================================
// Definitions of internal utils
Trans_TANGENT = IntCurveSurface_Tangent,
Trans_IN = IntCurveSurface_In,
Trans_OUT = IntCurveSurface_Out,
- Trans_APEX
+ Trans_APEX,
+ Trans_INTERNAL // for INTERNAL FACE
+ };
+ // --------------------------------------------------------------------------
+ /*!
+ * \brief Container of IDs of SOLID sub-shapes
+ */
+ class Solid // sole SOLID contains all sub-shapes
+ {
+ TGeomID _id; // SOLID id
+ bool _hasInternalFaces;
+ public:
+ virtual ~Solid() {}
+ virtual bool Contains( TGeomID subID ) const { return true; }
+ virtual bool ContainsAny( const vector< TGeomID>& subIDs ) const { return true; }
+ virtual TopAbs_Orientation Orientation( const TopoDS_Shape& s ) const { return s.Orientation(); }
+ virtual bool IsOutsideOriented( TGeomID faceID ) const { return true; }
+ void SetID( TGeomID id ) { _id = id; }
+ TGeomID ID() const { return _id; }
+ void SetHasInternalFaces( bool has ) { _hasInternalFaces = has; }
+ bool HasInternalFaces() const { return _hasInternalFaces; }
+ };
+ // --------------------------------------------------------------------------
+ class OneOfSolids : public Solid
+ {
+ TColStd_MapOfInteger _subIDs;
+ TopTools_MapOfShape _faces; // keep FACE orientation
+ TColStd_MapOfInteger _outFaceIDs; // FACEs of shape_to_mesh oriented outside the SOLID
+ public:
+ void Init( const TopoDS_Shape& solid,
+ TopAbs_ShapeEnum subType,
+ const SMESHDS_Mesh* mesh );
+ virtual bool Contains( TGeomID i ) const { return i == ID() || _subIDs.Contains( i ); }
+ virtual bool ContainsAny( const vector< TGeomID>& subIDs ) const
+ {
+ for ( size_t i = 0; i < subIDs.size(); ++i ) if ( Contains( subIDs[ i ])) return true;
+ return false;
+ }
+ virtual TopAbs_Orientation Orientation( const TopoDS_Shape& face ) const
+ {
+ const TopoDS_Shape& sInMap = const_cast< OneOfSolids* >(this)->_faces.Added( face );
+ return sInMap.Orientation();
+ }
+ virtual bool IsOutsideOriented( TGeomID faceID ) const
+ {
+ return faceID == 0 || _outFaceIDs.Contains( faceID );
+ }
+ };
+ // --------------------------------------------------------------------------
+ /*!
+ * \brief Geom data
+ */
+ struct Geometry
+ {
+ TopoDS_Shape _mainShape;
+ vector< vector< TGeomID > > _solidIDsByShapeID;// V/E/F ID -> SOLID IDs
+ Solid _soleSolid;
+ map< TGeomID, OneOfSolids > _solidByID;
+ TColStd_MapOfInteger _boundaryFaces; // FACEs on boundary of mesh->ShapeToMesh()
+ TColStd_MapOfInteger _strangeEdges; // EDGEs shared by strange FACEs
+ TGeomID _extIntFaceID; // pseudo FACE - extension of INTERNAL FACE
+
+ Controls::ElementsOnShape _edgeClassifier;
+ Controls::ElementsOnShape _vertexClassifier;
+
+ bool IsOneSolid() const { return _solidByID.size() < 2; }
};
// --------------------------------------------------------------------------
/*!
struct F_IntersectPoint : public B_IntersectPoint
{
double _paramOnLine;
+ double _u, _v;
mutable Transition _transition;
mutable size_t _indexOnLine;
{
gp_Pnt _point;
double _uvw[3];
- TGeomID _shapeID;
+ TGeomID _shapeID; // ID of EDGE or VERTEX
};
// --------------------------------------------------------------------------
/*!
multiset< F_IntersectPoint > _intPoints;
void RemoveExcessIntPoints( const double tol );
- bool GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut );
+ TGeomID GetSolidIDBefore( multiset< F_IntersectPoint >::iterator ip,
+ const TGeomID prevID,
+ const Geometry& geom);
};
// --------------------------------------------------------------------------
/*!
{
_size[0] = sz1; _size[1] = sz2; _size[2] = sz3;
_curInd[0] = _curInd[1] = _curInd[2] = 0;
- _iVar1 = iv1; _iVar2 = iv2; _iConst = iConst;
+ _iVar1 = iv1; _iVar2 = iv2; _iConst = iConst;
_name1 = nv1; _name2 = nv2; _nameConst = nConst;
}
vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes
vector< const F_IntersectPoint* > _gridIntP; // grid node intersection with geometry
-
- list< E_IntersectPoint > _edgeIntP; // intersections with EDGEs
- TopTools_IndexedMapOfShape _shapes;
-
+ ObjectPool< E_IntersectPoint > _edgeIntPool; // intersections with EDGEs
+ ObjectPool< F_IntersectPoint > _extIntPool; // intersections with extended INTERNAL FACEs
+ //list< E_IntersectPoint > _edgeIntP; // intersections with EDGEs
+
+ Geometry _geometry;
+ bool _toAddEdges;
+ bool _toCreateFaces;
+ bool _toConsiderInternalFaces;
+ bool _toUseThresholdForInternalFaces;
+ double _sizeThreshold;
+
+ vector< TGeomID > _shapeIDs; // returned by Hexahedron::getSolids()
SMESH_MesherHelper* _helper;
size_t CellIndex( size_t i, size_t j, size_t k ) const
LineIndexer GetLineIndexer(size_t iDir) const;
+ E_IntersectPoint* Add( const E_IntersectPoint& ip )
+ {
+ E_IntersectPoint* eip = _edgeIntPool.getNew();
+ *eip = ip;
+ return eip;
+ }
+ void Remove( E_IntersectPoint* eip ) { _edgeIntPool.destroy( eip ); }
+
+ TGeomID ShapeID( const TopoDS_Shape& s ) const;
+ const TopoDS_Shape& Shape( TGeomID id ) const;
+ TopAbs_ShapeEnum ShapeType( TGeomID id ) const { return Shape(id).ShapeType(); }
+ void InitGeometry( const TopoDS_Shape& theShape );
+ void InitClassifier( const TopoDS_Shape& mainShape,
+ TopAbs_ShapeEnum shapeType,
+ Controls::ElementsOnShape& classifier );
+ void GetEdgesToImplement( map< TGeomID, vector< TGeomID > > & edge2faceMap,
+ const TopoDS_Shape& shape,
+ const vector< TopoDS_Shape >& faces );
+ void SetSolidFather( const TopoDS_Shape& s, const TopoDS_Shape& theShapeToMesh );
+ bool IsShared( TGeomID faceID ) const;
+ bool IsAnyShared( const std::vector< TGeomID >& faceIDs ) const;
+ bool IsInternal( TGeomID faceID ) const {
+ return ( faceID == PseudoIntExtFaceID() ||
+ Shape( faceID ).Orientation() == TopAbs_INTERNAL ); }
+ bool IsSolid( TGeomID shapeID ) const {
+ if ( _geometry.IsOneSolid() ) return _geometry._soleSolid.ID() == shapeID;
+ else return _geometry._solidByID.count( shapeID ); }
+ bool IsStrangeEdge( TGeomID id ) const { return _geometry._strangeEdges.Contains( id ); }
+ TGeomID PseudoIntExtFaceID() const { return _geometry._extIntFaceID; }
+ Solid* GetSolid( TGeomID solidID = 0 );
+ Solid* GetOneOfSolids( TGeomID solidID );
+ const vector< TGeomID > & GetSolidIDs( TGeomID subShapeID ) const;
+ bool IsCorrectTransition( TGeomID faceID, const Solid* solid );
+ bool IsBoundaryFace( TGeomID face ) const { return _geometry._boundaryFaces.Contains( face ); }
+ void SetOnShape( const SMDS_MeshNode* n, const F_IntersectPoint& ip, bool unset=false );
+ bool IsToCheckNodePos() const { return !_toAddEdges && _toCreateFaces; }
+
void SetCoordinates(const vector<double>& xCoords,
const vector<double>& yCoords,
const vector<double>& zCoords,
void ComputeNodes(SMESH_MesherHelper& helper);
};
// --------------------------------------------------------------------------
+ /*!
+ * \brief Return cells sharing a link
+ */
+ struct CellsAroundLink
+ {
+ int _dInd[4][3];
+ size_t _nbCells[3];
+ int _i,_j,_k;
+ Grid* _grid;
+
+ CellsAroundLink( Grid* grid, int iDir ):
+ _dInd{ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} },
+ _nbCells{ grid->_coords[0].size() - 1,
+ grid->_coords[1].size() - 1,
+ grid->_coords[2].size() - 1 },
+ _grid( grid )
+ {
+ const int iDirOther[3][2] = {{ 1,2 },{ 0,2 },{ 0,1 }};
+ _dInd[1][ iDirOther[iDir][0] ] = -1;
+ _dInd[2][ iDirOther[iDir][1] ] = -1;
+ _dInd[3][ iDirOther[iDir][0] ] = -1; _dInd[3][ iDirOther[iDir][1] ] = -1;
+ }
+ void Init( int i, int j, int k, int link12 = 0 )
+ {
+ int iL = link12 % 4;
+ _i = i - _dInd[iL][0];
+ _j = j - _dInd[iL][1];
+ _k = k - _dInd[iL][2];
+ }
+ bool GetCell( int iL, int& i, int& j, int& k, int& cellIndex )
+ {
+ i = _i + _dInd[iL][0];
+ j = _j + _dInd[iL][1];
+ k = _k + _dInd[iL][2];
+ if ( i < 0 || i >= (int)_nbCells[0] ||
+ j < 0 || j >= (int)_nbCells[1] ||
+ k < 0 || k >= (int)_nbCells[2] )
+ return false;
+ cellIndex = _grid->CellIndex( i,j,k );
+ return true;
+ }
+ };
+ // --------------------------------------------------------------------------
/*!
* \brief Intersector of TopoDS_Face with all GridLine's
*/
{
for ( size_t i = 0; i < _intersections.size(); ++i )
{
- multiset< F_IntersectPoint >::iterator ip =
+ multiset< F_IntersectPoint >::iterator ip =
_intersections[i].first->_intPoints.insert( _intersections[i].second );
ip->_faceIDs.reserve( 1 );
ip->_faceIDs.push_back( _faceID );
{
double _tol;
double _u, _v, _w; // params on the face and the line
- Transition _transition; // transition of at intersection (see IntCurveSurface.cdl)
+ Transition _transition; // transition at intersection (see IntCurveSurface.cdl)
Transition _transIn, _transOut; // IN and OUT transitions depending of face orientation
gp_Pln _plane;
// --------------------------------------------------------------------------------
struct _Face;
struct _Link;
+ enum IsInternalFlag { IS_NOT_INTERNAL, IS_INTERNAL, IS_CUT_BY_INTERNAL_FACE };
// --------------------------------------------------------------------------------
struct _Node //!< node either at a hexahedron corner or at intersection
{
const SMDS_MeshNode* _node; // mesh node at hexahedron corner
const B_IntersectPoint* _intPoint;
const _Face* _usedInFace;
+ char _isInternalFlags;
_Node(const SMDS_MeshNode* n=0, const B_IntersectPoint* ip=0)
- :_node(n), _intPoint(ip), _usedInFace(0) {}
+ :_node(n), _intPoint(ip), _usedInFace(0), _isInternalFlags(0) {}
const SMDS_MeshNode* Node() const
{ return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; }
const E_IntersectPoint* EdgeIntPnt() const
{ return static_cast< const E_IntersectPoint* >( _intPoint ); }
+ const F_IntersectPoint* FaceIntPnt() const
+ { return static_cast< const F_IntersectPoint* >( _intPoint ); }
+ const vector< TGeomID >& faces() const { return _intPoint->_faceIDs; }
+ TGeomID face(size_t i) const { return _intPoint->_faceIDs[ i ]; }
+ void SetInternal( IsInternalFlag intFlag ) { _isInternalFlags |= intFlag; }
+ bool IsCutByInternal() const { return _isInternalFlags & IS_CUT_BY_INTERNAL_FACE; }
bool IsUsedInFace( const _Face* polygon = 0 )
{
return polygon ? ( _usedInFace == polygon ) : bool( _usedInFace );
}
- void Add( const E_IntersectPoint* ip )
- {
- if ( !_intPoint ) {
- _intPoint = ip;
- }
- else if ( !_intPoint->_node ) {
- ip->Add( _intPoint->_faceIDs );
- _intPoint = ip;
- }
- else {
- _intPoint->Add( ip->_faceIDs );
- }
- }
TGeomID IsLinked( const B_IntersectPoint* other,
TGeomID avoidFace=-1 ) const // returns id of a common face
{
gp_Pnt Point() const
{
if ( const SMDS_MeshNode* n = Node() )
- return SMESH_TNodeXYZ( n );
+ return SMESH_NodeXYZ( n );
if ( const E_IntersectPoint* eip =
dynamic_cast< const E_IntersectPoint* >( _intPoint ))
return eip->_point;
return eip->_shapeID;
return 0;
}
+ void Add( const E_IntersectPoint* ip )
+ {
+ // Possible cases before Add(ip):
+ /// 1) _node != 0 --> _Node at hex corner ( _intPoint == 0 || _intPoint._node == 0 )
+ /// 2) _node == 0 && _intPoint._node != 0 --> link intersected by FACE
+ /// 3) _node == 0 && _intPoint._node == 0 --> _Node at EDGE intersection
+ //
+ // If ip is added in cases 1) and 2) _node position must be changed to ip._shapeID
+ // at creation of elements
+ // To recognize this case, set _intPoint._node = Node()
+ const SMDS_MeshNode* node = Node();
+ if ( !_intPoint ) {
+ _intPoint = ip;
+ }
+ else {
+ ip->Add( _intPoint->_faceIDs );
+ _intPoint = ip;
+ }
+ if ( node )
+ _node = _intPoint->_node = node;
+ }
};
// --------------------------------------------------------------------------------
struct _Link // link connecting two _Node's
vector< const F_IntersectPoint* > _fIntPoints; // GridLine intersections with FACEs
vector< _Node* > _fIntNodes; // _Node's at _fIntPoints
vector< _Link > _splits;
- _Link() { _faces[0] = 0; }
+ _Link(): _faces{ 0, 0 } {}
};
// --------------------------------------------------------------------------------
struct _OrientedLink
}
};
// --------------------------------------------------------------------------------
+ struct _SplitIterator //! set to _hexLinks splits on one side of INTERNAL FACEs
+ {
+ struct _Split // data of a link split
+ {
+ int _linkID; // hex link ID
+ _Node* _nodes[2];
+ int _iCheckIteration; // iteration where split is tried as Hexahedron split
+ _Link* _checkedSplit; // split set to hex links
+ bool _isUsed; // used in a volume
+
+ _Split( _Link & split, int iLink ):
+ _linkID( iLink ), _nodes{ split._nodes[0], split._nodes[1] },
+ _iCheckIteration( 0 ), _isUsed( false )
+ {}
+ bool IsCheckedOrUsed( bool used ) const { return used ? _isUsed : _iCheckIteration > 0; }
+ };
+ _Link* _hexLinks;
+ std::vector< _Split > _splits;
+ int _iterationNb;
+ size_t _nbChecked;
+ size_t _nbUsed;
+ std::vector< _Node* > _freeNodes; // nodes reached while composing a split set
+
+ _SplitIterator( _Link* hexLinks ):
+ _hexLinks( hexLinks ), _iterationNb(0), _nbChecked(0), _nbUsed(0)
+ {
+ _freeNodes.reserve( 12 );
+ _splits.reserve( 24 );
+ for ( int iL = 0; iL < 12; ++iL )
+ for ( size_t iS = 0; iS < _hexLinks[ iL ]._splits.size(); ++iS )
+ _splits.emplace_back( _hexLinks[ iL ]._splits[ iS ], iL );
+ Next();
+ }
+ bool More() const { return _nbUsed < _splits.size(); }
+ bool Next();
+ };
+ // --------------------------------------------------------------------------------
struct _Face
{
vector< _OrientedLink > _links; // links on GridLine's
// --------------------------------------------------------------------------------
struct _volumeDef // holder of nodes of a volume mesh element
{
- vector< _Node* > _nodes;
- vector< int > _quantities;
- typedef boost::shared_ptr<_volumeDef> Ptr;
- void set( const vector< _Node* >& nodes,
- const vector< int >& quant = vector< int >() )
- { _nodes = nodes; _quantities = quant; }
- void set( _Node** nodes, int nb )
+ struct _nodeDef
+ {
+ const SMDS_MeshNode* _node; // mesh node at hexahedron corner
+ const B_IntersectPoint* _intPoint;
+
+ _nodeDef( _Node* n ): _node( n->_node), _intPoint( n->_intPoint ) {}
+ const SMDS_MeshNode* Node() const
+ { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; }
+ const E_IntersectPoint* EdgeIntPnt() const
+ { return static_cast< const E_IntersectPoint* >( _intPoint ); }
+ };
+ vector< _nodeDef > _nodes;
+ vector< int > _quantities;
+ _volumeDef* _next; // to store several _volumeDefs in a chain
+ TGeomID _solidID;
+ const SMDS_MeshElement* _volume; // new volume
+
+ _volumeDef(): _next(0), _solidID(0), _volume(0) {}
+ ~_volumeDef() { delete _next; }
+ _volumeDef( _volumeDef& other ):
+ _next(0), _solidID( other._solidID ), _volume( other._volume )
+ { _nodes.swap( other._nodes ); _quantities.swap( other._quantities ); other._volume = 0; }
+
+ void Set( const vector< _Node* >& nodes, const vector< int >& quant = vector< int >() )
+ { _nodes.assign( nodes.begin(), nodes.end() ); _quantities = quant; }
+
+ void Set( _Node** nodes, int nb )
{ _nodes.assign( nodes, nodes + nb ); }
+
+ void SetNext( _volumeDef* vd )
+ { if ( _next ) { _next->SetNext( vd ); } else { _next = vd; }}
};
// topology of a hexahedron
vector< _Node* > _vIntNodes;
// computed volume elements
- //vector< _volumeDef::Ptr > _volumeDefs;
_volumeDef _volumeDefs;
Grid* _grid;
- double _sizeThreshold, _sideLength[3];
+ double _sideLength[3];
int _nbCornerNodes, _nbFaceIntNodes, _nbBndNodes;
int _origNodeInd; // index of _hexNodes[0] node within the _grid
size_t _i,_j,_k;
+ bool _hasTooSmall;
+
+#ifdef _DEBUG_
+ int _cellID;
+#endif
public:
- Hexahedron(const double sizeThreshold, Grid* grid);
+ Hexahedron(Grid* grid);
int MakeElements(SMESH_MesherHelper& helper,
const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
- void ComputeElements();
- void Init() { init( _i, _j, _k ); }
+ void ComputeElements( const Solid* solid = 0, int solidIndex = -1 );
private:
- Hexahedron(const Hexahedron& other );
- void init( size_t i, size_t j, size_t k );
+ Hexahedron(const Hexahedron& other, size_t i, size_t j, size_t k, int cellID );
+ void init( size_t i, size_t j, size_t k, const Solid* solid=0 );
void init( size_t i );
+ void setIJK( size_t i );
+ bool compute( const Solid* solid, const IsInternalFlag intFlag );
+ const vector< TGeomID >& getSolids();
+ bool isCutByInternalFace( IsInternalFlag & maxFlag );
void addEdges(SMESH_MesherHelper& helper,
vector< Hexahedron* >& intersectedHex,
const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap);
double proj, BRepAdaptor_Curve& curve,
const gp_XYZ& axis, const gp_XYZ& origin );
int getEntity( const E_IntersectPoint* ip, int* facets, int& sub );
- bool addIntersection( const E_IntersectPoint& ip,
+ bool addIntersection( const E_IntersectPoint* ip,
vector< Hexahedron* >& hexes,
int ijk[], int dIJK[] );
bool findChain( _Node* n1, _Node* n2, _Face& quad, vector<_Node*>& chainNodes );
size_t & iS,
_Face& quad,
vector<_Node*>& chn);
- int addElements(SMESH_MesherHelper& helper);
- bool isOutPoint( _Link& link, int iP, SMESH_MesherHelper& helper ) const;
+ int addVolumes(SMESH_MesherHelper& helper );
+ void addFaces( SMESH_MesherHelper& helper,
+ const vector< const SMDS_MeshElement* > & boundaryVolumes );
+ void addSegments( SMESH_MesherHelper& helper,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap );
+ void getVolumes( vector< const SMDS_MeshElement* > & volumes );
+ void getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryVolumes );
+ TGeomID getAnyFace() const;
+ void cutByExtendedInternal( std::vector< Hexahedron* >& hexes,
+ const TColStd_MapOfInteger& intEdgeIDs );
+ gp_Pnt mostDistantInternalPnt( int hexIndex, const gp_Pnt& p1, const gp_Pnt& p2 );
+ bool isOutPoint( _Link& link, int iP, SMESH_MesherHelper& helper, const Solid* solid ) const;
void sortVertexNodes(vector<_Node*>& nodes, _Node* curNode, TGeomID face);
bool isInHole() const;
- bool checkPolyhedronSize() const;
+ bool hasStrangeEdge() const;
+ bool checkPolyhedronSize( bool isCutByInternalFace ) const;
bool addHexa ();
bool addTetra();
bool addPenta();
return nodes[i];
return 0;
}
- bool isImplementEdges() const { return !_grid->_edgeIntP.empty(); }
+ bool isImplementEdges() const { return _grid->_edgeIntPool.nbElements(); }
bool isOutParam(const double uvw[3]) const;
+
+ typedef boost::container::flat_map< TGeomID, size_t > TID2Nb;
+ static void insertAndIncrement( TGeomID id, TID2Nb& id2nbMap )
+ {
+ TID2Nb::value_type s0( id, 0 );
+ TID2Nb::iterator id2nb = id2nbMap.insert( s0 ).first;
+ id2nb->second++;
+ }
};
#ifdef WITH_TBB
}
//================================================================================
/*
- * Return "is OUT" state for nodes before the given intersection point
+ * Return ID of SOLID for nodes before the given intersection point
*/
- bool GridLine::GetIsOutBefore( multiset< F_IntersectPoint >::iterator ip, bool prevIsOut )
+ TGeomID GridLine::GetSolidIDBefore( multiset< F_IntersectPoint >::iterator ip,
+ const TGeomID prevID,
+ const Geometry& geom )
{
- if ( ip->_transition == Trans_IN )
- return true;
- if ( ip->_transition == Trans_OUT )
- return false;
- if ( ip->_transition == Trans_APEX )
+ if ( ip == _intPoints.begin() )
+ return 0;
+
+ if ( geom.IsOneSolid() )
{
- // singularity point (apex of a cone)
- if ( _intPoints.size() == 1 || ip == _intPoints.begin() )
- return true;
- multiset< F_IntersectPoint >::iterator ipBef = ip, ipAft = ++ip;
- if ( ipAft == _intPoints.end() )
- return false;
- --ipBef;
- if ( ipBef->_transition != ipAft->_transition )
- return ( ipBef->_transition == Trans_OUT );
- return ( ipBef->_transition != Trans_OUT );
+ bool isOut = true;
+ switch ( ip->_transition ) {
+ case Trans_IN: isOut = true; break;
+ case Trans_OUT: isOut = false; break;
+ case Trans_TANGENT: isOut = ( prevID == 0 ); break;
+ case Trans_APEX:
+ {
+ // singularity point (apex of a cone)
+ multiset< F_IntersectPoint >::iterator ipBef = ip, ipAft = ++ip;
+ if ( ipAft == _intPoints.end() )
+ isOut = false;
+ else
+ {
+ --ipBef;
+ if ( ipBef->_transition != ipAft->_transition )
+ isOut = ( ipBef->_transition == Trans_OUT );
+ else
+ isOut = ( ipBef->_transition != Trans_OUT );
+ }
+ break;
+ }
+ case Trans_INTERNAL: isOut = false;
+ default:;
+ }
+ return isOut ? 0 : geom._soleSolid.ID();
+ }
+
+ const vector< TGeomID >& solids = geom._solidIDsByShapeID[ ip->_faceIDs[ 0 ]];
+
+ --ip;
+ if ( ip->_transition == Trans_INTERNAL )
+ return prevID;
+
+ const vector< TGeomID >& solidsBef = geom._solidIDsByShapeID[ ip->_faceIDs[ 0 ]];
+
+ if ( ip->_transition == Trans_IN ||
+ ip->_transition == Trans_OUT )
+ {
+ if ( solidsBef.size() == 1 )
+ return ( solidsBef[0] == prevID ) ? 0 : solidsBef[0];
+
+ return solidsBef[ solidsBef[0] == prevID ];
+ }
+
+ if ( solidsBef.size() == 1 )
+ return solidsBef[0];
+
+ for ( size_t i = 0; i < solids.size(); ++i )
+ {
+ vector< TGeomID >::const_iterator it =
+ std::find( solidsBef.begin(), solidsBef.end(), solids[i] );
+ if ( it != solidsBef.end() )
+ return solids[i];
}
- // _transition == Trans_TANGENT
- return !prevIsOut;
+ return 0;
}
//================================================================================
/*
return ( it != _faceIDs.end() );
}
//================================================================================
+ /*
+ * OneOfSolids initialization
+ */
+ void OneOfSolids::Init( const TopoDS_Shape& solid,
+ TopAbs_ShapeEnum subType,
+ const SMESHDS_Mesh* mesh )
+ {
+ SetID( mesh->ShapeToIndex( solid ));
+
+ if ( subType == TopAbs_FACE )
+ SetHasInternalFaces( false );
+
+ for ( TopExp_Explorer sub( solid, subType ); sub.More(); sub.Next() )
+ {
+ _subIDs.Add( mesh->ShapeToIndex( sub.Current() ));
+ if ( subType == TopAbs_FACE )
+ {
+ _faces.Add( sub.Current() );
+ if ( sub.Current().Orientation() == TopAbs_INTERNAL )
+ SetHasInternalFaces( true );
+
+ TGeomID faceID = mesh->ShapeToIndex( sub.Current() );
+ if ( sub.Current().Orientation() == TopAbs_INTERNAL ||
+ sub.Current().Orientation() == mesh->IndexToShape( faceID ).Orientation() )
+ _outFaceIDs.Add( faceID );
+ }
+ }
+ }
+ //================================================================================
/*
* Return an iterator on GridLine's in a given direction
*/
}
}
}
+ //================================================================================
+ /*
+ * Return local ID of shape
+ */
+ TGeomID Grid::ShapeID( const TopoDS_Shape& s ) const
+ {
+ return _helper->GetMeshDS()->ShapeToIndex( s );
+ }
+ //================================================================================
+ /*
+ * Return a shape by its local ID
+ */
+ const TopoDS_Shape& Grid::Shape( TGeomID id ) const
+ {
+ return _helper->GetMeshDS()->IndexToShape( id );
+ }
+ //================================================================================
+ /*
+ * Initialize _geometry
+ */
+ void Grid::InitGeometry( const TopoDS_Shape& theShapeToMesh )
+ {
+ SMESH_Mesh* mesh = _helper->GetMesh();
+
+ _geometry._mainShape = theShapeToMesh;
+ _geometry._extIntFaceID = mesh->GetMeshDS()->MaxShapeIndex() * 100;
+ _geometry._soleSolid.SetID( 0 );
+ _geometry._soleSolid.SetHasInternalFaces( false );
+
+ InitClassifier( theShapeToMesh, TopAbs_VERTEX, _geometry._vertexClassifier );
+ InitClassifier( theShapeToMesh, TopAbs_EDGE , _geometry._edgeClassifier );
+
+ TopExp_Explorer solidExp( theShapeToMesh, TopAbs_SOLID );
+
+ bool isSeveralSolids = false;
+ if ( _toConsiderInternalFaces ) // check nb SOLIDs
+ {
+ solidExp.Next();
+ isSeveralSolids = solidExp.More();
+ _toConsiderInternalFaces = isSeveralSolids;
+ solidExp.ReInit();
+
+ if ( !isSeveralSolids ) // look for an internal FACE
+ {
+ TopExp_Explorer fExp( theShapeToMesh, TopAbs_FACE );
+ for ( ; fExp.More() && !_toConsiderInternalFaces; fExp.Next() )
+ _toConsiderInternalFaces = ( fExp.Current().Orientation() == TopAbs_INTERNAL );
+
+ _geometry._soleSolid.SetHasInternalFaces( _toConsiderInternalFaces );
+ _geometry._soleSolid.SetID( ShapeID( solidExp.Current() ));
+ }
+ else // fill Geometry::_solidByID
+ {
+ for ( ; solidExp.More(); solidExp.Next() )
+ {
+ OneOfSolids & solid = _geometry._solidByID[ ShapeID( solidExp.Current() )];
+ solid.Init( solidExp.Current(), TopAbs_FACE, mesh->GetMeshDS() );
+ solid.Init( solidExp.Current(), TopAbs_EDGE, mesh->GetMeshDS() );
+ solid.Init( solidExp.Current(), TopAbs_VERTEX, mesh->GetMeshDS() );
+ }
+ }
+ }
+ else
+ {
+ _geometry._soleSolid.SetID( ShapeID( solidExp.Current() ));
+ }
+
+ if ( !_toCreateFaces )
+ {
+ int nbSolidsGlobal = _helper->Count( mesh->GetShapeToMesh(), TopAbs_SOLID, false );
+ int nbSolidsLocal = _helper->Count( theShapeToMesh, TopAbs_SOLID, false );
+ _toCreateFaces = ( nbSolidsLocal < nbSolidsGlobal );
+ }
+
+ TopTools_IndexedMapOfShape faces;
+ if ( _toCreateFaces || isSeveralSolids )
+ TopExp::MapShapes( theShapeToMesh, TopAbs_FACE, faces );
+
+ // find boundary FACEs on boundary of mesh->ShapeToMesh()
+ if ( _toCreateFaces )
+ for ( int i = 1; i <= faces.Size(); ++i )
+ if ( faces(i).Orientation() != TopAbs_INTERNAL &&
+ _helper->NbAncestors( faces(i), *mesh, TopAbs_SOLID ) == 1 )
+ {
+ _geometry._boundaryFaces.Add( ShapeID( faces(i) ));
+ }
+
+ if ( isSeveralSolids )
+ for ( int i = 1; i <= faces.Size(); ++i )
+ {
+ SetSolidFather( faces(i), theShapeToMesh );
+ for ( TopExp_Explorer eExp( faces(i), TopAbs_EDGE ); eExp.More(); eExp.Next() )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() );
+ SetSolidFather( edge, theShapeToMesh );
+ SetSolidFather( _helper->IthVertex( 0, edge ), theShapeToMesh );
+ SetSolidFather( _helper->IthVertex( 1, edge ), theShapeToMesh );
+ }
+ }
+ return;
+ }
+ //================================================================================
+ /*
+ * Store ID of SOLID as father of its child shape ID
+ */
+ void Grid::SetSolidFather( const TopoDS_Shape& s, const TopoDS_Shape& theShapeToMesh )
+ {
+ if ( _geometry._solidIDsByShapeID.empty() )
+ _geometry._solidIDsByShapeID.resize( _helper->GetMeshDS()->MaxShapeIndex() + 1 );
+
+ vector< TGeomID > & solidIDs = _geometry._solidIDsByShapeID[ ShapeID( s )];
+ if ( !solidIDs.empty() )
+ return;
+ solidIDs.reserve(2);
+ PShapeIteratorPtr solidIt = _helper->GetAncestors( s,
+ *_helper->GetMesh(),
+ TopAbs_SOLID,
+ & theShapeToMesh );
+ while ( const TopoDS_Shape* solid = solidIt->next() )
+ solidIDs.push_back( ShapeID( *solid ));
+ }
+ //================================================================================
+ /*
+ * Return IDs of solids given sub-shape belongs to
+ */
+ const vector< TGeomID > & Grid::GetSolidIDs( TGeomID subShapeID ) const
+ {
+ return _geometry._solidIDsByShapeID[ subShapeID ];
+ }
+ //================================================================================
+ /*
+ * Check if a sub-shape belongs to several SOLIDs
+ */
+ bool Grid::IsShared( TGeomID shapeID ) const
+ {
+ return !_geometry.IsOneSolid() && ( _geometry._solidIDsByShapeID[ shapeID ].size() > 1 );
+ }
+ //================================================================================
+ /*
+ * Check if any of FACEs belongs to several SOLIDs
+ */
+ bool Grid::IsAnyShared( const std::vector< TGeomID >& faceIDs ) const
+ {
+ for ( size_t i = 0; i < faceIDs.size(); ++i )
+ if ( IsShared( faceIDs[ i ]))
+ return true;
+ return false;
+ }
+ //================================================================================
+ /*
+ * Return Solid by ID
+ */
+ Solid* Grid::GetSolid( TGeomID solidID )
+ {
+ if ( !solidID || _geometry.IsOneSolid() || _geometry._solidByID.empty() )
+ return & _geometry._soleSolid;
+
+ return & _geometry._solidByID[ solidID ];
+ }
+ //================================================================================
+ /*
+ * Return OneOfSolids by ID
+ */
+ Solid* Grid::GetOneOfSolids( TGeomID solidID )
+ {
+ map< TGeomID, OneOfSolids >::iterator is2s = _geometry._solidByID.find( solidID );
+ if ( is2s != _geometry._solidByID.end() )
+ return & is2s->second;
+
+ return & _geometry._soleSolid;
+ }
+ //================================================================================
+ /*
+ * Check if transition on given FACE is correct for a given SOLID
+ */
+ bool Grid::IsCorrectTransition( TGeomID faceID, const Solid* solid )
+ {
+ if ( _geometry.IsOneSolid() )
+ return true;
+
+ const vector< TGeomID >& solidIDs = _geometry._solidIDsByShapeID[ faceID ];
+ return solidIDs[0] == solid->ID();
+ }
+
+ //================================================================================
+ /*
+ * Assign to geometry a node at FACE intersection
+ */
+ void Grid::SetOnShape( const SMDS_MeshNode* n, const F_IntersectPoint& ip, bool unset )
+ {
+ TopoDS_Shape s;
+ SMESHDS_Mesh* mesh = _helper->GetMeshDS();
+ if ( ip._faceIDs.size() == 1 )
+ {
+ mesh->SetNodeOnFace( n, ip._faceIDs[0], ip._u, ip._v );
+ }
+ else if ( _geometry._vertexClassifier.IsSatisfy( n, &s ))
+ {
+ if ( unset ) mesh->UnSetNodeOnShape( n );
+ mesh->SetNodeOnVertex( n, TopoDS::Vertex( s ));
+ }
+ else if ( _geometry._edgeClassifier.IsSatisfy( n, &s ))
+ {
+ if ( unset ) mesh->UnSetNodeOnShape( n );
+ mesh->SetNodeOnEdge( n, TopoDS::Edge( s ));
+ }
+ else if ( ip._faceIDs.size() > 0 )
+ {
+ mesh->SetNodeOnFace( n, ip._faceIDs[0], ip._u, ip._v );
+ }
+ else if ( !unset && _geometry.IsOneSolid() )
+ {
+ mesh->SetNodeInVolume( n, _geometry._soleSolid.ID() );
+ }
+ }
+ //================================================================================
+ /*
+ * Initialize a classifier
+ */
+ void Grid::InitClassifier( const TopoDS_Shape& mainShape,
+ TopAbs_ShapeEnum shapeType,
+ Controls::ElementsOnShape& classifier )
+ {
+ TopTools_IndexedMapOfShape shapes;
+ TopExp::MapShapes( mainShape, shapeType, shapes );
+
+ TopoDS_Compound compound; BRep_Builder builder;
+ builder.MakeCompound( compound );
+ for ( int i = 1; i <= shapes.Size(); ++i )
+ builder.Add( compound, shapes(i) );
+
+ classifier.SetMesh( _helper->GetMeshDS() );
+ //classifier.SetTolerance( _tol ); // _tol is not initialised
+ classifier.SetShape( compound, SMDSAbs_Node );
+ }
+
+ //================================================================================
+ /*
+ * Return EDGEs with FACEs to implement into the mesh
+ */
+ void Grid::GetEdgesToImplement( map< TGeomID, vector< TGeomID > > & edge2faceIDsMap,
+ const TopoDS_Shape& shape,
+ const vector< TopoDS_Shape >& faces )
+ {
+ // check if there are strange EDGEs
+ TopTools_IndexedMapOfShape faceMap;
+ TopExp::MapShapes( _helper->GetMesh()->GetShapeToMesh(), TopAbs_FACE, faceMap );
+ int nbFacesGlobal = faceMap.Size();
+ faceMap.Clear( false );
+ TopExp::MapShapes( shape, TopAbs_FACE, faceMap );
+ int nbFacesLocal = faceMap.Size();
+ bool hasStrangeEdges = ( nbFacesGlobal > nbFacesLocal );
+ if ( !_toAddEdges && !hasStrangeEdges )
+ return; // no FACEs in contact with those meshed by other algo
+
+ for ( size_t i = 0; i < faces.size(); ++i )
+ {
+ _helper->SetSubShape( faces[i] );
+ for ( TopExp_Explorer eExp( faces[i], TopAbs_EDGE ); eExp.More(); eExp.Next() )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() );
+ if ( hasStrangeEdges )
+ {
+ bool hasStrangeFace = false;
+ PShapeIteratorPtr faceIt = _helper->GetAncestors( edge, *_helper->GetMesh(), TopAbs_FACE);
+ while ( const TopoDS_Shape* face = faceIt->next() )
+ if (( hasStrangeFace = !faceMap.Contains( *face )))
+ break;
+ if ( !hasStrangeFace && !_toAddEdges )
+ continue;
+ _geometry._strangeEdges.Add( ShapeID( edge ));
+ _geometry._strangeEdges.Add( ShapeID( _helper->IthVertex( 0, edge )));
+ _geometry._strangeEdges.Add( ShapeID( _helper->IthVertex( 1, edge )));
+ }
+ if ( !SMESH_Algo::isDegenerated( edge ) &&
+ !_helper->IsRealSeam( edge ))
+ {
+ edge2faceIDsMap[ ShapeID( edge )].push_back( ShapeID( faces[i] ));
+ }
+ }
+ }
+ return;
+ }
+
//================================================================================
/*
* Computes coordinates of a point in the grid CS
{
// state of each node of the grid relative to the geometry
const size_t nbGridNodes = _coords[0].size() * _coords[1].size() * _coords[2].size();
- vector< bool > isNodeOut( nbGridNodes, false );
+ const TGeomID undefID = 1e+9;
+ vector< TGeomID > shapeIDVec( nbGridNodes, undefID );
_nodes.resize( nbGridNodes, 0 );
_gridIntP.resize( nbGridNodes, NULL );
+ SMESHDS_Mesh* mesh = helper.GetMeshDS();
+
for ( int iDir = 0; iDir < 3; ++iDir ) // loop on 3 line directions
{
LineIndexer li = GetLineIndexer( iDir );
GridLine& line = _lines[ iDir ][ li.LineIndex() ];
const gp_XYZ lineLoc = line._line.Location().XYZ();
const gp_XYZ lineDir = line._line.Direction().XYZ();
+
line.RemoveExcessIntPoints( _tol );
- multiset< F_IntersectPoint >& intPnts = line._intPoints;
+ multiset< F_IntersectPoint >& intPnts = line._intPoints;
multiset< F_IntersectPoint >::iterator ip = intPnts.begin();
- bool isOut = true;
+ // Create mesh nodes at intersections with geometry
+ // and set OUT state of nodes between intersections
+
+ TGeomID solidID = 0;
const double* nodeCoord = & coords[0];
const double* coord0 = nodeCoord;
const double* coordEnd = coord0 + coords.size();
double nodeParam = 0;
for ( ; ip != intPnts.end(); ++ip )
{
+ solidID = line.GetSolidIDBefore( ip, solidID, _geometry );
+
// set OUT state or just skip IN nodes before ip
if ( nodeParam < ip->_paramOnLine - _tol )
{
- isOut = line.GetIsOutBefore( ip, isOut );
-
while ( nodeParam < ip->_paramOnLine - _tol )
{
- if ( isOut )
- isNodeOut[ nIndex0 + nShift * ( nodeCoord-coord0 ) ] = isOut;
+ TGeomID & nodeShapeID = shapeIDVec[ nIndex0 + nShift * ( nodeCoord-coord0 ) ];
+ nodeShapeID = Min( solidID, nodeShapeID );
if ( ++nodeCoord < coordEnd )
nodeParam = *nodeCoord - *coord0;
else
// create a mesh node on a GridLine at ip if it does not coincide with a grid node
if ( nodeParam > ip->_paramOnLine + _tol )
{
- // li.SetIndexOnLine( 0 );
- // double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
- // xyz[ li._iConst ] += ip->_paramOnLine;
gp_XYZ xyz = lineLoc + ip->_paramOnLine * lineDir;
- ip->_node = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+ ip->_node = mesh->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
ip->_indexOnLine = nodeCoord-coord0-1;
+ SetOnShape( ip->_node, *ip );
}
- // create a mesh node at ip concident with a grid node
+ // create a mesh node at ip coincident with a grid node
else
{
int nodeIndex = nIndex0 + nShift * ( nodeCoord-coord0 );
if ( !_nodes[ nodeIndex ] )
{
- //li.SetIndexOnLine( nodeCoord-coord0 );
- //double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
gp_XYZ xyz = lineLoc + nodeParam * lineDir;
- _nodes [ nodeIndex ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
- _gridIntP[ nodeIndex ] = & * ip;
+ _nodes [ nodeIndex ] = mesh->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+ //_gridIntP[ nodeIndex ] = & * ip;
+ //SetOnShape( _nodes[ nodeIndex ], *ip );
}
if ( _gridIntP[ nodeIndex ] )
_gridIntP[ nodeIndex ]->Add( ip->_faceIDs );
}
// set OUT state to nodes after the last ip
for ( ; nodeCoord < coordEnd; ++nodeCoord )
- isNodeOut[ nIndex0 + nShift * ( nodeCoord-coord0 ) ] = true;
+ shapeIDVec[ nIndex0 + nShift * ( nodeCoord-coord0 ) ] = 0;
}
}
for ( size_t x = 0; x < _coords[0].size(); ++x )
{
size_t nodeIndex = NodeIndex( x, y, z );
- if ( !isNodeOut[ nodeIndex ] && !_nodes[ nodeIndex] )
+ if ( !_nodes[ nodeIndex ] &&
+ 0 < shapeIDVec[ nodeIndex ] && shapeIDVec[ nodeIndex ] < undefID )
{
- //_nodes[ nodeIndex ] = helper.AddNode( _coords[0][x], _coords[1][y], _coords[2][z] );
gp_XYZ xyz = ( _coords[0][x] * _axes[0] +
_coords[1][y] * _axes[1] +
_coords[2][z] * _axes[2] );
- _nodes[ nodeIndex ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+ _nodes[ nodeIndex ] = mesh->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+ mesh->SetNodeInVolume( _nodes[ nodeIndex ], shapeIDVec[ nodeIndex ]);
+ }
+ else if ( _nodes[ nodeIndex ] && _gridIntP[ nodeIndex ] /*&&
+ !_nodes[ nodeIndex]->GetShapeID()*/ )
+ {
+ SetOnShape( _nodes[ nodeIndex ], *_gridIntP[ nodeIndex ]);
}
}
_intersections.push_back( make_pair( &gridLine, intersector._intPoints[i] ));
}
}
+
+ if ( _face.Orientation() == TopAbs_INTERNAL )
+ {
+ for ( size_t i = 0; i < _intersections.size(); ++i )
+ if ( _intersections[i].second._transition == Trans_IN ||
+ _intersections[i].second._transition == Trans_OUT )
+ {
+ _intersections[i].second._transition = Trans_INTERNAL;
+ }
+ }
+ return;
}
//================================================================================
/*
{
F_IntersectPoint p;
p._paramOnLine = _w;
+ p._u = _u;
+ p._v = _v;
p._transition = _transition;
_intPoints.push_back( p );
}
/*!
* \brief Creates topology of the hexahedron
*/
- Hexahedron::Hexahedron(const double sizeThreshold, Grid* grid)
- : _grid( grid ), _sizeThreshold( sizeThreshold ), _nbFaceIntNodes(0)
+ Hexahedron::Hexahedron(Grid* grid)
+ : _grid( grid ), _nbFaceIntNodes(0), _hasTooSmall( false )
{
_polygons.reserve(100); // to avoid reallocation;
/*!
* \brief Copy constructor
*/
- Hexahedron::Hexahedron( const Hexahedron& other )
- :_grid( other._grid ), _sizeThreshold( other._sizeThreshold ), _nbFaceIntNodes(0)
+ Hexahedron::Hexahedron( const Hexahedron& other, size_t i, size_t j, size_t k, int cellID )
+ :_grid( other._grid ), _nbFaceIntNodes(0), _i( i ), _j( j ), _k( k ), _hasTooSmall( false )
{
_polygons.reserve(100); // to avoid reallocation;
+ // copy topology
for ( int i = 0; i < 8; ++i )
_nodeShift[i] = other._nodeShift[i];
tgtLink._link = _hexLinks + ( srcLink._link - other._hexLinks );
}
}
+#ifdef _DEBUG_
+ _cellID = cellID;
+#endif
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return IDs of SOLIDs interfering with this Hexahedron
+ */
+ const vector< TGeomID >& Hexahedron::getSolids()
+ {
+ _grid->_shapeIDs.clear();
+ if ( _grid->_geometry.IsOneSolid() )
+ {
+ _grid->_shapeIDs.push_back( _grid->GetSolid()->ID() );
+ return _grid->_shapeIDs;
+ }
+ // count intersection points belonging to each SOLID
+ TID2Nb id2NbPoints;
+ id2NbPoints.reserve( 3 );
+
+ _origNodeInd = _grid->NodeIndex( _i,_j,_k );
+ for ( int iN = 0; iN < 8; ++iN )
+ {
+ _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ];
+ _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ];
+
+ if ( _hexNodes[iN]._intPoint ) // intersection with a FACE
+ {
+ for ( size_t iF = 0; iF < _hexNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ {
+ const vector< TGeomID > & solidIDs =
+ _grid->GetSolidIDs( _hexNodes[iN]._intPoint->_faceIDs[iF] );
+ for ( size_t i = 0; i < solidIDs.size(); ++i )
+ insertAndIncrement( solidIDs[i], id2NbPoints );
+ }
+ }
+ else if ( _hexNodes[iN]._node ) // node inside a SOLID
+ {
+ insertAndIncrement( _hexNodes[iN]._node->GetShapeID(), id2NbPoints );
+ }
+ }
+
+ for ( int iL = 0; iL < 12; ++iL )
+ {
+ const _Link& link = _hexLinks[ iL ];
+ for ( size_t iP = 0; iP < link._fIntPoints.size(); ++iP )
+ {
+ for ( size_t iF = 0; iF < link._fIntPoints[iP]->_faceIDs.size(); ++iF )
+ {
+ const vector< TGeomID > & solidIDs =
+ _grid->GetSolidIDs( link._fIntPoints[iP]->_faceIDs[iF] );
+ for ( size_t i = 0; i < solidIDs.size(); ++i )
+ insertAndIncrement( solidIDs[i], id2NbPoints );
+ }
+ }
+ }
+
+ for ( size_t iP = 0; iP < _eIntPoints.size(); ++iP )
+ {
+ const vector< TGeomID > & solidIDs = _grid->GetSolidIDs( _eIntPoints[iP]->_shapeID );
+ for ( size_t i = 0; i < solidIDs.size(); ++i )
+ insertAndIncrement( solidIDs[i], id2NbPoints );
+ }
+
+ _grid->_shapeIDs.reserve( id2NbPoints.size() );
+ for ( TID2Nb::iterator id2nb = id2NbPoints.begin(); id2nb != id2NbPoints.end(); ++id2nb )
+ if ( id2nb->second >= 3 )
+ _grid->_shapeIDs.push_back( id2nb->first );
+
+ return _grid->_shapeIDs;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Count cuts by INTERNAL FACEs and set _Node::_isInternalFlags
+ */
+ bool Hexahedron::isCutByInternalFace( IsInternalFlag & maxFlag )
+ {
+ TID2Nb id2NbPoints;
+ id2NbPoints.reserve( 3 );
+
+ for ( size_t iN = 0; iN < _intNodes.size(); ++iN )
+ for ( size_t iF = 0; iF < _intNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ {
+ if ( _grid->IsInternal( _intNodes[iN]._intPoint->_faceIDs[iF]))
+ insertAndIncrement( _intNodes[iN]._intPoint->_faceIDs[iF], id2NbPoints );
+ }
+ for ( size_t iN = 0; iN < 8; ++iN )
+ if ( _hexNodes[iN]._intPoint )
+ for ( size_t iF = 0; iF < _hexNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ {
+ if ( _grid->IsInternal( _hexNodes[iN]._intPoint->_faceIDs[iF]))
+ insertAndIncrement( _hexNodes[iN]._intPoint->_faceIDs[iF], id2NbPoints );
+ }
+
+ maxFlag = IS_NOT_INTERNAL;
+ for ( TID2Nb::iterator id2nb = id2NbPoints.begin(); id2nb != id2NbPoints.end(); ++id2nb )
+ {
+ TGeomID intFace = id2nb->first;
+ IsInternalFlag intFlag = ( id2nb->second >= 3 ? IS_CUT_BY_INTERNAL_FACE : IS_INTERNAL );
+ if ( intFlag > maxFlag )
+ maxFlag = intFlag;
+
+ for ( size_t iN = 0; iN < _intNodes.size(); ++iN )
+ if ( _intNodes[iN].IsOnFace( intFace ))
+ _intNodes[iN].SetInternal( intFlag );
+
+ for ( size_t iN = 0; iN < 8; ++iN )
+ if ( _hexNodes[iN].IsOnFace( intFace ))
+ _hexNodes[iN].SetInternal( intFlag );
+ }
+
+ return maxFlag;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return any FACE interfering with this Hexahedron
+ */
+ TGeomID Hexahedron::getAnyFace() const
+ {
+ TID2Nb id2NbPoints;
+ id2NbPoints.reserve( 3 );
+
+ for ( size_t iN = 0; iN < _intNodes.size(); ++iN )
+ for ( size_t iF = 0; iF < _intNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ insertAndIncrement( _intNodes[iN]._intPoint->_faceIDs[iF], id2NbPoints );
+
+ for ( size_t iN = 0; iN < 8; ++iN )
+ if ( _hexNodes[iN]._intPoint )
+ for ( size_t iF = 0; iF < _hexNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ insertAndIncrement( _hexNodes[iN]._intPoint->_faceIDs[iF], id2NbPoints );
+
+ for ( unsigned int minNb = 3; minNb > 0; --minNb )
+ for ( TID2Nb::iterator id2nb = id2NbPoints.begin(); id2nb != id2NbPoints.end(); ++id2nb )
+ if ( id2nb->second >= minNb )
+ return id2nb->first;
+
+ return 0;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Initializes IJK by Hexahedron index
+ */
+ void Hexahedron::setIJK( size_t iCell )
+ {
+ size_t iNbCell = _grid->_coords[0].size() - 1;
+ size_t jNbCell = _grid->_coords[1].size() - 1;
+ _i = iCell % iNbCell;
+ _j = ( iCell % ( iNbCell * jNbCell )) / iNbCell;
+ _k = iCell / iNbCell / jNbCell;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Initializes its data by given grid cell (countered from zero)
+ */
+ void Hexahedron::init( size_t iCell )
+ {
+ setIJK( iCell );
+ init( _i, _j, _k );
}
//================================================================================
/*!
- * \brief Initializes its data by given grid cell
+ * \brief Initializes its data by given grid cell nodes and intersections
*/
- void Hexahedron::init( size_t i, size_t j, size_t k )
+ void Hexahedron::init( size_t i, size_t j, size_t k, const Solid* solid )
{
_i = i; _j = j; _k = k;
+
+ if ( !solid )
+ solid = _grid->GetSolid();
+
// set nodes of grid to nodes of the hexahedron and
// count nodes at hexahedron corners located IN and ON geometry
_nbCornerNodes = _nbBndNodes = 0;
_origNodeInd = _grid->NodeIndex( i,j,k );
for ( int iN = 0; iN < 8; ++iN )
{
+ _hexNodes[iN]._isInternalFlags = 0;
+
_hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ];
_hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ];
+
+ if ( _hexNodes[iN]._node && !solid->Contains( _hexNodes[iN]._node->GetShapeID() ))
+ _hexNodes[iN]._node = 0;
+ if ( _hexNodes[iN]._intPoint && !solid->ContainsAny( _hexNodes[iN]._intPoint->_faceIDs ))
+ _hexNodes[iN]._intPoint = 0;
+
_nbCornerNodes += bool( _hexNodes[iN]._node );
_nbBndNodes += bool( _hexNodes[iN]._intPoint );
}
_intNodes.clear();
_vIntNodes.clear();
- if ( _nbFaceIntNodes + _eIntPoints.size() > 0 &&
- _nbFaceIntNodes + _nbCornerNodes + _eIntPoints.size() > 3)
+ if ( _nbFaceIntNodes + _eIntPoints.size() > 0 &&
+ _nbFaceIntNodes + _eIntPoints.size() + _nbCornerNodes > 3)
{
_intNodes.reserve( 3 * _nbBndNodes + _nbFaceIntNodes + _eIntPoints.size() );
// this method can be called in parallel, so use own helper
SMESH_MesherHelper helper( *_grid->_helper->GetMesh() );
- // create sub-links (_splits) by splitting links with _fIntPoints
+ // Create sub-links (_Link::_splits) by splitting links with _Link::_fIntPoints
+ // ---------------------------------------------------------------
_Link split;
for ( int iLink = 0; iLink < 12; ++iLink )
{
_Link& link = _hexLinks[ iLink ];
- link._fIntNodes.resize( link._fIntPoints.size() );
+ link._fIntNodes.clear();
+ link._fIntNodes.reserve( link._fIntPoints.size() );
for ( size_t i = 0; i < link._fIntPoints.size(); ++i )
- {
- _intNodes.push_back( _Node( 0, link._fIntPoints[i] ));
- link._fIntNodes[ i ] = & _intNodes.back();
- }
+ if ( solid->ContainsAny( link._fIntPoints[i]->_faceIDs ))
+ {
+ _intNodes.push_back( _Node( 0, link._fIntPoints[i] ));
+ link._fIntNodes.push_back( & _intNodes.back() );
+ }
link._splits.clear();
split._nodes[ 0 ] = link._nodes[0];
}
if ( checkTransition )
{
- if ( link._fIntPoints[i]->_faceIDs.size() > 1 || _eIntPoints.size() > 0 )
- isOut = isOutPoint( link, i, helper );
+ const vector< TGeomID >& faceIDs = link._fIntNodes[i]->_intPoint->_faceIDs;
+ if ( _grid->IsInternal( faceIDs.back() ))
+ isOut = false;
+ else if ( faceIDs.size() > 1 || _eIntPoints.size() > 0 )
+ isOut = isOutPoint( link, i, helper, solid );
else
- switch ( link._fIntPoints[i]->_transition ) {
- case Trans_OUT: isOut = true; break;
- case Trans_IN : isOut = false; break;
+ {
+ bool okTransi = _grid->IsCorrectTransition( faceIDs[0], solid );
+ switch ( link._fIntNodes[i]->FaceIntPnt()->_transition ) {
+ case Trans_OUT: isOut = okTransi; break;
+ case Trans_IN : isOut = !okTransi; break;
default:
- isOut = isOutPoint( link, i, helper );
+ isOut = isOutPoint( link, i, helper, solid );
}
+ }
}
}
if ( link._nodes[ 1 ]->Node() && split._nodes[ 0 ]->Node() && !isOut )
}
// Create _Node's at intersections with EDGEs.
-
+ // --------------------------------------------
+ // 1) add this->_eIntPoints to _Face::_eIntNodes
+ // 2) fill _intNodes and _vIntNodes
+ //
const double tol2 = _grid->_tol * _grid->_tol;
int facets[3], nbFacets, subEntity;
+ for ( int iF = 0; iF < 6; ++iF )
+ _hexQuads[ iF ]._eIntNodes.clear();
+
for ( size_t iP = 0; iP < _eIntPoints.size(); ++iP )
{
+ if ( !solid->ContainsAny( _eIntPoints[iP]->_faceIDs ))
+ continue;
nbFacets = getEntity( _eIntPoints[iP], facets, subEntity );
_Node* equalNode = 0;
switch( nbFacets ) {
equalNode = findEqualNode( link._fIntNodes, _eIntPoints[ iP ], tol2 );
if ( equalNode )
equalNode->Add( _eIntPoints[ iP ] );
+ else if ( link._splits.size() == 1 &&
+ link._splits[0]._nodes[0] &&
+ link._splits[0]._nodes[1] )
+ link._splits.clear(); // hex edge is divided by _eIntPoints[iP]
}
- else
+ //else
+ if ( !equalNode )
{
_intNodes.push_back( _Node( 0, _eIntPoints[ iP ]));
+ bool newNodeUsed = false;
for ( int iF = 0; iF < 2; ++iF )
{
_Face& quad = _hexQuads[ facets[iF] - SMESH_Block::ID_FirstF ];
}
else {
quad._eIntNodes.push_back( & _intNodes.back() );
+ newNodeUsed = true;
}
}
+ if ( !newNodeUsed )
+ _intNodes.pop_back();
}
break;
}
} // switch( nbFacets )
if ( nbFacets == 0 ||
- _grid->_shapes( _eIntPoints[ iP ]->_shapeID ).ShapeType() == TopAbs_VERTEX )
+ _grid->ShapeType( _eIntPoints[ iP ]->_shapeID ) == TopAbs_VERTEX )
{
equalNode = findEqualNode( _vIntNodes, _eIntPoints[ iP ], tol2 );
if ( equalNode ) {
}
} // loop on _eIntPoints
}
+
else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbFaceIntNodes == 0
{
_Link split;
}
}
}
+ return;
- }
- //================================================================================
- /*!
- * \brief Initializes its data by given grid cell (countered from zero)
- */
- void Hexahedron::init( size_t iCell )
- {
- size_t iNbCell = _grid->_coords[0].size() - 1;
- size_t jNbCell = _grid->_coords[1].size() - 1;
- _i = iCell % iNbCell;
- _j = ( iCell % ( iNbCell * jNbCell )) / iNbCell;
- _k = iCell / iNbCell / jNbCell;
- init( _i, _j, _k );
- }
+ } // init( _i, _j, _k )
//================================================================================
/*!
* \brief Compute mesh volumes resulted from intersection of the Hexahedron
*/
- void Hexahedron::ComputeElements()
+ void Hexahedron::ComputeElements( const Solid* solid, int solidIndex )
{
- Init();
+ if ( !solid )
+ {
+ solid = _grid->GetSolid();
+ if ( !_grid->_geometry.IsOneSolid() )
+ {
+ const vector< TGeomID >& solidIDs = getSolids();
+ if ( solidIDs.size() > 1 )
+ {
+ for ( size_t i = 0; i < solidIDs.size(); ++i )
+ {
+ solid = _grid->GetSolid( solidIDs[i] );
+ ComputeElements( solid, i );
+ if ( !_volumeDefs._nodes.empty() && i < solidIDs.size() - 1 )
+ _volumeDefs.SetNext( new _volumeDef( _volumeDefs ));
+ }
+ return;
+ }
+ solid = _grid->GetSolid( solidIDs[0] );
+ }
+ }
+
+ init( _i, _j, _k, solid ); // get nodes and intersections from grid nodes and split links
int nbIntersections = _nbFaceIntNodes + _eIntPoints.size();
if ( _nbCornerNodes + nbIntersections < 4 )
return;
if ( _nbBndNodes == _nbCornerNodes && nbIntersections == 0 && isInHole() )
- return;
+ return; // cell is in a hole
+
+ IsInternalFlag intFlag = IS_NOT_INTERNAL;
+ if ( solid->HasInternalFaces() && this->isCutByInternalFace( intFlag ))
+ {
+ for ( _SplitIterator it( _hexLinks ); it.More(); it.Next() )
+ {
+ if ( compute( solid, intFlag ))
+ _volumeDefs.SetNext( new _volumeDef( _volumeDefs ));
+ }
+ }
+ else
+ {
+ if ( solidIndex >= 0 )
+ intFlag = IS_CUT_BY_INTERNAL_FACE;
+
+ compute( solid, intFlag );
+ }
+ }
+ //================================================================================
+ /*!
+ * \brief Compute mesh volumes resulted from intersection of the Hexahedron
+ */
+ bool Hexahedron::compute( const Solid* solid, const IsInternalFlag intFlag )
+ {
_polygons.clear();
_polygons.reserve( 20 );
+ for ( int iN = 0; iN < 8; ++iN )
+ _hexNodes[iN]._usedInFace = 0;
+
// Create polygons from quadrangles
// --------------------------------
if (( nbSplits == 1 ) &&
( quad._eIntNodes.empty() ||
splits[0].FirstNode()->IsLinked( splits[0].LastNode()->_intPoint )))
- //( quad._eIntNodes.empty() || _nbCornerNodes + nbIntersections > 6 ))
+ //( quad._eIntNodes.empty() || _nbCornerNodes + nbIntersections > 6 ))
nbSplits = 0;
-#ifdef _DEBUG_
for ( size_t iP = 0; iP < quad._eIntNodes.size(); ++iP )
if ( quad._eIntNodes[ iP ]->IsUsedInFace( polygon ))
quad._eIntNodes[ iP ]->_usedInFace = 0;
-#endif
+
size_t nbUsedEdgeNodes = 0;
_Face* prevPolyg = 0; // polygon previously created from this quad
n1 = split.FirstNode();
if ( n1 == n2 &&
n1->_intPoint &&
- n1->_intPoint->_faceIDs.size() > 1 )
+ (( n1->_intPoint->_faceIDs.size() > 1 && isImplementEdges() ) ||
+ ( n1->_isInternalFlags )))
{
// n1 is at intersection with EDGE
if ( findChainOnEdge( splits, polygon->_links.back(), split, iS, quad, chainNodes ))
{
for ( size_t i = 1; i < chainNodes.size(); ++i )
polygon->AddPolyLink( chainNodes[i-1], chainNodes[i], prevPolyg );
- prevPolyg = polygon;
- n2 = chainNodes.back();
- continue;
+ if ( chainNodes.back() != n1 ) // not a partial cut by INTERNAL FACE
+ {
+ prevPolyg = polygon;
+ n2 = chainNodes.back();
+ continue;
+ }
}
}
else if ( n1 != n2 )
freeLinks.push_back( & polygon._links[ iL ]);
}
int nbFreeLinks = freeLinks.size();
- if ( nbFreeLinks == 1 ) return;
+ if ( nbFreeLinks == 1 ) return false;
// put not used intersection nodes to _vIntNodes
int nbVertexNodes = 0; // nb not used vertex nodes
_vIntNodes[ iN ]->_usedInFace = &polygon;
chainNodes.push_back( _vIntNodes[ iN ] );
}
- if ( chainNodes.size() > 1 )
+ if ( chainNodes.size() > 1 &&
+ curFace != _grid->PseudoIntExtFaceID() ) /////// TODO
{
sortVertexNodes( chainNodes, curNode, curFace );
}
if ( polygon._links.size() < 2 ||
polygon._links[0].LastNode() != polygon._links.back().FirstNode() )
- return; // closed polygon not found -> invalid polyhedron
+ return false; // closed polygon not found -> invalid polyhedron
if ( polygon._links.size() == 2 )
{
} // end of case ( polygon._links.size() > 2 )
} // while ( nbFreeLinks > 0 )
- if ( ! checkPolyhedronSize() )
- {
- return;
- }
+ // check volume size
+ _hasTooSmall = ! checkPolyhedronSize( intFlag & IS_CUT_BY_INTERNAL_FACE );
for ( size_t i = 0; i < 8; ++i )
if ( _hexNodes[ i ]._intPoint == &ipTmp )
_hexNodes[ i ]._intPoint = 0;
+ if ( _hasTooSmall )
+ return false; // too small volume
+
// create a classic cell if possible
int nbPolygons = 0;
_volumeDefs._nodes.push_back( _polygons[ iF ]._links[ iL ].FirstNode() );
}
}
+ _volumeDefs._solidID = solid->ID();
+
+ return !_volumeDefs._nodes.empty();
}
//================================================================================
/*!
{
SMESHDS_Mesh* mesh = helper.GetMeshDS();
- size_t nbCells[3] = { _grid->_coords[0].size() - 1,
- _grid->_coords[1].size() - 1,
- _grid->_coords[2].size() - 1 };
- const size_t nbGridCells = nbCells[0] * nbCells[1] * nbCells[2];
+ CellsAroundLink c( _grid, 0 );
+ const size_t nbGridCells = c._nbCells[0] * c._nbCells[1] * c._nbCells[2];
vector< Hexahedron* > allHexa( nbGridCells, 0 );
int nbIntHex = 0;
// set intersection nodes from GridLine's to links of allHexa
- int i,j,k, iDirOther[3][2] = {{ 1,2 },{ 0,2 },{ 0,1 }};
+ int i,j,k, cellIndex;
for ( int iDir = 0; iDir < 3; ++iDir )
{
- int dInd[4][3] = { {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} };
- dInd[1][ iDirOther[iDir][0] ] = -1;
- dInd[2][ iDirOther[iDir][1] ] = -1;
- dInd[3][ iDirOther[iDir][0] ] = -1; dInd[3][ iDirOther[iDir][1] ] = -1;
// loop on GridLine's parallel to iDir
LineIndexer lineInd = _grid->GetLineIndexer( iDir );
+ CellsAroundLink fourCells( _grid, iDir );
for ( ; lineInd.More(); ++lineInd )
{
GridLine& line = _grid->_lines[ iDir ][ lineInd.LineIndex() ];
{
// if ( !ip->_node ) continue; // intersection at a grid node
lineInd.SetIndexOnLine( ip->_indexOnLine );
+ fourCells.Init( lineInd.I(), lineInd.J(), lineInd.K() );
for ( int iL = 0; iL < 4; ++iL ) // loop on 4 cells sharing a link
{
- i = int(lineInd.I()) + dInd[iL][0];
- j = int(lineInd.J()) + dInd[iL][1];
- k = int(lineInd.K()) + dInd[iL][2];
- if ( i < 0 || i >= (int) nbCells[0] ||
- j < 0 || j >= (int) nbCells[1] ||
- k < 0 || k >= (int) nbCells[2] ) continue;
-
- const size_t hexIndex = _grid->CellIndex( i,j,k );
- Hexahedron *& hex = allHexa[ hexIndex ];
+ if ( !fourCells.GetCell( iL, i,j,k, cellIndex ))
+ continue;
+ Hexahedron *& hex = allHexa[ cellIndex ];
if ( !hex)
{
- hex = new Hexahedron( *this );
- hex->_i = i;
- hex->_j = j;
- hex->_k = k;
+ hex = new Hexahedron( *this, i, j, k, cellIndex );
++nbIntHex;
}
const int iLink = iL + iDir * 4;
// implement geom edges into the mesh
addEdges( helper, allHexa, edge2faceIDsMap );
- // add not split hexadrons to the mesh
+ // add not split hexahedra to the mesh
int nbAdded = 0;
- vector< Hexahedron* > intHexa( nbIntHex, (Hexahedron*) NULL );
+ vector< Hexahedron* > intHexa; intHexa.reserve( nbIntHex );
+ vector< const SMDS_MeshElement* > boundaryVolumes; boundaryVolumes.reserve( nbIntHex * 1.1 );
for ( size_t i = 0; i < allHexa.size(); ++i )
{
+ // initialize this by not cut allHexa[ i ]
Hexahedron * & hex = allHexa[ i ];
- if ( hex )
+ if ( hex ) // split hexahedron
{
intHexa.push_back( hex );
if ( hex->_nbFaceIntNodes > 0 || hex->_eIntPoints.size() > 0 )
- continue; // treat intersected hex later
+ continue; // treat intersected hex later in parallel
this->init( hex->_i, hex->_j, hex->_k );
}
else
- {
- this->init( i );
+ {
+ this->init( i ); // == init(i,j,k)
}
if (( _nbCornerNodes == 8 ) &&
( _nbBndNodes < _nbCornerNodes || !isInHole() ))
_hexNodes[3].Node(), _hexNodes[1].Node(),
_hexNodes[4].Node(), _hexNodes[6].Node(),
_hexNodes[7].Node(), _hexNodes[5].Node() );
- mesh->SetMeshElementOnShape( el, helper.GetSubShapeID() );
+ TGeomID solidID = 0;
+ if ( _nbBndNodes < _nbCornerNodes )
+ {
+ for ( int iN = 0; iN < 8 && !solidID; ++iN )
+ if ( !_hexNodes[iN]._intPoint ) // no intersection
+ solidID = _hexNodes[iN].Node()->GetShapeID();
+ }
+ else
+ {
+ solidID = getSolids()[0];
+ }
+ mesh->SetMeshElementOnShape( el, solidID );
++nbAdded;
if ( hex )
intHexa.pop_back();
+ if ( _grid->_toCreateFaces && _nbBndNodes >= 3 )
+ {
+ boundaryVolumes.push_back( el );
+ el->setIsMarked( true );
+ }
}
- else if ( _nbCornerNodes > 3 && !hex )
+ else if ( _nbCornerNodes > 3 && !hex )
{
// all intersection of hex with geometry are at grid nodes
- hex = new Hexahedron( *this );
- hex->_i = _i;
- hex->_j = _j;
- hex->_k = _k;
+ hex = new Hexahedron( *this, _i, _j, _k, i );
intHexa.push_back( hex );
}
}
tbb::simple_partitioner()); // ComputeElements() is called here
for ( size_t i = 0; i < intHexa.size(); ++i )
if ( Hexahedron * hex = intHexa[ i ] )
- nbAdded += hex->addElements( helper );
+ nbAdded += hex->addVolumes( helper );
#else
for ( size_t i = 0; i < intHexa.size(); ++i )
if ( Hexahedron * hex = intHexa[ i ] )
{
hex->ComputeElements();
- nbAdded += hex->addElements( helper );
+ nbAdded += hex->addVolumes( helper );
}
#endif
+ // fill boundaryVolumes with volumes neighboring too small skipped volumes
+ if ( _grid->_toCreateFaces )
+ {
+ for ( size_t i = 0; i < intHexa.size(); ++i )
+ if ( Hexahedron * hex = intHexa[ i ] )
+ hex->getBoundaryElems( boundaryVolumes );
+ }
+
+ // create boundary mesh faces
+ addFaces( helper, boundaryVolumes );
+
+ // create mesh edges
+ addSegments( helper, edge2faceIDsMap );
+
for ( size_t i = 0; i < allHexa.size(); ++i )
if ( allHexa[ i ] )
delete allHexa[ i ];
const double tol = _grid->_tol;
E_IntersectPoint ip;
+ TColStd_MapOfInteger intEdgeIDs; // IDs of not shared INTERNAL EDGES
+
// Intersect EDGEs with the planes
map< TGeomID, vector< TGeomID > >::const_iterator e2fIt = edge2faceIDsMap.begin();
for ( ; e2fIt != edge2faceIDsMap.end(); ++e2fIt )
{
const TGeomID edgeID = e2fIt->first;
- const TopoDS_Edge & E = TopoDS::Edge( _grid->_shapes( edgeID ));
+ const TopoDS_Edge & E = TopoDS::Edge( _grid->Shape( edgeID ));
BRepAdaptor_Curve curve( E );
- TopoDS_Vertex v1 = helper.IthVertex( 0, E, false );
- TopoDS_Vertex v2 = helper.IthVertex( 1, E, false );
+ TopoDS_Vertex v1 = helper.IthVertex( 0, E, false );
+ TopoDS_Vertex v2 = helper.IthVertex( 1, E, false );
ip._faceIDs = e2fIt->second;
ip._shapeID = edgeID;
+ bool isInternal = ( ip._faceIDs.size() == 1 && _grid->IsInternal( edgeID ));
+ if ( isInternal )
+ {
+ intEdgeIDs.Add( edgeID );
+ intEdgeIDs.Add( _grid->ShapeID( v1 ));
+ intEdgeIDs.Add( _grid->ShapeID( v2 ));
+ }
+
// discretize the EDGE
GCPnts_UniformDeflection discret( curve, deflection, true );
if ( !discret.IsDone() || discret.NbPoints() < 2 )
continue;
// perform intersection
+ E_IntersectPoint* eip, *vip;
for ( int iDirZ = 0; iDirZ < 3; ++iDirZ )
{
GridPlanes& planes = pln[ iDirZ ];
locateValue( iY1, ip._uvw[iDirY], _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
locateValue( iZ1, ip._uvw[iDirZ], _grid->_coords[ iDirZ ], dIJK[ iDirZ ], tol );
- int ijk[3]; // grid index where a segment intersect a plane
+ int ijk[3]; // grid index where a segment intersects a plane
ijk[ iDirX ] = iX1;
ijk[ iDirY ] = iY1;
ijk[ iDirZ ] = iZ1;
if ( iDirZ == 0 )
{
ip._point = p1;
- ip._shapeID = _grid->_shapes.Add( v1 );
- _grid->_edgeIntP.push_back( ip );
- if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
- _grid->_edgeIntP.pop_back();
+ ip._shapeID = _grid->ShapeID( v1 );
+ vip = _grid->Add( ip );
+ if ( isInternal )
+ vip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ if ( !addIntersection( vip, hexes, ijk, d000 ))
+ _grid->Remove( vip );
ip._shapeID = edgeID;
}
for ( int iP = 2; iP <= discret.NbPoints(); ++iP )
ijk[ iDirZ ] = iZ;
// add ip to hex "above" the plane
- _grid->_edgeIntP.push_back( ip );
+ eip = _grid->Add( ip );
+ if ( isInternal )
+ eip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
dIJK[ iDirZ ] = 0;
- bool added = addIntersection(_grid->_edgeIntP.back(), hexes, ijk, dIJK);
+ bool added = addIntersection( eip, hexes, ijk, dIJK);
// add ip to hex "below" the plane
ijk[ iDirZ ] = iZ-1;
- if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, dIJK ) &&
- !added)
- _grid->_edgeIntP.pop_back();
+ if ( !addIntersection( eip, hexes, ijk, dIJK ) &&
+ !added )
+ _grid->Remove( eip );
}
}
iZ1 = iZ2;
// add the 2nd vertex point to a hexahedron
if ( iDirZ == 0 )
{
- ip._shapeID = _grid->_shapes.Add( v2 );
- ip._point = p1;
+ ip._point = p1;
+ ip._shapeID = _grid->ShapeID( v2 );
_grid->ComputeUVW( p1, ip._uvw );
locateValue( ijk[iDirX], ip._uvw[iDirX], _grid->_coords[iDirX], dIJK[iDirX], tol );
locateValue( ijk[iDirY], ip._uvw[iDirY], _grid->_coords[iDirY], dIJK[iDirY], tol );
ijk[ iDirZ ] = iZ1;
- _grid->_edgeIntP.push_back( ip );
- if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
- _grid->_edgeIntP.pop_back();
+ bool sameV = ( v1.IsSame( v2 ));
+ if ( !sameV )
+ vip = _grid->Add( ip );
+ if ( isInternal && !sameV )
+ vip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ if ( !addIntersection( vip, hexes, ijk, d000 ) && !sameV )
+ _grid->Remove( vip );
ip._shapeID = edgeID;
}
} // loop on 3 grid directions
} // loop on EDGEs
+
+ if ( intEdgeIDs.Size() > 0 )
+ cutByExtendedInternal( hexes, intEdgeIDs );
+
+ return;
}
//================================================================================
/*!
- * \brief Finds intersection of a curve with a plane
- * \param [in] u1 - parameter of one curve point
- * \param [in] proj1 - projection of the curve point to the plane normal
- * \param [in] u2 - parameter of another curve point
- * \param [in] proj2 - projection of the other curve point to the plane normal
- * \param [in] proj - projection of a point where the curve intersects the plane
- * \param [in] curve - the curve
- * \param [in] axis - the plane normal
- * \param [in] origin - the plane origin
- * \return gp_Pnt - the found intersection point
+ * \brief Fully cut hexes that are partially cut by INTERNAL FACE.
+ * Cut them by extended INTERNAL FACE.
*/
- gp_Pnt Hexahedron::findIntPoint( double u1, double proj1,
- double u2, double proj2,
- double proj,
- BRepAdaptor_Curve& curve,
- const gp_XYZ& axis,
- const gp_XYZ& origin)
+ void Hexahedron::cutByExtendedInternal( std::vector< Hexahedron* >& hexes,
+ const TColStd_MapOfInteger& intEdgeIDs )
{
- double r = (( proj - proj1 ) / ( proj2 - proj1 ));
- double u = u1 * ( 1 - r ) + u2 * r;
- gp_Pnt p = curve.Value( u );
- double newProj = axis * ( p.XYZ() - origin );
- if ( Abs( proj - newProj ) > _grid->_tol / 10. )
+ IntAna_IntConicQuad intersection;
+ SMESHDS_Mesh* meshDS = _grid->_helper->GetMeshDS();
+ const double tol2 = _grid->_tol * _grid->_tol;
+
+ for ( size_t iH = 0; iH < hexes.size(); ++iH )
{
- if ( r > 0.5 )
- return findIntPoint( u2, proj2, u, newProj, proj, curve, axis, origin );
- else
- return findIntPoint( u1, proj2, u, newProj, proj, curve, axis, origin );
- }
- return p;
+ Hexahedron* hex = hexes[ iH ];
+ if ( !hex || hex->_eIntPoints.size() < 2 )
+ continue;
+ if ( !intEdgeIDs.Contains( hex->_eIntPoints.back()->_shapeID ))
+ continue;
+
+ // get 3 points on INTERNAL FACE to construct a cutting plane
+ gp_Pnt p1 = hex->_eIntPoints[0]->_point;
+ gp_Pnt p2 = hex->_eIntPoints[1]->_point;
+ gp_Pnt p3 = hex->mostDistantInternalPnt( iH, p1, p2 );
+
+ gp_Vec norm = gp_Vec( p1, p2 ) ^ gp_Vec( p1, p3 );
+ gp_Pln pln;
+ try {
+ pln = gp_Pln( p1, norm );
+ }
+ catch(...)
+ {
+ continue;
+ }
+
+ TGeomID intFaceID = hex->_eIntPoints.back()->_faceIDs.front(); // FACE being "extended"
+ TGeomID solidID = _grid->GetSolid( intFaceID )->ID();
+
+ // cut links by the plane
+ //bool isCut = false;
+ for ( int iLink = 0; iLink < 12; ++iLink )
+ {
+ _Link& link = hex->_hexLinks[ iLink ];
+ if ( !link._fIntPoints.empty() )
+ {
+ // if ( link._fIntPoints[0]->_faceIDs.back() == _grid->PseudoIntExtFaceID() )
+ // isCut = true;
+ continue; // already cut link
+ }
+ if ( !link._nodes[0]->Node() ||
+ !link._nodes[1]->Node() )
+ continue; // outside link
+
+ if ( link._nodes[0]->IsOnFace( intFaceID ))
+ {
+ if ( link._nodes[0]->_intPoint->_faceIDs.back() != _grid->PseudoIntExtFaceID() )
+ if ( p1.SquareDistance( link._nodes[0]->Point() ) < tol2 ||
+ p2.SquareDistance( link._nodes[0]->Point() ) < tol2 )
+ link._nodes[0]->_intPoint->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ continue; // link is cut by FACE being "extended"
+ }
+ if ( link._nodes[1]->IsOnFace( intFaceID ))
+ {
+ if ( link._nodes[1]->_intPoint->_faceIDs.back() != _grid->PseudoIntExtFaceID() )
+ if ( p1.SquareDistance( link._nodes[1]->Point() ) < tol2 ||
+ p2.SquareDistance( link._nodes[1]->Point() ) < tol2 )
+ link._nodes[1]->_intPoint->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ continue; // link is cut by FACE being "extended"
+ }
+ gp_Pnt p4 = link._nodes[0]->Point();
+ gp_Pnt p5 = link._nodes[1]->Point();
+ gp_Lin line( p4, gp_Vec( p4, p5 ));
+
+ intersection.Perform( line, pln );
+ if ( !intersection.IsDone() ||
+ intersection.IsInQuadric() ||
+ intersection.IsParallel() ||
+ intersection.NbPoints() < 1 )
+ continue;
+
+ double u = intersection.ParamOnConic(1);
+ if ( u + _grid->_tol < 0 )
+ continue;
+ int iDir = iLink / 4;
+ int index = (&hex->_i)[iDir];
+ double linkLen = _grid->_coords[iDir][index+1] - _grid->_coords[iDir][index];
+ if ( u - _grid->_tol > linkLen )
+ continue;
+
+ if ( u < _grid->_tol ||
+ u > linkLen - _grid->_tol ) // intersection at grid node
+ {
+ int i = ! ( u < _grid->_tol ); // [0,1]
+ int iN = link._nodes[ i ] - hex->_hexNodes; // [0-7]
+
+ const F_IntersectPoint * & ip = _grid->_gridIntP[ hex->_origNodeInd + _nodeShift[iN] ];
+ if ( !ip )
+ {
+ ip = _grid->_extIntPool.getNew();
+ ip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ //ip->_transition = Trans_INTERNAL;
+ }
+ else if ( ip->_faceIDs.back() != _grid->PseudoIntExtFaceID() )
+ {
+ ip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ }
+ hex->_nbFaceIntNodes++;
+ //isCut = true;
+ }
+ else
+ {
+ const gp_Pnt& p = intersection.Point( 1 );
+ F_IntersectPoint* ip = _grid->_extIntPool.getNew();
+ ip->_node = meshDS->AddNode( p.X(), p.Y(), p.Z() );
+ ip->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ ip->_transition = Trans_INTERNAL;
+ meshDS->SetNodeInVolume( ip->_node, solidID );
+
+ CellsAroundLink fourCells( _grid, iDir );
+ fourCells.Init( hex->_i, hex->_j, hex->_k, iLink );
+ int i,j,k, cellIndex;
+ for ( int iC = 0; iC < 4; ++iC ) // loop on 4 cells sharing the link
+ {
+ if ( !fourCells.GetCell( iC, i,j,k, cellIndex ))
+ continue;
+ Hexahedron * h = hexes[ cellIndex ];
+ if ( !h )
+ h = hexes[ cellIndex ] = new Hexahedron( *this, i, j, k, cellIndex );
+ const int iL = iC + iDir * 4;
+ h->_hexLinks[iL]._fIntPoints.push_back( ip );
+ h->_nbFaceIntNodes++;
+ //isCut = true;
+ }
+ }
+ }
+
+ // if ( isCut )
+ // for ( size_t i = 0; i < hex->_eIntPoints.size(); ++i )
+ // {
+ // if ( _grid->IsInternal( hex->_eIntPoints[i]->_shapeID ) &&
+ // ! hex->_eIntPoints[i]->IsOnFace( _grid->PseudoIntExtFaceID() ))
+ // hex->_eIntPoints[i]->_faceIDs.push_back( _grid->PseudoIntExtFaceID() );
+ // }
+ continue;
+
+ } // loop on all hexes
+ return;
}
//================================================================================
/*!
- * \brief Returns indices of a hexahedron sub-entities holding a point
- * \param [in] ip - intersection point
- * \param [out] facets - 0-3 facets holding a point
- * \param [out] sub - index of a vertex or an edge holding a point
+ * \brief Return intersection point on INTERNAL FACE most distant from given ones
+ */
+ gp_Pnt Hexahedron::mostDistantInternalPnt( int hexIndex, const gp_Pnt& p1, const gp_Pnt& p2 )
+ {
+ gp_Pnt resultPnt = p1;
+
+ double maxDist2 = 0;
+ for ( int iLink = 0; iLink < 12; ++iLink ) // check links
+ {
+ _Link& link = _hexLinks[ iLink ];
+ for ( size_t i = 0; i < link._fIntPoints.size(); ++i )
+ if ( _grid->PseudoIntExtFaceID() != link._fIntPoints[i]->_faceIDs[0] &&
+ _grid->IsInternal( link._fIntPoints[i]->_faceIDs[0] ) &&
+ link._fIntPoints[i]->_node )
+ {
+ gp_Pnt p = SMESH_NodeXYZ( link._fIntPoints[i]->_node );
+ double d = p1.SquareDistance( p );
+ if ( d > maxDist2 )
+ {
+ resultPnt = p;
+ maxDist2 = d;
+ }
+ else
+ {
+ d = p2.SquareDistance( p );
+ if ( d > maxDist2 )
+ {
+ resultPnt = p;
+ maxDist2 = d;
+ }
+ }
+ }
+ }
+ setIJK( hexIndex );
+ _origNodeInd = _grid->NodeIndex( _i,_j,_k );
+
+ for ( size_t iN = 0; iN < 8; ++iN ) // check corners
+ {
+ _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ];
+ _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ];
+ if ( _hexNodes[iN]._intPoint )
+ for ( size_t iF = 0; iF < _hexNodes[iN]._intPoint->_faceIDs.size(); ++iF )
+ {
+ if ( _grid->IsInternal( _hexNodes[iN]._intPoint->_faceIDs[iF]))
+ {
+ gp_Pnt p = SMESH_NodeXYZ( _hexNodes[iN]._node );
+ double d = p1.SquareDistance( p );
+ if ( d > maxDist2 )
+ {
+ resultPnt = p;
+ maxDist2 = d;
+ }
+ else
+ {
+ d = p2.SquareDistance( p );
+ if ( d > maxDist2 )
+ {
+ resultPnt = p;
+ maxDist2 = d;
+ }
+ }
+ }
+ }
+ }
+ if ( maxDist2 < _grid->_tol * _grid->_tol )
+ return p1;
+
+ return resultPnt;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Finds intersection of a curve with a plane
+ * \param [in] u1 - parameter of one curve point
+ * \param [in] proj1 - projection of the curve point to the plane normal
+ * \param [in] u2 - parameter of another curve point
+ * \param [in] proj2 - projection of the other curve point to the plane normal
+ * \param [in] proj - projection of a point where the curve intersects the plane
+ * \param [in] curve - the curve
+ * \param [in] axis - the plane normal
+ * \param [in] origin - the plane origin
+ * \return gp_Pnt - the found intersection point
+ */
+ gp_Pnt Hexahedron::findIntPoint( double u1, double proj1,
+ double u2, double proj2,
+ double proj,
+ BRepAdaptor_Curve& curve,
+ const gp_XYZ& axis,
+ const gp_XYZ& origin)
+ {
+ double r = (( proj - proj1 ) / ( proj2 - proj1 ));
+ double u = u1 * ( 1 - r ) + u2 * r;
+ gp_Pnt p = curve.Value( u );
+ double newProj = axis * ( p.XYZ() - origin );
+ if ( Abs( proj - newProj ) > _grid->_tol / 10. )
+ {
+ if ( r > 0.5 )
+ return findIntPoint( u2, proj2, u, newProj, proj, curve, axis, origin );
+ else
+ return findIntPoint( u1, proj2, u, newProj, proj, curve, axis, origin );
+ }
+ return p;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Returns indices of a hexahedron sub-entities holding a point
+ * \param [in] ip - intersection point
+ * \param [out] facets - 0-3 facets holding a point
+ * \param [out] sub - index of a vertex or an edge holding a point
* \return int - number of facets holding a point
*/
int Hexahedron::getEntity( const E_IntersectPoint* ip, int* facets, int& sub )
/*!
* \brief Adds intersection with an EDGE
*/
- bool Hexahedron::addIntersection( const E_IntersectPoint& ip,
+ bool Hexahedron::addIntersection( const E_IntersectPoint* ip,
vector< Hexahedron* >& hexes,
int ijk[], int dIJK[] )
{
};
for ( int i = 0; i < 4; ++i )
{
- if ( /*0 <= hexIndex[i] &&*/ hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
+ if ( hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
{
Hexahedron* h = hexes[ hexIndex[i] ];
- // check if ip is really inside the hex
+ h->_eIntPoints.reserve(2);
+ h->_eIntPoints.push_back( ip );
+ added = true;
#ifdef _DEBUG_
- if ( h->isOutParam( ip._uvw ))
+ // check if ip is really inside the hex
+ if ( h->isOutParam( ip->_uvw ))
throw SALOME_Exception("ip outside a hex");
#endif
- h->_eIntPoints.push_back( & ip );
- added = true;
}
}
return added;
/*!
* \brief Finds nodes on the same EDGE as the first node of avoidSplit.
*
- * This function is for a case where an EDGE lies on a quad which lies on a FACE
- * so that a part of quad in ON and another part in IN
+ * This function is for
+ * 1) a case where an EDGE lies on a quad which lies on a FACE
+ * so that a part of quad in ON and another part is IN
+ * 2) INTERNAL FACE passes through the 1st node of avoidSplit
*/
bool Hexahedron::findChainOnEdge( const vector< _OrientedLink >& splits,
const _OrientedLink& prevSplit,
_Face& quad,
vector<_Node*>& chn )
{
- if ( !isImplementEdges() )
- return false;
-
_Node* pn1 = prevSplit.FirstNode();
_Node* pn2 = prevSplit.LastNode();
int avoidFace = pn1->IsLinked( pn2->_intPoint ); // FACE under the quad
if ( avoidFace < 1 && pn1->_intPoint )
return false;
- _Node* n, *stopNode = avoidSplit.LastNode();
+ _Node* n = 0, *stopNode = avoidSplit.LastNode();
chn.clear();
- if ( !quad._eIntNodes.empty() )
+ if ( !quad._eIntNodes.empty() ) // connect pn2 with EDGE intersections
{
chn.push_back( pn2 );
bool found;
}
int i;
- for ( i = splits.size()-1; i >= 0; --i )
+ for ( i = splits.size()-1; i >= 0; --i ) // connect new pn2 (at _eIntNodes) with a split
{
if ( !splits[i] )
continue;
break;
n = 0;
}
- if ( n && n != stopNode)
+ if ( n && n != stopNode )
{
if ( chn.empty() )
chn.push_back( pn2 );
iS = i-1;
return true;
}
+ else if ( !chn.empty() && chn.back()->_isInternalFlags )
+ {
+ // INTERNAL FACE partially cuts the quad
+ for ( int i = chn.size() - 2; i >= 0; --i )
+ chn.push_back( chn[ i ]);
+ return true;
+ }
return false;
}
//================================================================================
/*!
* \brief Checks transition at the ginen intersection node of a link
*/
- bool Hexahedron::isOutPoint( _Link& link, int iP, SMESH_MesherHelper& helper ) const
+ bool Hexahedron::isOutPoint( _Link& link, int iP,
+ SMESH_MesherHelper& helper, const Solid* solid ) const
{
bool isOut = false;
- const bool moreIntPoints = ( iP+1 < (int) link._fIntPoints.size() );
+ if ( link._fIntNodes[iP]->faces().size() == 1 &&
+ _grid->IsInternal( link._fIntNodes[iP]->face(0) ))
+ return false;
+
+ const bool moreIntPoints = ( iP+1 < (int) link._fIntNodes.size() );
// get 2 _Node's
_Node* n1 = link._fIntNodes[ iP ];
// get all FACEs under n1 and n2
set< TGeomID > faceIDs;
- if ( moreIntPoints ) faceIDs.insert( link._fIntPoints[iP+1]->_faceIDs.begin(),
- link._fIntPoints[iP+1]->_faceIDs.end() );
+ if ( moreIntPoints ) faceIDs.insert( link._fIntNodes[iP+1]->faces().begin(),
+ link._fIntNodes[iP+1]->faces().end() );
if ( n2->_intPoint ) faceIDs.insert( n2->_intPoint->_faceIDs.begin(),
n2->_intPoint->_faceIDs.end() );
if ( faceIDs.empty() )
return false; // n2 is inside
if ( n1->_intPoint ) faceIDs.insert( n1->_intPoint->_faceIDs.begin(),
n1->_intPoint->_faceIDs.end() );
- faceIDs.insert( link._fIntPoints[iP]->_faceIDs.begin(),
- link._fIntPoints[iP]->_faceIDs.end() );
+ faceIDs.insert( link._fIntNodes[iP]->faces().begin(),
+ link._fIntNodes[iP]->faces().end() );
// get a point between 2 nodes
gp_Pnt p1 = n1->Point();
for ( ; faceID != faceIDs.end(); ++faceID )
{
// project pOnLink on a FACE
- if ( *faceID < 1 ) continue;
- const TopoDS_Face& face = TopoDS::Face( _grid->_shapes( *faceID ));
- GeomAPI_ProjectPointOnSurf& proj =
- helper.GetProjector( face, loc, 0.1*_grid->_tol );
+ if ( *faceID < 1 || !solid->Contains( *faceID )) continue;
+ const TopoDS_Face& face = TopoDS::Face( _grid->Shape( *faceID ));
+ GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( face, loc, 0.1*_grid->_tol );
gp_Pnt testPnt = pOnLink.Transformed( loc.Transformation().Inverted() );
proj.Perform( testPnt );
if ( proj.IsDone() && proj.NbPoints() > 0 )
0.1*_grid->_tol,
normal ) < 3 )
{
- if ( face.Orientation() == TopAbs_REVERSED )
+ if ( solid->Orientation( face ) == TopAbs_REVERSED )
normal.Reverse();
gp_Vec v( proj.NearestPoint(), testPnt );
isOut = ( v * normal > 0 );
return;
// get shapes of the FACE
- const TopoDS_Face& face = TopoDS::Face( _grid->_shapes( faceID ));
+ const TopoDS_Face& face = TopoDS::Face( _grid->Shape( faceID ));
list< TopoDS_Edge > edges;
list< int > nbEdges;
int nbW = SMESH_Block::GetOrderedEdges (face, edges, nbEdges);
for ( int i = 0; i < 2; ++i )
{
TGeomID id = i==0 ?
- _grid->_shapes.FindIndex( *e ) :
- _grid->_shapes.FindIndex( SMESH_MesherHelper::IthVertex( 0, *e ));
+ _grid->ShapeID( *e ) :
+ _grid->ShapeID( SMESH_MesherHelper::IthVertex( 0, *e ));
if (( id > 0 ) &&
( std::find( &nShapeIds[0], nShapeIdsEnd, id ) != nShapeIdsEnd ))
{
list< TopoDS_Edge >::iterator e = edges.begin(), eMidOut = edges.end();
for ( ; e != edges.end(); ++e )
{
- if ( !_grid->_shapes.FindIndex( *e ))
+ if ( !_grid->ShapeID( *e ))
continue;
bool isOut = false;
gp_Pnt p;
TGeomID id, *pID = 0;
for ( e = edges.begin(); e != edges.end(); ++e )
{
- if (( id = _grid->_shapes.FindIndex( SMESH_MesherHelper::IthVertex( 0, *e ))) &&
+ if (( id = _grid->ShapeID( SMESH_MesherHelper::IthVertex( 0, *e ))) &&
(( pID = std::find( &nShapeIds[0], nShapeIdsEnd, id )) != nShapeIdsEnd ))
{
//orderShapeIDs[ nbN ] = id;
orderNodes [ nbN++ ] = nodes[ pID - &nShapeIds[0] ];
*pID = -1;
}
- if (( id = _grid->_shapes.FindIndex( *e )) &&
+ if (( id = _grid->ShapeID( *e )) &&
(( pID = std::find( &nShapeIds[0], nShapeIdsEnd, id )) != nShapeIdsEnd ))
{
//orderShapeIDs[ nbN ] = id;
/*!
* \brief Adds computed elements to the mesh
*/
- int Hexahedron::addElements(SMESH_MesherHelper& helper)
+ int Hexahedron::addVolumes( SMESH_MesherHelper& helper )
{
+ F_IntersectPoint noIntPnt;
+ const bool toCheckNodePos = _grid->IsToCheckNodePos();
+
int nbAdded = 0;
// add elements resulted from hexahedron intersection
- //for ( size_t i = 0; i < _volumeDefs.size(); ++i )
+ for ( _volumeDef* volDef = &_volumeDefs; volDef; volDef = volDef->_next )
{
- vector< const SMDS_MeshNode* > nodes( _volumeDefs._nodes.size() );
+ vector< const SMDS_MeshNode* > nodes( volDef->_nodes.size() );
for ( size_t iN = 0; iN < nodes.size(); ++iN )
- if ( !( nodes[iN] = _volumeDefs._nodes[iN]->Node() ))
+ {
+ if ( !( nodes[iN] = volDef->_nodes[iN].Node() ))
{
- if ( const E_IntersectPoint* eip = _volumeDefs._nodes[iN]->EdgeIntPnt() )
- nodes[iN] = _volumeDefs._nodes[iN]->_intPoint->_node =
+ if ( const E_IntersectPoint* eip = volDef->_nodes[iN].EdgeIntPnt() )
+ {
+ nodes[iN] = volDef->_nodes[iN]._intPoint->_node =
helper.AddNode( eip->_point.X(),
eip->_point.Y(),
eip->_point.Z() );
+ if ( _grid->ShapeType( eip->_shapeID ) == TopAbs_VERTEX )
+ helper.GetMeshDS()->SetNodeOnVertex( nodes[iN], eip->_shapeID );
+ else
+ helper.GetMeshDS()->SetNodeOnEdge( nodes[iN], eip->_shapeID );
+ }
else
throw SALOME_Exception("Bug: no node at intersection point");
}
+ else if ( volDef->_nodes[iN]._intPoint &&
+ volDef->_nodes[iN]._intPoint->_node == volDef->_nodes[iN]._node )
+ {
+ // Update position of node at EDGE intersection;
+ // see comment to _Node::Add( E_IntersectPoint )
+ SMESHDS_Mesh* mesh = helper.GetMeshDS();
+ TGeomID shapeID = volDef->_nodes[iN].EdgeIntPnt()->_shapeID;
+ mesh->UnSetNodeOnShape( nodes[iN] );
+ if ( _grid->ShapeType( shapeID ) == TopAbs_VERTEX )
+ mesh->SetNodeOnVertex( nodes[iN], shapeID );
+ else
+ mesh->SetNodeOnEdge( nodes[iN], shapeID );
+ }
+ else if ( toCheckNodePos &&
+ !nodes[iN]->isMarked() &&
+ _grid->ShapeType( nodes[iN]->GetShapeID() ) == TopAbs_FACE )
+ {
+ _grid->SetOnShape( nodes[iN], noIntPnt, /*unset=*/true );
+ nodes[iN]->setIsMarked( true );
+ }
+ }
- if ( !_volumeDefs._quantities.empty() )
+ const SMDS_MeshElement* v = 0;
+ if ( !volDef->_quantities.empty() )
{
- helper.AddPolyhedralVolume( nodes, _volumeDefs._quantities );
+ v = helper.AddPolyhedralVolume( nodes, volDef->_quantities );
}
else
{
switch ( nodes.size() )
{
- case 8: helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3],
- nodes[4],nodes[5],nodes[6],nodes[7] );
+ case 8: v = helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3],
+ nodes[4],nodes[5],nodes[6],nodes[7] );
break;
- case 4: helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3] );
+ case 4: v = helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3] );
break;
- case 6: helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3], nodes[4],nodes[5] );
+ case 6: v = helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3],nodes[4],nodes[5] );
break;
- case 5:
- helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3],nodes[4] );
+ case 5: v = helper.AddVolume( nodes[0],nodes[1],nodes[2],nodes[3],nodes[4] );
break;
}
}
- nbAdded += int ( _volumeDefs._nodes.size() > 0 );
+ if (( volDef->_volume = v ))
+ {
+ helper.GetMeshDS()->SetMeshElementOnShape( v, volDef->_solidID );
+ ++nbAdded;
+ }
}
return nbAdded;
if ( firstIntPnt )
{
hasLinks = true;
- allLinksOut = ( firstIntPnt->_transition == Trans_OUT );
+ allLinksOut = ( firstIntPnt->_transition == Trans_OUT &&
+ !_grid->IsShared( firstIntPnt->_faceIDs[0] ));
}
}
if ( hasLinks && allLinksOut )
return false;
}
+ //================================================================================
+ /*!
+ * \brief Check if a polyherdon has an edge lying on EDGE shared by strange FACE
+ * that will be meshed by other algo
+ */
+ bool Hexahedron::hasStrangeEdge() const
+ {
+ if ( _eIntPoints.size() < 2 )
+ return false;
+
+ TopTools_MapOfShape edges;
+ for ( size_t i = 0; i < _eIntPoints.size(); ++i )
+ {
+ if ( !_grid->IsStrangeEdge( _eIntPoints[i]->_shapeID ))
+ continue;
+ const TopoDS_Shape& s = _grid->Shape( _eIntPoints[i]->_shapeID );
+ if ( s.ShapeType() == TopAbs_EDGE )
+ {
+ if ( ! edges.Add( s ))
+ return true; // an EDGE encounters twice
+ }
+ else
+ {
+ PShapeIteratorPtr edgeIt = _grid->_helper->GetAncestors( s,
+ *_grid->_helper->GetMesh(),
+ TopAbs_EDGE );
+ while ( const TopoDS_Shape* edge = edgeIt->next() )
+ if ( ! edges.Add( *edge ))
+ return true; // an EDGE encounters twice
+ }
+ }
+ return false;
+ }
+
//================================================================================
/*!
* \brief Return true if a polyhedron passes _sizeThreshold criterion
*/
- bool Hexahedron::checkPolyhedronSize() const
+ bool Hexahedron::checkPolyhedronSize( bool cutByInternalFace ) const
{
+ if ( cutByInternalFace && !_grid->_toUseThresholdForInternalFaces )
+ {
+ // check if any polygon fully lies on shared/internal FACEs
+ for ( size_t iP = 0; iP < _polygons.size(); ++iP )
+ {
+ const _Face& polygon = _polygons[iP];
+ if ( polygon._links.empty() )
+ continue;
+ bool allNodesInternal = true;
+ for ( size_t iL = 0; iL < polygon._links.size() && allNodesInternal; ++iL )
+ {
+ _Node* n = polygon._links[ iL ].FirstNode();
+ allNodesInternal = (( n->IsCutByInternal() ) ||
+ ( n->_intPoint && _grid->IsAnyShared( n->_intPoint->_faceIDs )));
+ }
+ if ( allNodesInternal )
+ return true;
+ }
+ }
+ if ( this->hasStrangeEdge() )
+ return true;
+
double volume = 0;
for ( size_t iP = 0; iP < _polygons.size(); ++iP )
{
double initVolume = _sideLength[0] * _sideLength[1] * _sideLength[2];
- return volume > initVolume / _sizeThreshold;
+ return volume > initVolume / _grid->_sizeThreshold;
}
//================================================================================
/*!
}
}
if ( nbN == 8 )
- _volumeDefs.set( &nodes[0], 8 );
+ _volumeDefs.Set( &nodes[0], 8 );
return nbN == 8;
}
if ( tria->_links[i]._link == link )
{
nodes[3] = tria->_links[(i+1)%3].LastNode();
- _volumeDefs.set( &nodes[0], 4 );
+ _volumeDefs.Set( &nodes[0], 4 );
return true;
}
}
}
if ( nbN == 6 )
- _volumeDefs.set( &nodes[0], 6 );
+ _volumeDefs.Set( &nodes[0], 6 );
return ( nbN == 6 );
}
if ( tria->_links[i]._link == link )
{
nodes[4] = tria->_links[(i+1)%3].LastNode();
- _volumeDefs.set( &nodes[0], 5 );
+ _volumeDefs.Set( &nodes[0], 5 );
return true;
}
( _grid->_coords[2][ _k ] - _grid->_tol > uvw[2] ) ||
( _grid->_coords[2][ _k+1 ] + _grid->_tol < uvw[2] ));
}
+ //================================================================================
+ /*!
+ * \brief Divide a polygon into triangles and modify accordingly an adjacent polyhedron
+ */
+ void splitPolygon( const SMDS_MeshElement* polygon,
+ SMDS_VolumeTool & volume,
+ const int facetIndex,
+ const TGeomID faceID,
+ const TGeomID solidID,
+ SMESH_MeshEditor::ElemFeatures& face,
+ SMESH_MeshEditor& editor,
+ const bool reinitVolume)
+ {
+ SMESH_MeshAlgos::Triangulate divider(/*optimize=*/false);
+ int nbTrias = divider.GetTriangles( polygon, face.myNodes );
+ face.myNodes.resize( nbTrias * 3 );
+
+ SMESH_MeshEditor::ElemFeatures newVolumeDef;
+ newVolumeDef.Init( volume.Element() );
+ newVolumeDef.SetID( volume.Element()->GetID() );
+
+ newVolumeDef.myPolyhedQuantities.reserve( volume.NbFaces() + nbTrias );
+ newVolumeDef.myNodes.reserve( volume.NbNodes() + nbTrias * 3 );
+
+ SMESHDS_Mesh* meshDS = editor.GetMeshDS();
+ SMDS_MeshElement* newTriangle;
+ for ( int iF = 0, nF = volume.NbFaces(); iF < nF; iF++ )
+ {
+ if ( iF == facetIndex )
+ {
+ newVolumeDef.myPolyhedQuantities.push_back( 3 );
+ newVolumeDef.myNodes.insert( newVolumeDef.myNodes.end(),
+ face.myNodes.begin(),
+ face.myNodes.begin() + 3 );
+ meshDS->RemoveFreeElement( polygon, 0, false );
+ newTriangle = meshDS->AddFace( face.myNodes[0], face.myNodes[1], face.myNodes[2] );
+ meshDS->SetMeshElementOnShape( newTriangle, faceID );
+ }
+ else
+ {
+ const SMDS_MeshNode** nn = volume.GetFaceNodes( iF );
+ const size_t nbFaceNodes = volume.NbFaceNodes ( iF );
+ newVolumeDef.myPolyhedQuantities.push_back( nbFaceNodes );
+ newVolumeDef.myNodes.insert( newVolumeDef.myNodes.end(), nn, nn + nbFaceNodes );
+ }
+ }
+
+ for ( size_t iN = 3; iN < face.myNodes.size(); iN += 3 )
+ {
+ newVolumeDef.myPolyhedQuantities.push_back( 3 );
+ newVolumeDef.myNodes.insert( newVolumeDef.myNodes.end(),
+ face.myNodes.begin() + iN,
+ face.myNodes.begin() + iN + 3 );
+ newTriangle = meshDS->AddFace( face.myNodes[iN], face.myNodes[iN+1], face.myNodes[iN+2] );
+ meshDS->SetMeshElementOnShape( newTriangle, faceID );
+ }
+
+ meshDS->RemoveFreeElement( volume.Element(), 0, false );
+ SMDS_MeshElement* newVolume = editor.AddElement( newVolumeDef.myNodes, newVolumeDef );
+ meshDS->SetMeshElementOnShape( newVolume, solidID );
+
+ if ( reinitVolume )
+ {
+ volume.Set( 0 );
+ volume.Set( newVolume );
+ }
+ return;
+ }
+ //================================================================================
+ /*!
+ * \brief Create mesh faces at free facets
+ */
+ void Hexahedron::addFaces( SMESH_MesherHelper& helper,
+ const vector< const SMDS_MeshElement* > & boundaryVolumes )
+ {
+ if ( !_grid->_toCreateFaces )
+ return;
+
+ SMDS_VolumeTool vTool;
+ vector<int> bndFacets;
+ SMESH_MeshEditor editor( helper.GetMesh() );
+ SMESH_MeshEditor::ElemFeatures face( SMDSAbs_Face );
+ SMESHDS_Mesh* meshDS = helper.GetMeshDS();
+
+ // check if there are internal or shared FACEs
+ bool hasInternal = ( !_grid->_geometry.IsOneSolid() ||
+ _grid->_geometry._soleSolid.HasInternalFaces() );
+
+ for ( size_t iV = 0; iV < boundaryVolumes.size(); ++iV )
+ {
+ if ( !vTool.Set( boundaryVolumes[ iV ]))
+ continue;
+
+ TGeomID solidID = vTool.Element()->GetShapeID();
+ Solid * solid = _grid->GetOneOfSolids( solidID );
+
+ // find boundary facets
+
+ bndFacets.clear();
+ for ( int iF = 0, n = vTool.NbFaces(); iF < n; iF++ )
+ {
+ bool isBoundary = vTool.IsFreeFace( iF );
+ if ( isBoundary )
+ {
+ bndFacets.push_back( iF );
+ }
+ else if ( hasInternal )
+ {
+ // check if all nodes are on internal/shared FACEs
+ isBoundary = true;
+ const SMDS_MeshNode** nn = vTool.GetFaceNodes( iF );
+ const size_t nbFaceNodes = vTool.NbFaceNodes ( iF );
+ for ( size_t iN = 0; iN < nbFaceNodes && isBoundary; ++iN )
+ isBoundary = ( nn[ iN ]->GetShapeID() != solidID );
+ if ( isBoundary )
+ bndFacets.push_back( -( iF+1 )); // !!! minus ==> to check the FACE
+ }
+ }
+ if ( bndFacets.empty() )
+ continue;
+
+ // create faces
+
+ if ( !vTool.IsPoly() )
+ vTool.SetExternalNormal();
+ for ( size_t i = 0; i < bndFacets.size(); ++i ) // loop on boundary facets
+ {
+ const bool isBoundary = ( bndFacets[i] >= 0 );
+ const int iFacet = isBoundary ? bndFacets[i] : -bndFacets[i]-1;
+ const SMDS_MeshNode** nn = vTool.GetFaceNodes( iFacet );
+ const size_t nbFaceNodes = vTool.NbFaceNodes ( iFacet );
+ face.myNodes.assign( nn, nn + nbFaceNodes );
+
+ TGeomID faceID = 0;
+ const SMDS_MeshElement* existFace = 0, *newFace = 0;
+
+ if (( existFace = meshDS->FindElement( face.myNodes, SMDSAbs_Face )))
+ {
+ if ( existFace->isMarked() )
+ continue; // created by this method
+ faceID = existFace->GetShapeID();
+ }
+ else
+ {
+ // look for a supporting FACE
+ for ( size_t iN = 0; iN < nbFaceNodes && !faceID; ++iN ) // look for a node on FACE
+ {
+ if ( nn[ iN ]->GetPosition()->GetDim() == 2 )
+ faceID = nn[ iN ]->GetShapeID();
+ }
+ for ( size_t iN = 0; iN < nbFaceNodes && !faceID; ++iN )
+ {
+ // look for a father FACE of EDGEs and VERTEXes
+ const TopoDS_Shape& s1 = _grid->Shape( nn[ iN ]->GetShapeID() );
+ const TopoDS_Shape& s2 = _grid->Shape( nn[ iN+1 ]->GetShapeID() );
+ if ( s1 != s2 && s1.ShapeType() == TopAbs_EDGE && s2.ShapeType() == TopAbs_EDGE )
+ {
+ TopoDS_Shape f = helper.GetCommonAncestor( s1, s2, *helper.GetMesh(), TopAbs_FACE );
+ if ( !f.IsNull() )
+ faceID = _grid->ShapeID( f );
+ }
+ }
+
+ bool toCheckFace = faceID && (( !isBoundary ) ||
+ ( hasInternal && _grid->_toUseThresholdForInternalFaces ));
+ if ( toCheckFace ) // check if all nodes are on the found FACE
+ {
+ SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMeshContaining( faceID );
+ for ( size_t iN = 0; iN < nbFaceNodes && faceID; ++iN )
+ {
+ TGeomID subID = nn[ iN ]->GetShapeID();
+ if ( subID != faceID && !faceSM->DependsOn( subID ))
+ faceID = 0;
+ }
+ if ( !faceID && !isBoundary )
+ continue;
+ }
+ }
+ // orient a new face according to supporting FACE orientation in shape_to_mesh
+ if ( !solid->IsOutsideOriented( faceID ))
+ {
+ if ( existFace )
+ editor.Reorient( existFace );
+ else
+ std::reverse( face.myNodes.begin(), face.myNodes.end() );
+ }
+
+ if ( ! ( newFace = existFace ))
+ {
+ face.SetPoly( nbFaceNodes > 4 );
+ newFace = editor.AddElement( face.myNodes, face );
+ if ( !newFace )
+ continue;
+ newFace->setIsMarked( true ); // to distinguish from face created in getBoundaryElems()
+ }
+
+ if ( faceID && _grid->IsBoundaryFace( faceID )) // face is not shared
+ {
+ // set newFace to the found FACE provided that it fully lies on the FACE
+ for ( size_t iN = 0; iN < nbFaceNodes && faceID; ++iN )
+ if ( nn[iN]->GetShapeID() == solidID )
+ {
+ if ( existFace )
+ meshDS->UnSetMeshElementOnShape( existFace, _grid->Shape( faceID ));
+ faceID = 0;
+ }
+ }
+
+ // split a polygon that will be used by other 3D algorithm
+ if ( faceID && nbFaceNodes > 4 &&
+ !_grid->IsInternal( faceID ) &&
+ !_grid->IsShared( faceID ) &&
+ !_grid->IsBoundaryFace( faceID ))
+ {
+ splitPolygon( newFace, vTool, iFacet, faceID, solidID,
+ face, editor, i+1 < bndFacets.size() );
+ }
+ else
+ {
+ if ( faceID )
+ meshDS->SetMeshElementOnShape( newFace, faceID );
+ else
+ meshDS->SetMeshElementOnShape( newFace, solidID );
+ }
+ } // loop on bndFacets
+ } // loop on boundaryVolumes
+
+
+ // Orient coherently mesh faces on INTERNAL FACEs
+
+ if ( hasInternal )
+ {
+ TopExp_Explorer faceExp( _grid->_geometry._mainShape, TopAbs_FACE );
+ for ( ; faceExp.More(); faceExp.Next() )
+ {
+ if ( faceExp.Current().Orientation() != TopAbs_INTERNAL )
+ continue;
+
+ SMESHDS_SubMesh* sm = meshDS->MeshElements( faceExp.Current() );
+ if ( !sm ) continue;
+
+ TIDSortedElemSet facesToOrient;
+ for ( SMDS_ElemIteratorPtr fIt = sm->GetElements(); fIt->more(); )
+ facesToOrient.insert( facesToOrient.end(), fIt->next() );
+ if ( facesToOrient.size() < 2 )
+ continue;
+
+ gp_Dir direction(1,0,0);
+ const SMDS_MeshElement* anyFace = *facesToOrient.begin();
+ editor.Reorient2D( facesToOrient, direction, anyFace );
+ }
+ }
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Create mesh segments.
+ */
+ void Hexahedron::addSegments( SMESH_MesherHelper& helper,
+ const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap )
+ {
+ SMESHDS_Mesh* mesh = helper.GetMeshDS();
+
+ std::vector<const SMDS_MeshNode*> nodes;
+ std::vector<const SMDS_MeshElement *> elems;
+ map< TGeomID, vector< TGeomID > >::const_iterator e2ff = edge2faceIDsMap.begin();
+ for ( ; e2ff != edge2faceIDsMap.end(); ++e2ff )
+ {
+ const TopoDS_Edge& edge = TopoDS::Edge( _grid->Shape( e2ff->first ));
+ const TopoDS_Face& face = TopoDS::Face( _grid->Shape( e2ff->second[0] ));
+ StdMeshers_FaceSide side( face, edge, helper.GetMesh(), /*isFwd=*/true, /*skipMed=*/true );
+ nodes = side.GetOrderedNodes();
+
+ elems.clear();
+ if ( nodes.size() == 2 )
+ // check that there is an element connecting two nodes
+ if ( !mesh->GetElementsByNodes( nodes, elems ))
+ continue;
+
+ for ( size_t i = 1; i < nodes.size(); i++ )
+ {
+ SMDS_MeshElement* segment = mesh->AddEdge( nodes[i-1], nodes[i] );
+ mesh->SetMeshElementOnShape( segment, e2ff->first );
+ }
+ }
+ return;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return created volumes and volumes that can have free facet because of
+ * skipped small volume. Also create mesh faces on free facets
+ * of adjacent not-cut volumes id the result volume is too small.
+ */
+ void Hexahedron::getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryElems )
+ {
+ if ( _hasTooSmall /*|| _volumeDefs.IsEmpty()*/ )
+ {
+ // create faces around a missing small volume
+ TGeomID faceID = 0;
+ SMESH_MeshEditor editor( _grid->_helper->GetMesh() );
+ SMESH_MeshEditor::ElemFeatures polygon( SMDSAbs_Face );
+ SMESHDS_Mesh* meshDS = _grid->_helper->GetMeshDS();
+ std::vector<const SMDS_MeshElement *> adjVolumes(2);
+ for ( size_t iF = 0; iF < _polygons.size(); ++iF )
+ {
+ const size_t nbLinks = _polygons[ iF ]._links.size();
+ if ( nbLinks != 4 ) continue;
+ polygon.myNodes.resize( nbLinks );
+ polygon.myNodes.back() = 0;
+ for ( size_t iL = 0, iN = nbLinks - 1; iL < nbLinks; ++iL, --iN )
+ if ( ! ( polygon.myNodes[iN] = _polygons[ iF ]._links[ iL ].FirstNode()->Node() ))
+ break;
+ if ( !polygon.myNodes.back() )
+ continue;
+
+ meshDS->GetElementsByNodes( polygon.myNodes, adjVolumes, SMDSAbs_Volume );
+ if ( adjVolumes.size() != 1 )
+ continue;
+ if ( !adjVolumes[0]->isMarked() )
+ {
+ boundaryElems.push_back( adjVolumes[0] );
+ adjVolumes[0]->setIsMarked( true );
+ }
+
+ bool sameShape = true;
+ TGeomID shapeID = polygon.myNodes[0]->GetShapeID();
+ for ( size_t i = 1; i < polygon.myNodes.size() && sameShape; ++i )
+ sameShape = ( shapeID == polygon.myNodes[i]->GetShapeID() );
+
+ if ( !sameShape || !_grid->IsSolid( shapeID ))
+ continue; // some of shapes must be FACE
+
+ if ( !faceID )
+ {
+ faceID = getAnyFace();
+ if ( !faceID )
+ break;
+ if ( _grid->IsInternal( faceID ) ||
+ _grid->IsShared( faceID ) ||
+ _grid->IsBoundaryFace( faceID ))
+ break; // create only if a new face will be used by other 3D algo
+ }
+
+ Solid * solid = _grid->GetOneOfSolids( adjVolumes[0]->GetShapeID() );
+ if ( !solid->IsOutsideOriented( faceID ))
+ std::reverse( polygon.myNodes.begin(), polygon.myNodes.end() );
+
+ //polygon.SetPoly( polygon.myNodes.size() > 4 );
+ const SMDS_MeshElement* newFace = editor.AddElement( polygon.myNodes, polygon );
+ meshDS->SetMeshElementOnShape( newFace, faceID );
+ }
+ }
+
+ // return created volumes
+ for ( _volumeDef* volDef = &_volumeDefs; volDef; volDef = volDef->_next )
+ {
+ if ( volDef->_volume && !volDef->_volume->isMarked() )
+ {
+ volDef->_volume->setIsMarked( true );
+ boundaryElems.push_back( volDef->_volume );
+
+ if ( _grid->IsToCheckNodePos() ) // un-mark nodes marked in addVolumes()
+ for ( size_t iN = 0; iN < volDef->_nodes.size(); ++iN )
+ volDef->_nodes[iN].Node()->setIsMarked( false );
+ }
+ }
+ }
+
+ //================================================================================
+ /*!
+ * \brief Set to _hexLinks a next portion of splits located on one side of INTERNAL FACEs
+ */
+ bool Hexahedron::_SplitIterator::Next()
+ {
+ if ( _iterationNb > 0 )
+ // count used splits
+ for ( size_t i = 0; i < _splits.size(); ++i )
+ {
+ if ( _splits[i]._iCheckIteration == _iterationNb )
+ {
+ _splits[i]._isUsed = _splits[i]._checkedSplit->_faces[1];
+ _nbUsed += _splits[i]._isUsed;
+ }
+ if ( !More() )
+ return false;
+ }
+
+ ++_iterationNb;
+
+ bool toTestUsed = ( _nbChecked >= _splits.size() );
+ if ( toTestUsed )
+ {
+ // all splits are checked; find all not used splits
+ for ( size_t i = 0; i < _splits.size(); ++i )
+ if ( !_splits[i].IsCheckedOrUsed( toTestUsed ))
+ _splits[i]._iCheckIteration = _iterationNb;
+
+ _nbUsed = _splits.size(); // to stop iteration
+ }
+ else
+ {
+ // get any not used/checked split to start from
+ _freeNodes.clear();
+ for ( size_t i = 0; i < _splits.size(); ++i )
+ {
+ if ( !_splits[i].IsCheckedOrUsed( toTestUsed ))
+ {
+ _freeNodes.push_back( _splits[i]._nodes[0] );
+ _freeNodes.push_back( _splits[i]._nodes[1] );
+ _splits[i]._iCheckIteration = _iterationNb;
+ break;
+ }
+ }
+ // find splits connected to the start one via _freeNodes
+ for ( size_t iN = 0; iN < _freeNodes.size(); ++iN )
+ {
+ for ( size_t iS = 0; iS < _splits.size(); ++iS )
+ {
+ if ( _splits[iS].IsCheckedOrUsed( toTestUsed ))
+ continue;
+ int iN2 = -1;
+ if ( _freeNodes[iN] == _splits[iS]._nodes[0] )
+ iN2 = 1;
+ else if ( _freeNodes[iN] == _splits[iS]._nodes[1] )
+ iN2 = 0;
+ else
+ continue;
+ if ( _freeNodes[iN]->_isInternalFlags > 0 )
+ {
+ if ( _splits[iS]._nodes[ iN2 ]->_isInternalFlags == 0 )
+ continue;
+ if ( !_splits[iS]._nodes[ iN2 ]->IsLinked( _freeNodes[iN]->_intPoint ))
+ continue;
+ }
+ _splits[iS]._iCheckIteration = _iterationNb;
+ _freeNodes.push_back( _splits[iS]._nodes[ iN2 ]);
+ }
+ }
+ }
+ // set splits to hex links
+
+ for ( int iL = 0; iL < 12; ++iL )
+ _hexLinks[ iL ]._splits.clear();
+
+ _Link split;
+ for ( size_t i = 0; i < _splits.size(); ++i )
+ {
+ if ( _splits[i]._iCheckIteration == _iterationNb )
+ {
+ split._nodes[0] = _splits[i]._nodes[0];
+ split._nodes[1] = _splits[i]._nodes[1];
+ _Link & hexLink = _hexLinks[ _splits[i]._linkID ];
+ hexLink._splits.push_back( split );
+ _splits[i]._checkedSplit = & hexLink._splits.back();
+ ++_nbChecked;
+ }
+ }
+ return More();
+ }
//================================================================================
/*!
_computeCanceled = false;
SMESH_MesherHelper helper( theMesh );
+ SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
try
{
Grid grid;
- grid._helper = &helper;
+ grid._helper = &helper;
+ grid._toAddEdges = _hyp->GetToAddEdges();
+ grid._toCreateFaces = _hyp->GetToCreateFaces();
+ grid._toConsiderInternalFaces = _hyp->GetToConsiderInternalFaces();
+ grid._toUseThresholdForInternalFaces = _hyp->GetToUseThresholdForInternalFaces();
+ grid._sizeThreshold = _hyp->GetSizeThreshold();
+ grid.InitGeometry( theShape );
vector< TopoDS_Shape > faceVec;
{
TopTools_MapOfShape faceMap;
TopExp_Explorer fExp;
for ( fExp.Init( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
- if ( !faceMap.Add( fExp.Current() ))
- faceMap.Remove( fExp.Current() ); // remove a face shared by two solids
-
- for ( fExp.ReInit(); fExp.More(); fExp.Next() )
- if ( faceMap.Contains( fExp.Current() ))
- faceVec.push_back( fExp.Current() );
+ {
+ bool isNewFace = faceMap.Add( fExp.Current() );
+ if ( !grid._toConsiderInternalFaces )
+ if ( !isNewFace || fExp.Current().Orientation() == TopAbs_INTERNAL )
+ // remove an internal face
+ faceMap.Remove( fExp.Current() );
+ }
+ faceVec.reserve( faceMap.Extent() );
+ faceVec.assign( faceMap.cbegin(), faceMap.cend() );
}
vector<FaceGridIntersector> facesItersectors( faceVec.size() );
- map< TGeomID, vector< TGeomID > > edge2faceIDsMap;
- TopExp_Explorer eExp;
Bnd_Box shapeBox;
for ( size_t i = 0; i < faceVec.size(); ++i )
{
- facesItersectors[i]._face = TopoDS::Face ( faceVec[i] );
- facesItersectors[i]._faceID = grid._shapes.Add( faceVec[i] );
+ facesItersectors[i]._face = TopoDS::Face( faceVec[i] );
+ facesItersectors[i]._faceID = grid.ShapeID( faceVec[i] );
facesItersectors[i]._grid = &grid;
shapeBox.Add( facesItersectors[i].GetFaceBndBox() );
-
- if ( _hyp->GetToAddEdges() )
- {
- helper.SetSubShape( faceVec[i] );
- for ( eExp.Init( faceVec[i], TopAbs_EDGE ); eExp.More(); eExp.Next() )
- {
- const TopoDS_Edge& edge = TopoDS::Edge( eExp.Current() );
- if ( !SMESH_Algo::isDegenerated( edge ) &&
- !helper.IsRealSeam( edge ))
- edge2faceIDsMap[ grid._shapes.Add( edge )].push_back( facesItersectors[i]._faceID );
- }
- }
}
-
getExactBndBox( faceVec, _hyp->GetAxisDirs(), shapeBox );
+
vector<double> xCoords, yCoords, zCoords;
_hyp->GetCoordinates( xCoords, yCoords, zCoords, shapeBox );
BRepBuilderAPI_Copy copier;
for ( size_t i = 0; i < facesItersectors.size(); ++i )
{
- if ( !facesItersectors[i].IsThreadSafe(tshapes) )
+ if ( !facesItersectors[i].IsThreadSafe( tshapes ))
{
copier.Perform( facesItersectors[i]._face );
facesItersectors[i]._face = TopoDS::Face( copier );
for ( size_t i = 0; i < facesItersectors.size(); ++i )
facesItersectors[i].StoreIntersections();
- TopExp_Explorer solidExp (theShape, TopAbs_SOLID);
- helper.SetSubShape( solidExp.Current() );
- helper.SetElementsOnShape( true );
-
if ( _computeCanceled ) return false;
// create nodes on the geometry
- grid.ComputeNodes(helper);
+ grid.ComputeNodes( helper );
if ( _computeCanceled ) return false;
+ // get EDGEs to take into account
+ map< TGeomID, vector< TGeomID > > edge2faceIDsMap;
+ grid.GetEdgesToImplement( edge2faceIDsMap, theShape, faceVec );
+
// create volume elements
- Hexahedron hex( _hyp->GetSizeThreshold(), &grid );
+ Hexahedron hex( &grid );
int nbAdded = hex.MakeElements( helper, edge2faceIDsMap );
- SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
if ( nbAdded > 0 )
{
- // make all SOLIDs computed
- if ( SMESHDS_SubMesh* sm1 = meshDS->MeshElements( solidExp.Current()) )
+ if ( !grid._toConsiderInternalFaces )
{
- SMDS_ElemIteratorPtr volIt = sm1->GetElements();
- for ( ; solidExp.More() && volIt->more(); solidExp.Next() )
+ // make all SOLIDs computed
+ TopExp_Explorer solidExp( theShape, TopAbs_SOLID );
+ if ( SMESHDS_SubMesh* sm1 = meshDS->MeshElements( solidExp.Current()) )
{
- const SMDS_MeshElement* vol = volIt->next();
- sm1->RemoveElement( vol );
- meshDS->SetMeshElementOnShape( vol, solidExp.Current() );
+ SMDS_ElemIteratorPtr volIt = sm1->GetElements();
+ for ( ; solidExp.More() && volIt->more(); solidExp.Next() )
+ {
+ const SMDS_MeshElement* vol = volIt->next();
+ sm1->RemoveElement( vol );
+ meshDS->SetMeshElementOnShape( vol, solidExp.Current() );
+ }
}
}
// make other sub-shapes computed
}
// remove free nodes
- if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( helper.GetSubShapeID() ))
+ //if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( helper.GetSubShapeID() ))
{
- TIDSortedNodeSet nodesToRemove;
+ std::vector< const SMDS_MeshNode* > nodesToRemove;
// get intersection nodes
for ( int iDir = 0; iDir < 3; ++iDir )
{
{
multiset< F_IntersectPoint >::iterator ip = lines[i]._intPoints.begin();
for ( ; ip != lines[i]._intPoints.end(); ++ip )
- if ( ip->_node && ip->_node->NbInverseElements() == 0 )
- nodesToRemove.insert( nodesToRemove.end(), ip->_node );
+ if ( ip->_node && ip->_node->NbInverseElements() == 0 && !ip->_node->isMarked() )
+ {
+ nodesToRemove.push_back( ip->_node );
+ ip->_node->setIsMarked( true );
+ }
}
}
// get grid nodes
for ( size_t i = 0; i < grid._nodes.size(); ++i )
- if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 )
- nodesToRemove.insert( nodesToRemove.end(), grid._nodes[i] );
+ if ( grid._nodes[i] && grid._nodes[i]->NbInverseElements() == 0 &&
+ !grid._nodes[i]->isMarked() )
+ {
+ nodesToRemove.push_back( grid._nodes[i] );
+ grid._nodes[i]->setIsMarked( true );
+ }
// do remove
- TIDSortedNodeSet::iterator n = nodesToRemove.begin();
- for ( ; n != nodesToRemove.end(); ++n )
- meshDS->RemoveFreeNode( *n, smDS, /*fromGroups=*/false );
+ for ( size_t i = 0; i < nodesToRemove.size(); ++i )
+ meshDS->RemoveFreeNode( nodesToRemove[i], /*smD=*/0, /*fromGroups=*/false );
}
return nbAdded;
for ( TopExp_Explorer soExp( theShape, TopAbs_SOLID ); soExp.More(); soExp.Next() )
_EventListener::setAlwaysComputed( true, theMesh.GetSubMesh( soExp.Current() ));
}
-
iE = theEdgeInd % NbEdges();
iEnd = iE + 1;
}
- for ( iE = 0; iE < iEnd; ++iE )
+ for ( ; iE < iEnd; ++iE )
{
double prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
*/
//=============================================================================
-ostream & StdMeshers_Geometric1D::SaveTo(ostream & save)
+std::ostream & StdMeshers_Geometric1D::SaveTo(std::ostream & save)
{
save << _begLength << " " << _ratio << " ";
*/
//=============================================================================
-istream & StdMeshers_Geometric1D::LoadFrom(istream & load)
+std::istream & StdMeshers_Geometric1D::LoadFrom(std::istream & load)
{
bool isOK = true;
isOK = static_cast<bool>(load >> _begLength);
#include <TopExp_Explorer.hxx>
#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
#include <vector>
-#include <TopoDS.hxx>
using namespace std;
//=======================================================================
//function : StdMeshers_PolygonPerFace_2D
-//purpose :
+//purpose :
//=======================================================================
StdMeshers_PolygonPerFace_2D::StdMeshers_PolygonPerFace_2D(int hypId,
--- /dev/null
+// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, 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 : StdMeshers_PolyhedronPerSolid_3D.cxx
+// Module : SMESH
+// Created : Fri Oct 20 11:37:07 2006
+// Author : Edward AGAPOV (eap)
+//
+#include "StdMeshers_PolyhedronPerSolid_3D.hxx"
+
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_ControlsDef.hxx"
+#include "SMESH_Gen.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_MesherHelper.hxx"
+#include "SMESH_ProxyMesh.hxx"
+#include "SMESH_subMesh.hxx"
+#include "StdMeshers_PolygonPerFace_2D.hxx"
+#include "StdMeshers_Regular_1D.hxx"
+#include "StdMeshers_ViscousLayers.hxx"
+
+#include <TopExp_Explorer.hxx>
+
+#include <vector>
+#include <set>
+
+namespace
+{
+ struct _EdgeMesher : public StdMeshers_Regular_1D
+ {
+ _EdgeMesher( int hypId, SMESH_Gen* gen )
+ : StdMeshers_Regular_1D( hypId, gen )
+ {
+ _hypType = NB_SEGMENTS;
+ _ivalue[ NB_SEGMENTS_IND ] = 1;
+ }
+ };
+
+ //=======================================================================
+ //function : addHexa
+ //purpose :
+ //=======================================================================
+
+ const SMDS_MeshElement* addHexa( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newHexa = 0;
+
+ // check nb of nodes in faces
+ for ( size_t i = 0; i < quantities.size(); ++i )
+ if ( quantities[ i ] != 4 )
+ return newHexa;
+
+ // look for a top face
+ const SMDS_MeshElement* topFace = 0;
+ const SMDS_MeshElement* botFace = faces[0];
+ std::vector< const SMDS_MeshNode* > nodes( 16 ); // last 8 is a working buffer
+ nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
+ for ( size_t iF = 1; iF < faces.size() && !topFace; ++iF )
+ {
+ bool hasCommonNode = false;
+ for ( int iN = 0; iN < quantities[ 0 ] && !hasCommonNode; ++iN )
+ hasCommonNode = ( faces[ iF ]->GetNodeIndex( nodes[ iN ]) >= 0 );
+
+ if ( !hasCommonNode )
+ topFace = faces[ iF ];
+ }
+
+ nodes.resize( 8 ); // set top nodes after hexa nodes - [8-11]
+ nodes.insert( nodes.end(), topFace->begin_nodes(), topFace->end_nodes() );
+ nodes.resize( 12 );
+ nodes.insert( nodes.end(), nodes.begin() + 8, nodes.begin() + 12 );
+
+ // find corresponding nodes of top and bottom by finding a side face including 2 node of each
+ SMESHDS_Mesh* mesh = helper.GetMeshDS();
+ const SMDS_MeshElement* sideFace = 0;
+ size_t i;
+ for ( i = 8; i < nodes.size()-1 && !sideFace; ++i )
+ {
+ sideFace = mesh->FindFace( nodes[0], nodes[1], nodes[ i ], nodes[ i + 1 ]);
+ }
+ if ( !sideFace )
+ return newHexa;
+
+ --i; // restore after ++i in the loop
+ bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ] );
+ bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ i ], nodes[ i + 1 ] );
+ if ( botOriRight == topOriRight )
+ {
+ nodes[ 4 ] = nodes[ i + 1 ];
+ nodes[ 5 ] = nodes[ i + 0 ];
+ nodes[ 6 ] = nodes[ i + 3 ];
+ nodes[ 7 ] = nodes[ i + 2 ];
+ }
+ else
+ {
+ nodes[ 4 ] = nodes[ i + 0 ];
+ nodes[ 5 ] = nodes[ i + 1 ];
+ nodes[ 6 ] = nodes[ i + 2 ];
+ nodes[ 7 ] = nodes[ i + 3 ];
+ }
+
+ newHexa = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ],
+ nodes[ 4 ], nodes[ 5 ], nodes[ 6 ], nodes[ 7 ]);
+
+ return newHexa;
+ }
+
+ //=======================================================================
+ //function : addTetra
+ //purpose :
+ //=======================================================================
+
+ const SMDS_MeshElement* addTetra( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newTetra = 0;
+
+ // check nb of nodes in faces
+ for ( size_t i = 0; i < quantities.size(); ++i )
+ if ( quantities[ i ] != 3 )
+ return newTetra;
+
+ const SMDS_MeshElement* botFace = faces[0];
+
+ std::vector< const SMDS_MeshNode* > nodes( 6 );
+ nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
+ nodes.resize( 3 );
+
+ const SMDS_MeshNode* topNode = 0;
+ for ( size_t i = 0; i < 3 && !topNode; ++i )
+ {
+ topNode = faces[ 1 ]->GetNode( i );
+ if ( botFace->GetNodeIndex( topNode ) >= 0 )
+ topNode = 0;
+ }
+ if ( !topNode )
+ return newTetra;
+
+ nodes.push_back( topNode );
+
+ newTetra = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
+
+ return newTetra;
+ }
+
+ //=======================================================================
+ //function : addPenta
+ //purpose :
+ //=======================================================================
+
+ const SMDS_MeshElement* addPenta( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newPenta = 0;
+
+ // check nb of nodes in faces and find triangle faces
+ int trias[2] = { -1, -1 };
+ for ( size_t i = 0; i < quantities.size(); ++i )
+ if ( quantities[ i ] != 4 )
+ {
+ if ( quantities[ i ] != 3 )
+ return newPenta;
+ int iTria = ( trias[0] != -1 );
+ if ( trias[ iTria ] != -1 )
+ return newPenta;
+ trias[ iTria ] = i;
+ }
+ if ( trias[1] == -1 )
+ return newPenta;
+
+ int iSide = trias[0] + 1;
+ if ( iSide == trias[1] )
+ ++iSide;
+
+ const SMDS_MeshElement* botFace = faces[ trias[0]];
+ const SMDS_MeshElement* topFace = faces[ trias[1]];
+ const SMDS_MeshElement* sideFace = faces[ iSide ];
+ const SMDS_MeshNode* nodes[ 6 ] = { 0,0,0,0,0,0 };
+ for ( int i = 0 ; i < 3; ++i )
+ {
+ const SMDS_MeshNode* botNode = botFace->GetNode( i );
+ if ( sideFace->GetNodeIndex( botNode ) < 0 )
+ nodes[2] = botNode;
+ else
+ nodes[ bool( nodes[0] )] = botNode;
+
+ const SMDS_MeshNode* topNode = topFace->GetNode( i );
+ if ( sideFace->GetNodeIndex( topNode ) < 0 )
+ nodes[5] = topNode;
+ else
+ nodes[ 3 + bool( nodes[3]) ] = topNode;
+ }
+ bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ]);
+ bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 3 ], nodes[ 4 ]);
+ if ( botOriRight == topOriRight )
+ std::swap( nodes[ 3 ], nodes[ 4 ]);
+
+ newPenta = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ],
+ nodes[ 3 ], nodes[ 4 ], nodes[ 5 ]);
+
+ return newPenta;
+ }
+
+ //=======================================================================
+ //function : addPyra
+ //purpose :
+ //=======================================================================
+
+ const SMDS_MeshElement* addPyra( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newPyra = 0;
+
+ // check nb of nodes in faces
+ int iBot = -1;
+ for ( size_t i = 0; i < quantities.size(); ++i )
+ if ( quantities[ i ] != 3 )
+ {
+ if ( quantities[ i ] != 4 || iBot != -1 )
+ return newPyra;
+ iBot = i;
+ }
+
+ const SMDS_MeshElement* botFace = faces[ iBot ];
+
+ std::vector< const SMDS_MeshNode* > nodes( 8 );
+ nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
+ nodes.resize( 4 );
+
+ const SMDS_MeshNode* topNode = 0;
+ for ( size_t i = 0; i < 4 && !topNode; ++i )
+ {
+ topNode = faces[ 1 ]->GetNode( i );
+ if ( botFace->GetNodeIndex( topNode ) >= 0 )
+ topNode = 0;
+ }
+ if ( !topNode )
+ return newPyra;
+
+ nodes.push_back( topNode );
+
+ newPyra = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ], nodes[4] );
+
+ return newPyra;
+ }
+
+ //=======================================================================
+ //function : addHPrism
+ //purpose : add hexagonal prism
+ //=======================================================================
+
+ const SMDS_MeshElement* addHPrism( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newHexPrism = 0;
+
+ // check nb of nodes in faces and find hexagons
+ int hexa[2] = { -1, -1 };
+ for ( size_t i = 0; i < quantities.size(); ++i )
+ if ( quantities[ i ] != 4 )
+ {
+ if ( quantities[ i ] != 6 )
+ return newHexPrism;
+ int iHex = ( hexa[0] != -1 );
+ if ( hexa[ iHex ] != -1 )
+ return newHexPrism;
+ hexa[ iHex ] = i;
+ }
+ if ( hexa[1] == -1 )
+ return newHexPrism;
+
+ int iSide = hexa[0] + 1;
+ if ( iSide == hexa[1] )
+ ++iSide;
+
+ const SMDS_MeshElement* botFace = faces[ hexa[ 0 ]];
+ const SMDS_MeshElement* topFace = faces[ hexa[ 1 ]];
+ std::vector< const SMDS_MeshNode* > nodes( 24 ); // last 12 is a working buffer
+
+ nodes.assign( botFace->begin_nodes(), botFace->end_nodes() );
+ nodes.resize( 12 ); // set top nodes after hexa nodes - [12-17]
+ nodes.insert( nodes.end(), topFace->begin_nodes(), topFace->end_nodes() );
+ nodes.resize( 18 );
+ nodes.insert( nodes.end(), nodes.begin() + 12, nodes.begin() + 18 );
+
+ // find corresponding nodes of top and bottom by finding a side face including 2 node of each
+ SMESHDS_Mesh* mesh = helper.GetMeshDS();
+ const SMDS_MeshElement* sideFace = 0;
+ size_t i;
+ for ( i = 12; i < nodes.size()-1 && !sideFace; ++i )
+ {
+ sideFace = mesh->FindFace( nodes[0], nodes[1], nodes[ i ], nodes[ i + 1 ]);
+ }
+ if ( !sideFace )
+ return newHexPrism;
+
+ --i; // restore after ++i in the loop
+ bool botOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ 0 ], nodes[ 1 ] );
+ bool topOriRight = SMESH_MeshAlgos::IsRightOrder( sideFace, nodes[ i ], nodes[ i + 1 ] );
+ if ( botOriRight == topOriRight )
+ {
+ nodes[ 6 ] = nodes[ i + 1 ];
+ nodes[ 7 ] = nodes[ i + 0 ];
+ nodes[ 8 ] = nodes[ i + 5 ];
+ nodes[ 9 ] = nodes[ i + 4 ];
+ nodes[ 10 ] = nodes[ i + 3 ];
+ nodes[ 11 ] = nodes[ i + 2 ];
+ }
+ else
+ {
+ nodes[ 6 ] = nodes[ i + 0 ];
+ nodes[ 7 ] = nodes[ i + 1 ];
+ nodes[ 8 ] = nodes[ i + 2 ];
+ nodes[ 9 ] = nodes[ i + 3 ];
+ nodes[ 10 ] = nodes[ i + 4 ];
+ nodes[ 11 ] = nodes[ i + 5 ];
+ }
+
+ newHexPrism = helper.AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ],
+ nodes[ 3 ], nodes[ 4 ], nodes[ 5 ],
+ nodes[ 6 ], nodes[ 7 ], nodes[ 8 ],
+ nodes[ 9 ], nodes[10 ], nodes[11 ]);
+
+ return newHexPrism;
+ }
+
+ //=======================================================================
+ //function : addPoly
+ //purpose :
+ //=======================================================================
+
+ const SMDS_MeshElement* addPoly( std::vector< const SMDS_MeshElement* >& faces,
+ const std::vector< int > & quantities,
+ SMESH_MesherHelper & helper )
+ {
+ const SMDS_MeshElement* newPoly = 0;
+
+ std::vector< const SMDS_MeshNode* > nodes;
+ for ( size_t iF = 0; iF < faces.size(); ++iF )
+ nodes.insert( nodes.end(), faces[iF]->begin_nodes(), faces[iF]->end_nodes() );
+
+ newPoly = helper.AddPolyhedralVolume( nodes, quantities );
+
+ return newPoly;
+ }
+
+} // namespace
+
+//=======================================================================
+//function : StdMeshers_PolyhedronPerSolid_3D
+//purpose :
+//=======================================================================
+
+StdMeshers_PolyhedronPerSolid_3D::StdMeshers_PolyhedronPerSolid_3D(int hypId,
+ SMESH_Gen* gen)
+ :SMESH_3D_Algo(hypId, gen),
+ myEdgeMesher( new _EdgeMesher( gen->GetANewId(), gen )),
+ myFaceMesher( new StdMeshers_PolygonPerFace_2D( gen->GetANewId(), gen ))
+{
+ _name = "PolyhedronPerSolid_3D";
+ _requireDiscreteBoundary = false;
+ _supportSubmeshes = true;
+ _compatibleHypothesis.push_back("ViscousLayers");
+ _neededLowerHyps[0] = _neededLowerHyps[1] = _neededLowerHyps[2] = true;
+}
+
+//=======================================================================
+//function : ~StdMeshers_PolyhedronPerSolid_3D
+//purpose :
+//=======================================================================
+
+StdMeshers_PolyhedronPerSolid_3D::~StdMeshers_PolyhedronPerSolid_3D()
+{
+ delete myEdgeMesher;
+ delete myFaceMesher;
+}
+
+//=======================================================================
+//function : CheckHypothesis
+//purpose :
+//=======================================================================
+
+bool StdMeshers_PolyhedronPerSolid_3D::CheckHypothesis(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape,
+ Hypothesis_Status& theStatus)
+{
+ myViscousLayersHyp = NULL;
+
+ const std::list<const SMESHDS_Hypothesis*>& hyps =
+ GetUsedHypothesis( theMesh, theShape, /*ignoreAuxiliary=*/false);
+ std::list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
+ if ( h == hyps.end())
+ {
+ theStatus = SMESH_Hypothesis::HYP_OK;
+ return true;
+ }
+
+ // only StdMeshers_ViscousLayers can be used
+ theStatus = HYP_OK;
+ for ( ; h != hyps.end(); ++h )
+ {
+ if ( !(myViscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h )))
+ break;
+ }
+ if ( !myViscousLayersHyp )
+ theStatus = HYP_INCOMPATIBLE;
+ else
+ error( myViscousLayersHyp->CheckHypothesis( theMesh, theShape, theStatus ));
+
+ return theStatus == HYP_OK;
+}
+
+//=======================================================================
+//function : Compute
+//purpose :
+//=======================================================================
+
+bool StdMeshers_PolyhedronPerSolid_3D::Compute(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape)
+{
+ const SMDS_MeshElement* newVolume = 0;
+
+ SMESH_subMesh* sm = theMesh.GetSubMesh( theShape );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true,
+ /*complexFirst=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ if ( !sm->IsEmpty() )
+ continue;
+
+ const TopoDS_Shape & shape = sm->GetSubShape();
+ switch ( shape.ShapeType() )
+ {
+ case TopAbs_VERTEX:
+ sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ break;
+
+ case TopAbs_EDGE:
+ sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ if ( sm->IsEmpty() )
+ myEdgeMesher->Compute( theMesh, shape );
+ break;
+
+ case TopAbs_FACE:
+ sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
+ if ( sm->IsEmpty() && !myFaceMesher->Compute( theMesh, shape ))
+ {
+ sm->GetComputeError() = myFaceMesher->GetComputeError();
+ sm->GetComputeError()->myAlgo = myFaceMesher;
+ return false;
+ }
+ break;
+
+ case TopAbs_SOLID:
+ {
+ SMESH_MesherHelper helper( theMesh );
+ helper.SetElementsOnShape( true );
+ _quadraticMesh = helper.IsQuadraticSubMesh( shape );
+
+ SMESH_ProxyMesh::Ptr proxymesh( new SMESH_ProxyMesh( theMesh ));
+ if ( myViscousLayersHyp )
+ {
+ proxymesh = myViscousLayersHyp->Compute( theMesh, theShape );
+ if ( !proxymesh )
+ return false;
+ }
+
+ std::vector< const SMDS_MeshElement* > faces;
+ faces.reserve( 20 );
+
+ for ( TopExp_Explorer faceEx( shape, TopAbs_FACE ); faceEx.More(); faceEx.Next() )
+ {
+ const SMESHDS_SubMesh* smDS = proxymesh->GetSubMesh( faceEx.Current() );
+ for ( SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); faceIt->more(); )
+ faces.push_back( faceIt->next() );
+ }
+
+ bool useMediumNodes = false;
+ if ( !_quadraticMesh && theMesh.GetMeshDS()->GetMeshInfo().NbFaces( ORDER_QUADRATIC ))
+ for ( size_t i = 0; i < faces.size() && !useMediumNodes ; ++i )
+ useMediumNodes = faces[ i ]->IsQuadratic();
+
+ std::vector< int > quantities( faces.size() );
+ std::set< const SMDS_MeshNode* > nodes;
+ for ( size_t i = 0; i < faces.size(); ++i )
+ {
+ quantities[ i ] = useMediumNodes ? faces[ i ]->NbNodes() : faces[ i ]->NbCornerNodes();
+ for ( int iN = 0; iN < quantities[ i ]; ++iN )
+ nodes.insert( faces[ i ]->GetNode( iN ));
+ }
+
+ const size_t nbNodes = nodes.size(), nbFaces = faces.size();
+ if ( nbNodes == 8 && nbFaces == 6 ) newVolume = addHexa ( faces, quantities, helper );
+ else if ( nbNodes == 4 && nbFaces == 4 ) newVolume = addTetra ( faces, quantities, helper );
+ else if ( nbNodes == 6 && nbFaces == 5 ) newVolume = addPenta ( faces, quantities, helper );
+ else if ( nbNodes == 5 && nbFaces == 5 ) newVolume = addPyra ( faces, quantities, helper );
+ else if ( nbNodes == 12 && nbFaces == 8 ) newVolume = addHPrism( faces, quantities, helper );
+ if ( !newVolume )
+ newVolume = addPoly ( faces, quantities, helper );
+
+ if ( newVolume )
+ {
+ SMESH::Controls::BadOrientedVolume checker;
+ checker.SetMesh( theMesh.GetMeshDS() );
+ if ( checker.IsSatisfy( newVolume->GetID() ))
+ {
+ SMESH_MeshEditor editor( &theMesh );
+ editor.Reorient( newVolume );
+ }
+ }
+ }
+ default:;
+
+ } // switch ( shape.ShapeType() )
+ } // loop on sub-meshes
+
+ return newVolume;
+}
+
+//=======================================================================
+//function : Evaluate
+//purpose :
+//=======================================================================
+
+bool StdMeshers_PolyhedronPerSolid_3D::Evaluate(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape,
+ MapShapeNbElems& theResMap)
+{
+ _quadraticMesh = false;
+
+ SMESH_subMesh* sm = theMesh.GetSubMesh( theShape );
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true,
+ /*complexFirst=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+
+ MapShapeNbElems::iterator sm2vec = theResMap.find( sm );
+ if ( sm2vec != theResMap.end() && !sm2vec->second.empty() )
+ continue;
+
+ const TopoDS_Shape & shape = sm->GetSubShape();
+ switch ( shape.ShapeType() )
+ {
+ case TopAbs_EDGE:
+ myEdgeMesher->Evaluate( theMesh, shape, theResMap );
+ break;
+
+ case TopAbs_FACE:
+ {
+ myFaceMesher->Evaluate( theMesh, shape, theResMap );
+ std::vector<int> & quantities = theResMap[ sm ];
+ _quadraticMesh = ( !quantities.empty() &&
+ ( quantities[ SMDSEntity_Quad_Triangle ] +
+ quantities[ SMDSEntity_Quad_Quadrangle ] +
+ quantities[ SMDSEntity_Quad_Polygon ]));
+ break;
+ }
+
+ case TopAbs_SOLID:
+ {
+ std::vector<int> & quantities = theResMap[ sm ];
+ quantities.resize( SMDSEntity_Last, 0 );
+
+ SMESH_MesherHelper helper( theMesh );
+ const int nbNodes = helper.Count( shape, TopAbs_VERTEX, /*ignoreSame=*/true );
+ const int nbFaces = helper.Count( shape, TopAbs_FACE, /*ignoreSame=*/false );
+
+ if ( nbNodes == 8 && nbFaces == 6 )
+ quantities[ _quadraticMesh ? SMDSEntity_Quad_Hexa : SMDSEntity_Hexa ] = 1;
+ else if ( nbNodes == 4 && nbFaces == 4 )
+ quantities[ _quadraticMesh ? SMDSEntity_Quad_Tetra : SMDSEntity_Tetra ] = 1;
+ else if ( nbNodes == 6 && nbFaces == 5 )
+ quantities[ _quadraticMesh ? SMDSEntity_Quad_Penta : SMDSEntity_Penta ] = 1;
+ else if ( nbNodes == 5 && nbFaces == 5 )
+ quantities[ _quadraticMesh ? SMDSEntity_Quad_Pyramid : SMDSEntity_Pyramid ] = 1;
+ else if ( nbNodes == 12 && nbFaces == 8 )
+ quantities[ /*_quadraticMesh ? SMDSEntity_Quad_Pyramid :*/ SMDSEntity_Hexagonal_Prism ] = 1;
+ else
+ quantities[ /*_quadraticMesh ? SMDSEntity_Quad_Polyhedra : */SMDSEntity_Polyhedra ] = 1;
+
+ return true;
+ }
+ default:;
+
+ } // switch ( shape.ShapeType() )
+ } // loop on sub-meshes
+
+ return false;
+}
--- /dev/null
+// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, 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 : StdMeshers_PolyhedronPerSolid_3D.hxx
+// Module : SMESH
+//
+#ifndef _SMESH_PolyhedronPerSolid_3D_HXX_
+#define _SMESH_PolyhedronPerSolid_3D_HXX_
+
+#include "SMESH_StdMeshers.hxx"
+#include "SMESH_Algo.hxx"
+
+class StdMeshers_Regular_1D;
+class StdMeshers_PolygonPerFace_2D;
+class StdMeshers_ViscousLayers;
+
+class STDMESHERS_EXPORT StdMeshers_PolyhedronPerSolid_3D: public SMESH_3D_Algo
+{
+ public:
+ StdMeshers_PolyhedronPerSolid_3D(int hypId, SMESH_Gen* gen);
+ ~StdMeshers_PolyhedronPerSolid_3D();
+
+ virtual bool CheckHypothesis(SMESH_Mesh& aMesh,
+ const TopoDS_Shape& aShape,
+ SMESH_Hypothesis::Hypothesis_Status& aStatus);
+
+ virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape);
+
+ virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape,
+ MapShapeNbElems& aResMap);
+
+ private:
+
+ StdMeshers_Regular_1D* myEdgeMesher;
+ StdMeshers_PolygonPerFace_2D* myFaceMesher;
+ const StdMeshers_ViscousLayers* myViscousLayersHyp;
+};
+
+#endif
an = eltSize;
eltSize *= q;
++nbParams;
+ if ( q < 1. && eltSize < 1e-100 )
+ return error("Too small common ratio causes too many segments");
}
if ( nbParams > 1 )
{
#include "StdMeshers_ViscousLayers.hxx"
+#include "ObjectPool.hxx"
#include "SMDS_EdgePosition.hxx"
#include "SMDS_FaceOfNodes.hxx"
#include "SMDS_FacePosition.hxx"
#include "SMESHDS_Hypothesis.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Algo.hxx"
+#include "SMESH_Block.hxx"
#include "SMESH_ComputeError.hxx"
#include "SMESH_ControlsDef.hxx"
#include "SMESH_Gen.hxx"
#include "SMESH_HypoFilter.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MeshAlgos.hxx"
+#include "SMESH_MeshEditor.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_ProxyMesh.hxx"
#include "SMESH_subMesh.hxx"
-#include "SMESH_MeshEditor.hxx"
#include "SMESH_subMeshEventListener.hxx"
#include "StdMeshers_FaceSide.hxx"
+#include "StdMeshers_ProjectionUtils.hxx"
#include "StdMeshers_ViscousLayers2D.hxx"
#include <Adaptor3d_HSurface.hxx>
double _h2lenRatio; // avgNormProj / (2*avgDist)
gp_Pnt2d _uv; // UV used in putOnOffsetSurface()
public:
- static _Curvature* New( double avgNormProj, double avgDist )
- {
- _Curvature* c = 0;
- if ( fabs( avgNormProj / avgDist ) > 1./200 )
- {
- c = new _Curvature;
- c->_r = avgDist * avgDist / avgNormProj;
- c->_k = avgDist * avgDist / c->_r / c->_r;
- //c->_k = avgNormProj / c->_r;
- c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive
- c->_h2lenRatio = avgNormProj / ( avgDist + avgDist );
-
- c->_uv.SetCoord( 0., 0. );
- }
- return c;
- }
+ static _Curvature* New( double avgNormProj, double avgDist );
double lenDelta(double len) const { return _k * ( _r + len ); }
double lenDeltaByDist(double dist) const { return dist * _h2lenRatio; }
};
gp_XYZ* _plnNorm;
_2NearEdges() { _edges[0]=_edges[1]=0; _plnNorm = 0; }
+ ~_2NearEdges(){ delete _plnNorm; }
const SMDS_MeshNode* tgtNode(bool is2nd) {
return _edges[is2nd] ? _edges[is2nd]->_nodes.back() : 0;
}
_thickness = Max( _thickness, hyp->GetTotalThickness() );
_stretchFactor += hyp->GetStretchFactor();
_method = hyp->GetMethod();
+ if ( _groupName.empty() )
+ _groupName = hyp->GetGroupName();
}
}
double GetTotalThickness() const { return _thickness; /*_nbHyps ? _thickness / _nbHyps : 0;*/ }
double GetStretchFactor() const { return _nbHyps ? _stretchFactor / _nbHyps : 0; }
int GetNumberLayers() const { return _nbLayers; }
int GetMethod() const { return _method; }
+ bool ToCreateGroup() const { return !_groupName.empty(); }
+ const std::string& GetGroupName() const { return _groupName; }
bool UseSurfaceNormal() const
{ return _method == StdMeshers_ViscousLayers::SURF_OFFSET_SMOOTH; }
bool IsOffsetMethod() const
{ return _method == StdMeshers_ViscousLayers::FACE_OFFSET; }
+ bool operator==( const AverageHyp& other ) const
+ {
+ return ( _nbLayers == other._nbLayers &&
+ _method == other._method &&
+ Equals( GetTotalThickness(), other.GetTotalThickness() ) &&
+ Equals( GetStretchFactor(), other.GetStretchFactor() ));
+ }
+ static bool Equals( double v1, double v2 ) { return Abs( v1 - v2 ) < 0.01 * ( v1 + v2 ); }
+
private:
- int _nbLayers, _nbHyps, _method;
- double _thickness, _stretchFactor;
+ int _nbLayers, _nbHyps, _method;
+ double _thickness, _stretchFactor;
+ std::string _groupName;
};
//--------------------------------------------------------------------------------
_SolidData& GetData() const { return *_data; }
_EdgesOnShape(): _shapeID(-1), _subMesh(0), _toSmooth(false), _edgeSmoother(0) {}
+ ~_EdgesOnShape();
};
//--------------------------------------------------------------------------------
TopTools_MapOfShape _before; // SOLIDs to be computed before _solid
TGeomID _index; // SOLID id
_MeshOfSolid* _proxyMesh;
+ bool _done;
list< THyp > _hyps;
list< TopoDS_Shape > _hypShapes;
map< TGeomID, THyp > _face2hyp; // filled if _hyps.size() > 1
// _LayerEdge's with underlying shapes
vector< _EdgesOnShape > _edgesOnShape;
- // key: an id of shape (EDGE or VERTEX) shared by a FACE with
+ // key: an ID of shape (EDGE or VERTEX) shared by a FACE with
// layers and a FACE w/o layers
// value: the shape (FACE or EDGE) to shrink mesh on.
// _LayerEdge's basing on nodes on key shape are inflated along the value shape
_SolidData(const TopoDS_Shape& s=TopoDS_Shape(),
_MeshOfSolid* m=0)
- :_solid(s), _proxyMesh(m), _helper(0) {}
- ~_SolidData();
+ :_solid(s), _proxyMesh(m), _done(false),_helper(0) {}
+ ~_SolidData() { delete _helper; _helper = 0; }
void SortOnEdge( const TopoDS_Edge& E, vector< _LayerEdge* >& edges);
void Sort2NeiborsOnEdge( vector< _LayerEdge* >& edges );
const double refSign );
};
struct PyDump;
+ struct Periodicity;
//--------------------------------------------------------------------------------
/*!
* \brief Builder of viscous layers
bool findSolidsWithLayers();
bool setBefore( _SolidData& solidBefore, _SolidData& solidAfter );
bool findFacesWithLayers(const bool onlyWith=false);
+ void findPeriodicFaces();
void getIgnoreFaces(const TopoDS_Shape& solid,
const StdMeshers_ViscousLayers* hyp,
const TopoDS_Shape& hypShape,
set<TGeomID>& ignoreFaces);
+ void makeEdgesOnShape();
bool makeLayer(_SolidData& data);
void setShapeData( _EdgesOnShape& eos, SMESH_subMesh* sm, _SolidData& data );
bool setEdgeData( _LayerEdge& edge, _EdgesOnShape& eos,
// debug
void makeGroupOfLE();
- SMESH_Mesh* _mesh;
- SMESH_ComputeErrorPtr _error;
+ SMESH_Mesh* _mesh;
+ SMESH_ComputeErrorPtr _error;
- vector< _SolidData > _sdVec;
- TopTools_IndexedMapOfShape _solids; // to find _SolidData by a solid
- TopTools_MapOfShape _shrinkedFaces;
+ vector< _SolidData > _sdVec;
+ TopTools_IndexedMapOfShape _solids; // to find _SolidData by a solid
+ TopTools_MapOfShape _shrunkFaces;
+ std::unique_ptr<Periodicity> _periodicity;
- int _tmpFaceID;
- PyDump* _pyDump;
+ int _tmpFaceID;
+ PyDump* _pyDump;
};
//--------------------------------------------------------------------------------
/*!
( dot * dot ) / l1 / l2 >= ( cos * cos ));
}
+ class _Factory
+ {
+ ObjectPool< _LayerEdge > _edgePool;
+ ObjectPool< _Curvature > _curvaturePool;
+ ObjectPool< _2NearEdges > _nearEdgesPool;
+
+ static _Factory* & me()
+ {
+ static _Factory* theFactory = 0;
+ return theFactory;
+ }
+ public:
+
+ _Factory() { me() = this; }
+ ~_Factory() { me() = 0; }
+
+ static _LayerEdge* NewLayerEdge() { return me()->_edgePool.getNew(); }
+ static _Curvature * NewCurvature() { return me()->_curvaturePool.getNew(); }
+ static _2NearEdges* NewNearEdges() { return me()->_nearEdgesPool.getNew(); }
+ };
+
} // namespace VISCOUS_3D
StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, SMESH_Gen* gen)
:SMESH_Hypothesis(hypId, gen),
_isToIgnoreShapes(1), _nbLayers(1), _thickness(1), _stretchFactor(1),
- _method( SURF_OFFSET_SMOOTH )
+ _method( SURF_OFFSET_SMOOTH ),
+ _groupName("")
{
_name = StdMeshers_ViscousLayers::GetHypType();
_param_algo_dim = -3; // auxiliary hyp used by 3D algos
if ( _method != method )
_method = method, NotifySubMeshesHypothesisModification();
} // --------------------------------------------------------------------------------
+void StdMeshers_ViscousLayers::SetGroupName(const std::string& name)
+{
+ if ( _groupName != name )
+ {
+ _groupName = name;
+ if ( !_groupName.empty() )
+ NotifySubMeshesHypothesisModification();
+ }
+} // --------------------------------------------------------------------------------
SMESH_ProxyMesh::Ptr
StdMeshers_ViscousLayers::Compute(SMESH_Mesh& theMesh,
const TopoDS_Shape& theShape,
save << " " << _shapeIds[i];
save << " " << !_isToIgnoreShapes; // negate to keep the behavior in old studies.
save << " " << _method;
+ save << " " << _groupName.size();
+ if ( !_groupName.empty() )
+ save << " " << _groupName;
return save;
} // --------------------------------------------------------------------------------
std::istream & StdMeshers_ViscousLayers::LoadFrom(std::istream & load)
_isToIgnoreShapes = !shapeToTreat;
if ( load >> method )
_method = (ExtrusionMethod) method;
+ int nameSize = 0;
+ if ( load >> nameSize && nameSize > 0 )
+ {
+ _groupName.resize( nameSize );
+ load.get( _groupName[0] ); // remove a white-space
+ load.getline( &_groupName[0], nameSize + 1 );
+ }
}
else {
_isToIgnoreShapes = true; // old behavior
( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
return IsToIgnoreShapes() ? !isIn : isIn;
}
+
+// --------------------------------------------------------------------------------
+SMDS_MeshGroup* StdMeshers_ViscousLayers::CreateGroup( const std::string& theName,
+ SMESH_Mesh& theMesh,
+ SMDSAbs_ElementType theType)
+{
+ SMESH_Group* group = 0;
+ SMDS_MeshGroup* groupDS = 0;
+
+ if ( theName.empty() )
+ return groupDS;
+
+ if ( SMESH_Mesh::GroupIteratorPtr grIt = theMesh.GetGroups() )
+ while( grIt->more() && !group )
+ {
+ group = grIt->next();
+ if ( !group ||
+ group->GetGroupDS()->GetType() != theType ||
+ group->GetName() != theName ||
+ !dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() ))
+ group = 0;
+ }
+ if ( !group )
+ group = theMesh.AddGroup( theType, theName.c_str() );
+
+ groupDS = & dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() )->SMDSGroup();
+
+ return groupDS;
+}
+
// END StdMeshers_ViscousLayers hypothesis
//================================================================================
{
_mesh = & theMesh;
+ _Factory factory;
+
// check if proxy mesh already computed
TopExp_Explorer exp( theShape, TopAbs_SOLID );
if ( !exp.More() )
PyDump debugDump( theMesh );
_pyDump = &debugDump;
- // TODO: ignore already computed SOLIDs
+ // TODO: ignore already computed SOLIDs
if ( !findSolidsWithLayers())
return _error;
if ( !findFacesWithLayers() )
return _error;
+ // for ( size_t i = 0; i < _sdVec.size(); ++i )
+ // {
+ // if ( ! makeLayer( _sdVec[ i ])) // create _LayerEdge's
+ // return _error;
+ // }
+
+ makeEdgesOnShape();
+
+ findPeriodicFaces();
+
for ( size_t i = 0; i < _sdVec.size(); ++i )
{
size_t iSD = 0;
for ( iSD = 0; iSD < _sdVec.size(); ++iSD ) // find next SOLID to compute
if ( _sdVec[iSD]._before.IsEmpty() &&
!_sdVec[iSD]._solid.IsNull() &&
- _sdVec[iSD]._n2eMap.empty() )
+ !_sdVec[iSD]._done )
break;
if ( ! makeLayer(_sdVec[iSD]) ) // create _LayerEdge's
addBoundaryElements(_sdVec[iSD]); // create quadrangles on prism bare sides
+ _sdVec[iSD]._done = true;
+
const TopoDS_Shape& solid = _sdVec[iSD]._solid;
for ( iSD = 0; iSD < _sdVec.size(); ++iSD )
_sdVec[iSD]._before.Remove( solid );
for ( ; exp.More(); exp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( exp.Current() );
- const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
+ const TGeomID faceID = getMeshDS()->ShapeToIndex( face );
if ( //!sdVec[i]._ignoreFaceIds.count( faceID ) &&
helper.NbAncestors( face, *_mesh, TopAbs_SOLID ) > 1 &&
helper.IsReversedSubMesh( face ))
ignore[j] = _sdVec[i]._ignoreFaceIds.count( getMeshDS()->ShapeToIndex( FF[j] ));
if ( ignore[0] == ignore[1] )
continue; // nothing interesting
- TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ];
+ TopoDS_Shape fWOL = FF[ ignore[0] ? 0 : 1 ]; // FACE w/o layers
// add EDGE to maps
if ( !fWOL.IsNull())
}
}
- // Add to _noShrinkShapes sub-shapes of FACE's that can't be shrinked since
+ // Add to _noShrinkShapes sub-shapes of FACE's that can't be shrunk since
// the algo of the SOLID sharing the FACE does not support it or for other reasons
set< string > notSupportAlgos; notSupportAlgos.insert( structAlgoName );
for ( size_t i = 0; i < _sdVec.size(); ++i )
bool _ViscousBuilder::makeLayer(_SolidData& data)
{
- // get all sub-shapes to make layers on
- set<TGeomID> subIds, faceIds;
- 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() ))
- faceIds.insert( fSubM->GetId() );
- }
-
// make a map to find new nodes on sub-shapes shared with other SOLID
map< TGeomID, TNode2Edge* >::iterator s2ne;
map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
dumpFunction(SMESH_Comment("makeLayers_")<<data._index);
+ vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
+
data._stepSize = Precision::Infinite();
data._stepSizeNodes[0] = 0;
vector< const SMDS_MeshNode*> newNodes; // of a mesh face
TNode2Edge::iterator n2e2;
- // collect _LayerEdge's of shapes they are based on
- vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
- const int nbShapes = getMeshDS()->MaxShapeIndex();
- edgesByGeom.resize( nbShapes+1 );
-
- // set data of _EdgesOnShape's
- if ( SMESH_subMesh* sm = _mesh->GetSubMesh( data._solid ))
- {
- SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
- while ( smIt->more() )
- {
- sm = smIt->next();
- if ( sm->GetSubShape().ShapeType() == TopAbs_FACE &&
- !faceIds.count( sm->GetId() ))
- continue;
- setShapeData( edgesByGeom[ sm->GetId() ], sm, data );
- }
- }
// make _LayerEdge's
- for ( set<TGeomID>::iterator id = faceIds.begin(); id != faceIds.end(); ++id )
+ for ( TopExp_Explorer exp( data._solid, TopAbs_FACE ); exp.More(); exp.Next() )
{
- const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( *id ));
- SMESH_subMesh* sm = _mesh->GetSubMesh( F );
+ const TopoDS_Face& F = TopoDS::Face( exp.Current() );
+ SMESH_subMesh* sm = _mesh->GetSubMesh( F );
+ const TGeomID id = sm->GetId();
+ if ( edgesByGeom[ id ]._shape.IsNull() )
+ continue; // no layers
SMESH_ProxyMesh::SubMesh* proxySub =
data._proxyMesh->getFaceSubM( F, /*create=*/true);
SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
- if ( !smDS ) return error(SMESH_Comment("Not meshed face ") << *id, data._index );
+ if ( !smDS ) return error(SMESH_Comment("Not meshed face ") << id, data._index );
SMDS_ElemIteratorPtr eIt = smDS->GetElements();
while ( eIt->more() )
if ( !(*n2e).second )
{
// add a _LayerEdge
- _LayerEdge* edge = new _LayerEdge();
+ _LayerEdge* edge = _Factory::NewLayerEdge();
edge->_nodes.push_back( n );
n2e->second = edge;
edgesByGeom[ shapeID ]._edges.push_back( edge );
return ok;
}
+//================================================================================
+/*!
+ * \brief Set up _SolidData::_edgesOnShape
+ */
+//================================================================================
+
+void _ViscousBuilder::makeEdgesOnShape()
+{
+ const int nbShapes = getMeshDS()->MaxShapeIndex();
+
+ for ( size_t i = 0; i < _sdVec.size(); ++i )
+ {
+ _SolidData& data = _sdVec[ i ];
+ vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
+ edgesByGeom.resize( nbShapes+1 );
+
+ // set data of _EdgesOnShape's
+ if ( SMESH_subMesh* sm = _mesh->GetSubMesh( data._solid ))
+ {
+ SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/false);
+ while ( smIt->more() )
+ {
+ sm = smIt->next();
+ if ( sm->GetSubShape().ShapeType() == TopAbs_FACE &&
+ data._ignoreFaceIds.count( sm->GetId() ))
+ continue;
+
+ setShapeData( edgesByGeom[ sm->GetId() ], sm, data );
+ }
+ }
+ }
+}
+
//================================================================================
/*!
* \brief initialize data of _EdgesOnShape
return ok;
}
+//================================================================================
+/*!
+ * \brief EdgesOnShape destructor
+ */
+//================================================================================
+
+_EdgesOnShape::~_EdgesOnShape()
+{
+ delete _edgeSmoother;
+}
//================================================================================
/*!
{
const SMDS_MeshNode* node = edge._nodes[0]; // source node
- edge._len = 0;
- edge._maxLen = Precision::Infinite();
- edge._minAngle = 0;
- edge._2neibors = 0;
- edge._curvature = 0;
- edge._flags = 0;
+ edge._len = 0;
+ edge._maxLen = Precision::Infinite();
+ edge._minAngle = 0;
+ edge._2neibors = 0;
+ edge._curvature = 0;
+ edge._flags = 0;
+ edge._smooFunction = 0;
// --------------------------
// Compute _normal and _cosin
if ( eos.ShapeType() == TopAbs_EDGE /*||
( onShrinkShape && posType == SMDS_TOP_VERTEX && fabs( edge._cosin ) < 1e-10 )*/)
{
- edge._2neibors = new _2NearEdges;
+ edge._2neibors = _Factory::NewNearEdges();
// target nodes instead of source ones will be set later
}
return true;
}
+//================================================================================
+/*!
+ * \brief Create _Curvature
+ */
+//================================================================================
+
+_Curvature* _Curvature::New( double avgNormProj, double avgDist )
+{
+ // double _r; // radius
+ // double _k; // factor to correct node smoothed position
+ // double _h2lenRatio; // avgNormProj / (2*avgDist)
+ // gp_Pnt2d _uv; // UV used in putOnOffsetSurface()
+
+ _Curvature* c = 0;
+ if ( fabs( avgNormProj / avgDist ) > 1./200 )
+ {
+ c = _Factory::NewCurvature();
+ c->_r = avgDist * avgDist / avgNormProj;
+ c->_k = avgDist * avgDist / c->_r / c->_r;
+ //c->_k = avgNormProj / c->_r;
+ c->_k *= ( c->_r < 0 ? 1/1.1 : 1.1 ); // not to be too restrictive
+ c->_h2lenRatio = avgNormProj / ( avgDist + avgDist );
+
+ c->_uv.SetCoord( 0., 0. );
+ }
+ return c;
+}
+
//================================================================================
/*!
* \brief Set _curvature and _2neibors->_plnNorm by 2 neighbor nodes residing the same EDGE
_2neibors->_wgt[1] = 1 - vec2.Modulus() / sumLen;
double avgNormProj = 0.5 * ( _normal * vec1 + _normal * vec2 );
double avgLen = 0.5 * ( vec1.Modulus() + vec2.Modulus() );
- if ( _curvature ) delete _curvature;
_curvature = _Curvature::New( avgNormProj, avgLen );
// if ( _curvature )
// debugMsg( _nodes[0]->GetID()
_lenFactor = other._lenFactor;
_cosin = other._cosin;
_2neibors = other._2neibors;
- _curvature = 0; std::swap( _curvature, other._curvature );
- _2neibors = 0; std::swap( _2neibors, other._2neibors );
+ _curvature = other._curvature;
+ _2neibors = other._2neibors;
+ _maxLen = Precision::Infinite();//other._maxLen;
+ _flags = 0;
+ _smooFunction = 0;
gp_XYZ lastPos( 0,0,0 );
if ( eos.SWOLType() == TopAbs_EDGE )
if ( dist < 0.95 * ledge->_maxLen )
{
ledge->Set( _LayerEdge::UPD_NORMAL_CONV );
- if ( !ledge->_curvature ) ledge->_curvature = new _Curvature;
+ if ( !ledge->_curvature ) ledge->_curvature = _Factory::NewCurvature();
ledge->_curvature->_uv.SetCoord( uv.X(), uv.Y() );
edgesToUpdateFound = true;
}
if ( !edgeF->_curvature )
if (( fPos = edgeF->_nodes[0]->GetPosition() ))
{
- edgeF->_curvature = new _Curvature;
+ edgeF->_curvature = _Factory::NewCurvature();
edgeF->_curvature->_r = 0;
edgeF->_curvature->_k = 0;
edgeF->_curvature->_h2lenRatio = 0;
const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
if ( data._ignoreFaceIds.count( faceID ))
continue;
+ _EdgesOnShape* eos = data.GetShapeEdges( faceID );
+ SMDS_MeshGroup* group = StdMeshers_ViscousLayers::CreateGroup( eos->_hyp.GetGroupName(),
+ *helper.GetMesh(),
+ SMDSAbs_Volume );
+ std::vector< const SMDS_MeshElement* > vols;
const bool isReversedFace = data._reversedFaceIds.count( faceID );
SMESHDS_SubMesh* fSubM = getMeshDS()->MeshElements( exp.Current() );
SMDS_ElemIteratorPtr fIt = fSubM->GetElements();
if ( 0 < nnSet.size() && nnSet.size() < 3 )
continue;
+ vols.clear();
+ const SMDS_MeshElement* vol;
+
switch ( nbNodes )
{
case 3: // TRIA
{
// PENTA
for ( size_t iZ = 1; iZ < minZ; ++iZ )
- helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
- (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]);
+ {
+ vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
+ (*nnVec[0])[iZ], (*nnVec[1])[iZ], (*nnVec[2])[iZ]);
+ vols.push_back( vol );
+ }
for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
{
int i2 = *degenEdgeInd.begin();
int i0 = helper.WrapIndex( i2 - 1, nbNodes );
int i1 = helper.WrapIndex( i2 + 1, nbNodes );
- helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
- (*nnVec[i1])[iZ ], (*nnVec[i0])[iZ ], (*nnVec[i2]).back());
+ vol = helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
+ (*nnVec[i1])[iZ ], (*nnVec[i0])[iZ ], (*nnVec[i2]).back());
+ vols.push_back( vol );
}
else // TETRA
{
int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2;
- helper.AddVolume( (*nnVec[ 0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
- (*nnVec[ 1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
- (*nnVec[ 2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
- (*nnVec[ i3 ])[ iZ ]);
+ vol = helper.AddVolume( (*nnVec[ 0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
+ (*nnVec[ 1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
+ (*nnVec[ 2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
+ (*nnVec[ i3 ])[ iZ ]);
+ vols.push_back( vol );
}
}
break; // TRIA
{
// HEX
for ( size_t iZ = 1; iZ < minZ; ++iZ )
- helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
- (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
- (*nnVec[0])[iZ], (*nnVec[1])[iZ],
- (*nnVec[2])[iZ], (*nnVec[3])[iZ]);
+ {
+ vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
+ (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
+ (*nnVec[0])[iZ], (*nnVec[1])[iZ],
+ (*nnVec[2])[iZ], (*nnVec[3])[iZ]);
+ vols.push_back( vol );
+ }
for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
{
int i0 = helper.WrapIndex( i3 + 1, nbNodes );
int i1 = helper.WrapIndex( i0 + 1, nbNodes );
- const SMDS_MeshElement* vol =
- helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
- nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+ vol = helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
+ nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+ vols.push_back( vol );
if ( !ok && vol )
degenVols.push_back( vol );
}
default: // degen HEX
{
- const SMDS_MeshElement* vol =
- helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
- nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
- nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
- nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
- nnVec[0]->size() > iZ ? (*nnVec[0])[iZ] : nnVec[0]->back(),
- nnVec[1]->size() > iZ ? (*nnVec[1])[iZ] : nnVec[1]->back(),
- nnVec[2]->size() > iZ ? (*nnVec[2])[iZ] : nnVec[2]->back(),
- nnVec[3]->size() > iZ ? (*nnVec[3])[iZ] : nnVec[3]->back());
+ vol = helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
+ nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
+ nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
+ nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
+ nnVec[0]->size() > iZ ? (*nnVec[0])[iZ] : nnVec[0]->back(),
+ nnVec[1]->size() > iZ ? (*nnVec[1])[iZ] : nnVec[1]->back(),
+ nnVec[2]->size() > iZ ? (*nnVec[2])[iZ] : nnVec[2]->back(),
+ nnVec[3]->size() > iZ ? (*nnVec[3])[iZ] : nnVec[3]->back());
+ vols.push_back( vol );
degenVols.push_back( vol );
}
}
return error("Not supported type of element", data._index);
} // switch ( nbNodes )
+
+ if ( group )
+ for ( size_t i = 0; i < vols.size(); ++i )
+ group->Add( vols[ i ]);
+
} // while ( fIt->more() )
} // loop on FACEs
return true;
}
+namespace VISCOUS_3D
+{
+ struct ShrinkFace;
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Pair of periodic FACEs
+ */
+ struct PeriodicFaces
+ {
+ typedef StdMeshers_ProjectionUtils::TrsfFinder3D Trsf;
+
+ ShrinkFace* _shriFace[2];
+ TNodeNodeMap _nnMap;
+ Trsf _trsf;
+
+ PeriodicFaces( ShrinkFace* sf1, ShrinkFace* sf2 ): _shriFace{ sf1, sf2 } {}
+ bool IncludeShrunk( const TopoDS_Face& face, const TopTools_MapOfShape& shrunkFaces ) const;
+ bool MoveNodes( const TopoDS_Face& tgtFace );
+ };
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Shrink FACE data used to find periodic FACEs
+ */
+ struct ShrinkFace
+ {
+ // ................................................................................
+ struct BndPart //!< part of FACE boundary, either shrink or no-shrink
+ {
+ bool _isShrink, _isReverse;
+ int _nbSegments;
+ AverageHyp* _hyp;
+ std::vector< SMESH_NodeXYZ > _nodes;
+ TopAbs_ShapeEnum _vertSWOLType[2]; // shrink part includes VERTEXes
+ AverageHyp* _vertHyp[2];
+
+ BndPart():
+ _isShrink(0), _isReverse(0), _nbSegments(0), _hyp(0),
+ _vertSWOLType{ TopAbs_WIRE, TopAbs_WIRE }, _vertHyp{ 0, 0 }
+ {}
+
+ bool operator==( const BndPart& other ) const
+ {
+ return ( _isShrink == other._isShrink &&
+ _nbSegments == other._nbSegments &&
+ _nodes.size() == other._nodes.size() &&
+ vertSWOLType1() == other.vertSWOLType1() &&
+ vertSWOLType2() == other.vertSWOLType2() &&
+ (( !_isShrink ) ||
+ ( *_hyp == *other._hyp &&
+ vertHyp1() == other.vertHyp1() &&
+ vertHyp2() == other.vertHyp2() ))
+ );
+ }
+ bool CanAppend( const BndPart& other )
+ {
+ return ( _isShrink == other._isShrink &&
+ (( !_isShrink ) ||
+ ( *_hyp == *other._hyp &&
+ *_hyp == vertHyp2() &&
+ vertHyp2() == other.vertHyp1() ))
+ );
+ }
+ void Append( const BndPart& other )
+ {
+ _nbSegments += other._nbSegments;
+ bool hasCommonNode = ( _nodes.back()->GetID() == other._nodes.front()->GetID() );
+ _nodes.insert( _nodes.end(), other._nodes.begin() + hasCommonNode, other._nodes.end() );
+ _vertSWOLType[1] = other._vertSWOLType[1];
+ if ( _isShrink )
+ _vertHyp[1] = other._vertHyp[1];
+ }
+ const SMDS_MeshNode* Node(size_t i) const
+ {
+ return _nodes[ _isReverse ? ( _nodes.size() - 1 - i ) : i ]._node;
+ }
+ void Reverse() { _isReverse = !_isReverse; }
+ const TopAbs_ShapeEnum& vertSWOLType1() const { return _vertSWOLType[ _isReverse ]; }
+ const TopAbs_ShapeEnum& vertSWOLType2() const { return _vertSWOLType[ !_isReverse ]; }
+ const AverageHyp& vertHyp1() const { return *(_vertHyp[ _isReverse ]); }
+ const AverageHyp& vertHyp2() const { return *(_vertHyp[ !_isReverse ]); }
+ };
+ // ................................................................................
+
+ SMESH_subMesh* _subMesh;
+ _SolidData* _data1;
+ _SolidData* _data2;
+ //bool _isPeriodic;
+
+ std::list< BndPart > _boundary;
+ int _boundarySize, _nbBoundaryParts;
+
+ void Init( SMESH_subMesh* sm, _SolidData* sd1, _SolidData* sd2 )
+ {
+ _subMesh = sm; _data1 = sd1; _data2 = sd2; //_isPeriodic = false;
+ }
+ bool IsSame( const TopoDS_Face& face ) const
+ {
+ return _subMesh->GetSubShape().IsSame( face );
+ }
+ bool IsShrunk( const TopTools_MapOfShape& shrunkFaces ) const
+ {
+ return shrunkFaces.Contains( _subMesh->GetSubShape() );
+ }
+
+ //================================================================================
+ /*!
+ * Check if meshes on two FACEs are equal
+ */
+ bool IsPeriodic( ShrinkFace& other, PeriodicFaces& periodic )
+ {
+ if ( !IsSameNbElements( other ))
+ return false;
+
+ this->SetBoundary();
+ other.SetBoundary();
+ if ( this->_boundarySize != other._boundarySize ||
+ this->_nbBoundaryParts != other._nbBoundaryParts )
+ return false;
+
+ for ( int isReverse = 0; isReverse < 2; ++isReverse )
+ {
+ if ( isReverse )
+ Reverse( _boundary );
+
+ // check boundaries
+ bool equalBoundary = false;
+ for ( int iP = 0; iP < _nbBoundaryParts && !equalBoundary; ++iP )
+ {
+ if ( ! ( equalBoundary = ( this->_boundary == other._boundary )))
+ // set first part at end
+ _boundary.splice( _boundary.end(), _boundary, _boundary.begin() );
+ }
+ if ( !equalBoundary )
+ continue;
+
+ // check connectivity
+ std::set<const SMDS_MeshElement*> elemsThis, elemsOther;
+ this->GetElements( elemsThis );
+ other.GetElements( elemsOther );
+ SMESH_MeshEditor::Sew_Error err =
+ SMESH_MeshEditor::FindMatchingNodes( elemsThis, elemsOther,
+ this->_boundary.front().Node(0),
+ other._boundary.front().Node(0),
+ this->_boundary.front().Node(1),
+ other._boundary.front().Node(1),
+ periodic._nnMap );
+ if ( err != SMESH_MeshEditor::SEW_OK )
+ continue;
+
+ // check node positions
+ std::vector< gp_XYZ > srcPnts, tgtPnts;
+ this->GetBoundaryPoints( srcPnts );
+ other.GetBoundaryPoints( tgtPnts );
+ if ( !periodic._trsf.Solve( srcPnts, tgtPnts )) {
+ continue;
+ }
+ double tol = std::numeric_limits<double>::max();
+ for ( size_t i = 1; i < srcPnts.size(); ++i ) {
+ tol = Min( tol, ( srcPnts[i-1] - srcPnts[i] ).SquareModulus() );
+ }
+ tol = 0.01 * Sqrt( tol );
+ bool nodeCoincide = true;
+ TNodeNodeMap::iterator n2n = periodic._nnMap.begin();
+ for ( ; n2n != periodic._nnMap.end() && nodeCoincide; ++n2n )
+ {
+ SMESH_NodeXYZ nSrc = n2n->first;
+ SMESH_NodeXYZ nTgt = n2n->second;
+ gp_XYZ pTgt = periodic._trsf.Transform( nSrc );
+ nodeCoincide = (( pTgt - nTgt ).SquareModulus() < tol );
+ }
+ if ( nodeCoincide )
+ return true;
+ }
+ return false;
+ }
+
+ bool IsSameNbElements( ShrinkFace& other ) // check number of mesh faces
+ {
+ SMESHDS_SubMesh* sm1 = this->_subMesh->GetSubMeshDS();
+ SMESHDS_SubMesh* sm2 = other._subMesh->GetSubMeshDS();
+ return ( sm1->NbElements() == sm2->NbElements() &&
+ sm1->NbNodes() == sm2->NbNodes() );
+ }
+
+ void Reverse( std::list< BndPart >& boundary )
+ {
+ boundary.reverse();
+ for ( std::list< BndPart >::iterator part = boundary.begin(); part != boundary.end(); ++part )
+ part->Reverse();
+ }
+
+ void SetBoundary()
+ {
+ if ( !_boundary.empty() )
+ return;
+
+ TopoDS_Face F = TopoDS::Face( _subMesh->GetSubShape() );
+ if ( F.Orientation() >= TopAbs_INTERNAL ) F.Orientation( TopAbs_FORWARD );
+ std::list< TopoDS_Edge > edges;
+ std::list< int > nbEdgesInWire;
+ /*int nbWires =*/ SMESH_Block::GetOrderedEdges (F, edges, nbEdgesInWire);
+
+ // std::list< TopoDS_Edge >::iterator edgesEnd = edges.end();
+ // if ( nbWires > 1 ) {
+ // edgesEnd = edges.begin();
+ // std::advance( edgesEnd, nbEdgesInWire.front() );
+ // }
+ StdMeshers_FaceSide fSide( F, edges, _subMesh->GetFather(),
+ /*fwd=*/true, /*skipMedium=*/true );
+ _boundarySize = fSide.NbSegments();
+
+ //TopoDS_Vertex vv[2];
+ //std::list< TopoDS_Edge >::iterator edgeIt = edges.begin();
+ for ( int iE = 0; iE < nbEdgesInWire.front(); ++iE )
+ {
+ BndPart bndPart;
+ _EdgesOnShape* eos = _data1->GetShapeEdges( fSide.EdgeID( iE ));
+
+ bndPart._isShrink = ( eos->SWOLType() == TopAbs_FACE );
+ if ( bndPart._isShrink )
+ if (( _data1->_noShrinkShapes.count( eos->_shapeID )) ||
+ ( _data2 && _data2->_noShrinkShapes.count( eos->_shapeID )))
+ bndPart._isShrink = false;
+
+ if ( bndPart._isShrink )
+ {
+ bndPart._hyp = & eos->_hyp;
+ _EdgesOnShape* eov[2] = { _data1->GetShapeEdges( fSide.FirstVertex( iE )),
+ _data1->GetShapeEdges( fSide.LastVertex ( iE )) };
+ for ( int iV = 0; iV < 2; ++iV )
+ {
+ bndPart._vertHyp [iV] = & eov[iV]->_hyp;
+ bndPart._vertSWOLType[iV] = eov[iV]->SWOLType();
+ if ( _data1->_noShrinkShapes.count( eov[iV]->_shapeID ))
+ bndPart._vertSWOLType[iV] = TopAbs_SHAPE;
+ if ( _data2 && bndPart._vertSWOLType[iV] != TopAbs_SHAPE )
+ {
+ eov[iV] = _data2->GetShapeEdges( iV ? fSide.LastVertex(iE) : fSide.FirstVertex(iE ));
+ if ( _data2->_noShrinkShapes.count( eov[iV]->_shapeID ))
+ bndPart._vertSWOLType[iV] = TopAbs_SHAPE;
+ else if ( eov[iV]->SWOLType() > bndPart._vertSWOLType[iV] )
+ bndPart._vertSWOLType[iV] = eov[iV]->SWOLType();
+ }
+ }
+ }
+ std::vector<const SMDS_MeshNode*> nodes = fSide.GetOrderedNodes( iE );
+ bndPart._nodes.assign( nodes.begin(), nodes.end() );
+ bndPart._nbSegments = bndPart._nodes.size() - 1;
+
+ if ( _boundary.empty() || ! _boundary.back().CanAppend( bndPart ))
+ _boundary.push_back( bndPart );
+ else
+ _boundary.back().Append( bndPart );
+ }
+
+ _nbBoundaryParts = _boundary.size();
+ if ( _nbBoundaryParts > 1 && _boundary.front()._isShrink == _boundary.back()._isShrink )
+ {
+ _boundary.back().Append( _boundary.front() );
+ _boundary.pop_front();
+ --_nbBoundaryParts;
+ }
+ }
+
+ void GetElements( std::set<const SMDS_MeshElement*>& theElems)
+ {
+ if ( SMESHDS_SubMesh* sm = _subMesh->GetSubMeshDS() )
+ for ( SMDS_ElemIteratorPtr fIt = sm->GetElements(); fIt->more(); )
+ theElems.insert( theElems.end(), fIt->next() );
+
+ return ;
+ }
+
+ void GetBoundaryPoints( std::vector< gp_XYZ >& points )
+ {
+ points.reserve( _boundarySize );
+ size_t nb = _boundary.rbegin()->_nodes.size();
+ int lastID = _boundary.rbegin()->Node( nb - 1 )->GetID();
+ std::list< BndPart >::const_iterator part = _boundary.begin();
+ for ( ; part != _boundary.end(); ++part )
+ {
+ size_t nb = part->_nodes.size();
+ size_t iF = 0;
+ size_t iR = nb - 1;
+ size_t* i = part->_isReverse ? &iR : &iF;
+ if ( part->_nodes[ *i ]->GetID() == lastID )
+ ++iF, --iR;
+ for ( ; iF < nb; ++iF, --iR )
+ points.push_back( part->_nodes[ *i ]);
+ --iF, ++iR;
+ lastID = part->_nodes[ *i ]->GetID();
+ }
+ }
+ }; // struct ShrinkFace
+
+ //--------------------------------------------------------------------------------
+ /*!
+ * \brief Periodic FACEs
+ */
+ struct Periodicity
+ {
+ std::vector< ShrinkFace > _shrinkFaces;
+ std::vector< PeriodicFaces > _periodicFaces;
+
+ PeriodicFaces* GetPeriodic( const TopoDS_Face& face, const TopTools_MapOfShape& shrunkFaces )
+ {
+ for ( size_t i = 0; i < _periodicFaces.size(); ++i )
+ if ( _periodicFaces[ i ].IncludeShrunk( face, shrunkFaces ))
+ return & _periodicFaces[ i ];
+ return 0;
+ }
+ };
+
+ //================================================================================
+ /*!
+ * Check if a pair includes the given FACE and the other FACE is already shrunk
+ */
+ bool PeriodicFaces::IncludeShrunk( const TopoDS_Face& face,
+ const TopTools_MapOfShape& shrunkFaces ) const
+ {
+ return (( _shriFace[0]->IsSame( face ) && _shriFace[1]->IsShrunk( shrunkFaces )) ||
+ ( _shriFace[1]->IsSame( face ) && _shriFace[0]->IsShrunk( shrunkFaces )));
+ }
+
+ //================================================================================
+ /*!
+ * Make equal meshes on periodic faces by moving corresponding nodes
+ */
+ bool PeriodicFaces::MoveNodes( const TopoDS_Face& tgtFace )
+ {
+ int iTgt = _shriFace[1]->IsSame( tgtFace );
+ int iSrc = 1 - iTgt;
+
+ _SolidData* dataSrc = _shriFace[iSrc]->_data1;
+ _SolidData* dataTgt = _shriFace[iTgt]->_data1;
+
+ Trsf * trsf = & _trsf, trsfInverse;
+ if ( iSrc != 0 )
+ {
+ trsfInverse = _trsf;
+ trsfInverse.Invert();
+ trsf = &trsfInverse;
+ }
+ SMESHDS_Mesh* meshDS = dataSrc->GetHelper().GetMeshDS();
+
+ TNode2Edge::iterator n2e;
+ TNodeNodeMap::iterator n2n = _nnMap.begin();
+ for ( ; n2n != _nnMap.end(); ++n2n )
+ {
+ const SMDS_MeshNode* const* nn = & n2n->first;
+ const SMDS_MeshNode* nSrc = nn[ iSrc ];
+ const SMDS_MeshNode* nTgt = nn[ iTgt ];
+
+ if (( nSrc->GetPosition()->GetDim() == 2 ) ||
+ (( n2e = dataSrc->_n2eMap.find( nSrc )) == dataSrc->_n2eMap.end() ))
+ {
+ SMESH_NodeXYZ pSrc = nSrc;
+ gp_XYZ pTgt = trsf->Transform( pSrc );
+ meshDS->MoveNode( nTgt, pTgt.X(), pTgt.Y(), pTgt.Z() );
+ }
+ else
+ {
+ _LayerEdge* leSrc = n2e->second;
+ n2e = dataTgt->_n2eMap.find( nTgt );
+ if ( n2e == dataTgt->_n2eMap.end() )
+ break;
+ _LayerEdge* leTgt = n2e->second;
+ if ( leSrc->_nodes.size() != leTgt->_nodes.size() )
+ break;
+ for ( size_t iN = 1; iN < leSrc->_nodes.size(); ++iN )
+ {
+ SMESH_NodeXYZ pSrc = leSrc->_nodes[ iN ];
+ gp_XYZ pTgt = trsf->Transform( pSrc );
+ meshDS->MoveNode( leTgt->_nodes[ iN ], pTgt.X(), pTgt.Y(), pTgt.Z() );
+ }
+ }
+ }
+ bool done = ( n2n == _nnMap.end() );
+ // cout << "MMMMMMMOOOOOOOOOOVVVVVVVVVVVEEEEEEEE "
+ // << _shriFace[iSrc]->_subMesh->GetId() << " -> "
+ // << _shriFace[iTgt]->_subMesh->GetId() << " -- "
+ // << ( done ? "DONE" : "FAIL") << endl;
+
+ return done;
+ }
+} // namespace VISCOUS_3D; Periodicity part
+
+
+//================================================================================
+/*!
+ * \brief Find FACEs to shrink, that are equally meshed before shrink (i.e. periodic)
+ * and should remain equal after shrink
+ */
+//================================================================================
+
+void _ViscousBuilder::findPeriodicFaces()
+{
+ // make map of (ids of FACEs to shrink mesh on) to (list of _SolidData containing
+ // _LayerEdge's inflated along FACE or EDGE)
+ std::map< TGeomID, std::list< _SolidData* > > id2sdMap;
+ for ( size_t i = 0 ; i < _sdVec.size(); ++i )
+ {
+ _SolidData& data = _sdVec[i];
+ std::map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
+ for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
+ if ( s2s->second.ShapeType() == TopAbs_FACE )
+ id2sdMap[ getMeshDS()->ShapeToIndex( s2s->second )].push_back( &data );
+ }
+
+ _periodicity.reset( new Periodicity );
+ _periodicity->_shrinkFaces.resize( id2sdMap.size() );
+
+ std::map< TGeomID, std::list< _SolidData* > >::iterator id2sdIt = id2sdMap.begin();
+ for ( size_t i = 0; i < id2sdMap.size(); ++i, ++id2sdIt )
+ {
+ _SolidData* sd1 = id2sdIt->second.front();
+ _SolidData* sd2 = id2sdIt->second.back();
+ _periodicity->_shrinkFaces[ i ].Init( _mesh->GetSubMeshContaining( id2sdIt->first ), sd1, sd2 );
+ }
+
+ for ( size_t i1 = 0; i1 < _periodicity->_shrinkFaces.size(); ++i1 )
+ for ( size_t i2 = i1 + 1; i2 < _periodicity->_shrinkFaces.size(); ++i2 )
+ {
+ PeriodicFaces pf( & _periodicity->_shrinkFaces[ i1 ],
+ & _periodicity->_shrinkFaces[ i2 ]);
+ if ( pf._shriFace[0]->IsPeriodic( *pf._shriFace[1], pf ))
+ {
+ _periodicity->_periodicFaces.push_back( pf );
+ }
+ }
+ return;
+}
+
//================================================================================
/*!
* \brief Shrink 2D mesh on faces to let space for inflated layers
_SolidData& data = _sdVec[i];
map< TGeomID, TopoDS_Shape >::iterator s2s = data._shrinkShape2Shape.begin();
for (; s2s != data._shrinkShape2Shape.end(); ++s2s )
- if ( s2s->second.ShapeType() == TopAbs_FACE && !_shrinkedFaces.Contains( s2s->second ))
+ if ( s2s->second.ShapeType() == TopAbs_FACE && !_shrunkFaces.Contains( s2s->second ))
{
f2sdMap[ getMeshDS()->ShapeToIndex( s2s->second )].push_back( &data );
- // Put mesh faces on the shrinked FACE to the proxy sub-mesh to avoid
+ // Put mesh faces on the shrunk FACE to the proxy sub-mesh to avoid
// usage of mesh faces made in addBoundaryElements() by the 3D algo or
// by StdMeshers_QuadToTriaAdaptor
if ( SMESHDS_SubMesh* smDS = getMeshDS()->MeshElements( s2s->second ))
Handle(Geom_Surface) surface = BRep_Tool::Surface( F );
- _shrinkedFaces.Add( F );
+ _shrunkFaces.Add( F );
helper.SetSubShape( F );
+ // ==============================
+ // Use periodicity to move nodes
+ // ==============================
+
+ PeriodicFaces* periodic = _periodicity->GetPeriodic( F, _shrunkFaces );
+ bool movedByPeriod = ( periodic && periodic->MoveNodes( F ));
+
// ===========================
// Prepare data for shrinking
// ===========================
// Collect nodes to smooth (they are marked at the beginning of this method)
vector < const SMDS_MeshNode* > smoothNodes;
+
+ if ( !movedByPeriod )
{
SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
while ( nIt->more() )
}
subEOS.push_back( eos );
- for ( size_t i = 0; i < eos->_edges.size(); ++i )
- {
- lEdges.push_back( eos->_edges[ i ] );
- prepareEdgeToShrink( *eos->_edges[ i ], *eos, helper, smDS );
- }
+ if ( !movedByPeriod )
+ for ( size_t i = 0; i < eos->_edges.size(); ++i )
+ {
+ lEdges.push_back( eos->_edges[ i ] );
+ prepareEdgeToShrink( *eos->_edges[ i ], *eos, helper, smDS );
+ }
}
}
if ( eos.SWOLType() == TopAbs_EDGE )
{
SMESH_subMesh* edgeSM = _mesh->GetSubMesh( eos._sWOL );
- _Shrinker1D& shrinker = e2shrMap[ edgeSM->GetId() ];
- eShri1D.insert( & shrinker );
- shrinker.AddEdge( eos._edges[0], eos, helper );
VISCOUS_3D::ToClearSubWithMain( edgeSM, data._solid );
- // restore params of nodes on EDGE if the EDGE has been already
- // shrinked while shrinking other FACE
- shrinker.RestoreParams();
+ if ( !movedByPeriod )
+ {
+ _Shrinker1D& shrinker = e2shrMap[ edgeSM->GetId() ];
+ eShri1D.insert( & shrinker );
+ shrinker.AddEdge( eos._edges[0], eos, helper );
+ // restore params of nodes on EDGE if the EDGE has been already
+ // shrunk while shrinking other FACE
+ shrinker.RestoreParams();
+ }
}
for ( size_t i = 0; i < eos._edges.size(); ++i )
{
}
bool toFixTria = false; // to improve quality of trias by diagonal swap
- if ( isConcaveFace )
+ if ( isConcaveFace && !movedByPeriod )
{
const bool hasTria = _mesh->NbTriangles(), hasQuad = _mesh->NbQuadrangles();
if ( hasTria != hasQuad ) {
// Perform shrinking
// ==================
- bool shrinked = true;
+ bool shrunk = !movedByPeriod;
int nbBad, shriStep=0, smooStep=0;
_SmoothNode::SmoothType smoothType
= isConcaveFace ? _SmoothNode::ANGULAR : _SmoothNode::LAPLACIAN;
SMESH_Comment errMsg;
- while ( shrinked )
+ while ( shrunk )
{
shriStep++;
// Move boundary nodes (actually just set new UV)
// -----------------------------------------------
dumpFunction(SMESH_Comment("moveBoundaryOnF")<<f2sd->first<<"_st"<<shriStep ); // debug
- shrinked = false;
+ shrunk = false;
for ( size_t iS = 0; iS < subEOS.size(); ++iS )
{
_EdgesOnShape& eos = * subEOS[ iS ];
for ( size_t i = 0; i < eos._edges.size(); ++i )
{
- shrinked |= eos._edges[i]->SetNewLength2d( surface, F, eos, helper );
+ shrunk |= eos._edges[i]->SetNewLength2d( surface, F, eos, helper );
}
}
dumpFunctionEnd();
// }
// }
- } // while ( shrinked )
+ } // while ( shrunk )
if ( !errMsg.empty() ) // Try to re-compute the shrink FACE
{
return error( errMsg );
} // end of re-meshing in case of failed smoothing
- else
+ else if ( !movedByPeriod )
{
// No wrongly shaped faces remain; final smooth. Set node XYZ.
bool isStructuredFixed = false;
} // loop on FACES to shrink mesh on
- // Replace source nodes by target nodes in shrinked mesh edges
+ // Replace source nodes by target nodes in shrunk mesh edges
map< int, _Shrinker1D >::iterator e2shr = e2shrMap.begin();
for ( ; e2shr != e2shrMap.end(); ++e2shr )
return newPos;
}
-//================================================================================
-/*!
- * \brief Delete _SolidData
- */
-//================================================================================
-
-_SolidData::~_SolidData()
-{
- TNode2Edge::iterator n2e = _n2eMap.begin();
- for ( ; n2e != _n2eMap.end(); ++n2e )
- {
- _LayerEdge* & e = n2e->second;
- if ( e )
- {
- delete e->_curvature;
- if ( e->_2neibors )
- delete e->_2neibors->_plnNorm;
- delete e->_2neibors;
- }
- delete e;
- e = 0;
- }
- _n2eMap.clear();
-
- delete _helper;
- _helper = 0;
-}
-
//================================================================================
/*!
* \brief Keep a _LayerEdge inflated along the EDGE
//================================================================================
/*!
- * \brief Replace source nodes by target nodes in shrinked mesh edges
+ * \brief Replace source nodes by target nodes in shrunk mesh edges
*/
//================================================================================
#include <vector>
+class SMDS_MeshGroup;
+
/*!
* \brief Hypothesis defining parameters of viscous layers
*/
void SetMethod( ExtrusionMethod how );
ExtrusionMethod GetMethod() const { return _method; }
+ // name of a group to create
+ void SetGroupName(const std::string& name);
+ const std::string& GetGroupName() const { return _groupName; }
+ static SMDS_MeshGroup* CreateGroup( const std::string& theName,
+ SMESH_Mesh& theMesh,
+ SMDSAbs_ElementType theType);
+
// Computes temporary 2D mesh to be used by 3D algorithm.
// Return SMESH_ProxyMesh for each SOLID in theShape
SMESH_ProxyMesh::Ptr Compute(SMESH_Mesh& theMesh,
double _thickness;
double _stretchFactor;
ExtrusionMethod _method;
+ std::string _groupName;
};
class SMESH_subMesh;
outerNodes.swap( innerNodes );
}
+ // Add faces to a group
+ SMDS_MeshGroup* group = StdMeshers_ViscousLayers::CreateGroup( hyp->GetGroupName(),
+ *_helper.GetMesh(),
+ SMDSAbs_Face );
+ if ( group )
+ {
+ TIDSortedElemSet::iterator fIt = L._newFaces.begin();
+ for ( ; fIt != L._newFaces.end(); ++fIt )
+ group->Add( *fIt );
+ }
+
// faces between not shared _LayerEdge's (at concave VERTEX)
for ( int isR = 0; isR < 2; ++isR )
{
if ( lNodes.empty() || rNodes.empty() || lNodes.size() != rNodes.size() )
continue;
+ const SMDS_MeshElement* face = 0;
for ( size_t i = 1; i < lNodes.size(); ++i )
- _helper.AddFace( lNodes[ i+prev ], rNodes[ i+prev ],
- rNodes[ i+cur ], lNodes[ i+cur ]);
+ {
+ face = _helper.AddFace( lNodes[ i+prev ], rNodes[ i+prev ],
+ rNodes[ i+cur ], lNodes[ i+cur ]);
+ if ( group )
+ group->Add( face );
+ }
const UVPtStruct& ptOnVertex = points[ isR ? L._lastPntInd : L._firstPntInd ];
if ( isReverse )
- _helper.AddFace( ptOnVertex.node, lNodes[ 0 ], rNodes[ 0 ]);
+ face = _helper.AddFace( ptOnVertex.node, lNodes[ 0 ], rNodes[ 0 ]);
else
- _helper.AddFace( ptOnVertex.node, rNodes[ 0 ], lNodes[ 0 ]);
+ face = _helper.AddFace( ptOnVertex.node, rNodes[ 0 ], lNodes[ 0 ]);
+ if ( group )
+ group->Add( face );
}
// Fill the _ProxyMeshOfFace
StdMeshersGUI_CartesianParamCreator.h
StdMeshersGUI_RadioButtonsGrpWdg.h
StdMeshersGUI_PropagationHelperWdg.h
+ StdMeshersGUI_NameCheckableGrpWdg.h
)
IF(SALOME_USE_PLOT2DVIEWER)
StdMeshersGUI_CartesianParamCreator.cxx
StdMeshersGUI_RadioButtonsGrpWdg.cxx
StdMeshersGUI_PropagationHelperWdg.cxx
+ StdMeshersGUI_NameCheckableGrpWdg.cxx
)
IF(SALOME_USE_PLOT2DVIEWER)
axisTabLayout->setSpacing( SPACING );
axisTabLayout->addWidget( modeBox , 0, 0, 1, 3 );
- axisTabLayout->addWidget( myInsertBtn , 1, 0, 1, 2 );
- axisTabLayout->addWidget( myDeleteBtn , 2, 0, 1, 2 );
+ axisTabLayout->addWidget( myInsertBtn, 1, 0, 1, 2 );
+ axisTabLayout->addWidget( myDeleteBtn, 2, 0, 1, 2 );
axisTabLayout->addWidget( myStepLabel, 3, 0 );
axisTabLayout->addWidget( myStepSpin , 3, 1 );
axisTabLayout->addWidget( csFrame , 1, 2, 4, 1 );
myAddEdges = new QCheckBox( tr("ADD_EDGES"), GroupC1 );
argGroupLayout->addWidget( myAddEdges, row, 0, 1, 2 );
row++;
+ myCreateFaces = new QCheckBox( tr("CREATE_FACES"), GroupC1 );
+ argGroupLayout->addWidget( myCreateFaces, row, 0, 1, 2 );
+ row++;
+ myConsiderInternalFaces = new QCheckBox( tr("CONSIDER_INTERNAL_FACES"), GroupC1 );
+ argGroupLayout->addWidget( myConsiderInternalFaces, row, 0, 1, 2 );
+ row++;
+ myUseThresholdForInternalFaces = new QCheckBox( tr("USE_THRESHOLD_FOR_INTERNAL_FACES"), GroupC1 );
+ argGroupLayout->addWidget( myUseThresholdForInternalFaces, row, 0, 1, 2 );
+ row++;
// 3) Grid definition
QTabWidget* tabWdg = new QTabWidget( fr );
connect( myOrthogonalChk, SIGNAL( toggled(bool)), SLOT( onOrthogonalAxes(bool)));
connect( optimBtn, SIGNAL( clicked(bool)), SLOT( onOptimalAxes(bool)));
connect( resetBtn, SIGNAL( clicked(bool)), SLOT( onResetAxes(bool)));
+ connect( myConsiderInternalFaces, SIGNAL( toggled(bool)),
+ myUseThresholdForInternalFaces, SLOT( setEnabled(bool)));
for ( int i = 0; i < 3; ++i )
{
connect( myXDirSpin[i], SIGNAL(valueChanged (const QString&)),
myThreshold->setText( varName );
myAddEdges->setChecked( h->GetToAddEdges() );
+ myCreateFaces->setChecked( h->GetToCreateFaces() );
+ myConsiderInternalFaces->setChecked( h->GetToConsiderInternalFaces() );
+ myUseThresholdForInternalFaces->setChecked( h->GetToUseThresholdForInternalFaces() );
// grid definition
for ( int ax = 0; ax < 3; ++ax )
h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" );
h->SetSizeThreshold( myThreshold->text().toDouble() );
h->SetToAddEdges( myAddEdges->isChecked() );
+ h->SetToCreateFaces( myCreateFaces->isChecked() );
+ h->SetToConsiderInternalFaces( myConsiderInternalFaces->isChecked() );
+ h->SetToUseThresholdForInternalFaces( myUseThresholdForInternalFaces->isChecked() );
// grid
for ( int ax = 0; ax < 3; ++ax )
QLineEdit* myName;
SMESHGUI_SpinBox* myThreshold;
QCheckBox* myAddEdges;
+ QCheckBox* myCreateFaces;
+ QCheckBox* myConsiderInternalFaces;
+ QCheckBox* myUseThresholdForInternalFaces;
StdMeshersGUI::GridAxisTab* myAxisTabs[3];
QGroupBox* myFixedPointGrp;
--- /dev/null
+// Copyright (C) 2007-2019 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
+//
+#include "StdMeshersGUI_NameCheckableGrpWdg.h"
+
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+
+#define SPACING 6
+#define MARGIN 11
+
+//================================================================================
+/*!
+ * \brief Creates a QGroupBox with a given title
+ */
+//================================================================================
+
+StdMeshersGUI_NameCheckableGrpWdg::StdMeshersGUI_NameCheckableGrpWdg( const QString& groupTitle,
+ const QString& nameLabel )
+ : QGroupBox( groupTitle ),
+ myNameLineEdit( new QLineEdit( this ))
+{
+ setCheckable( true );
+
+ QLabel* label = new QLabel( nameLabel );
+
+ QGridLayout* layout = new QGridLayout( this );
+ layout->setSpacing(SPACING);
+ layout->setMargin(MARGIN);
+
+ layout->addWidget( label, 0, 0 );
+ layout->addWidget( myNameLineEdit, 0, 1 );
+
+ connect( this, SIGNAL( toggled( bool )), myNameLineEdit, SLOT( setEnabled( bool )));
+}
+
+QString StdMeshersGUI_NameCheckableGrpWdg::getName()
+{
+ return isChecked() ? myNameLineEdit->text() : QString();
+}
+
+void StdMeshersGUI_NameCheckableGrpWdg::setName( CORBA::String_var name )
+{
+ myNameLineEdit->setText( name.in() );
+ setChecked( ! myNameLineEdit->text().isEmpty() );
+}
+
+void StdMeshersGUI_NameCheckableGrpWdg::setDefaultName( QString name )
+{
+ myNameLineEdit->setText( name );
+ setChecked( ! myNameLineEdit->text().isEmpty() );
+}
--- /dev/null
+// Copyright (C) 2007-2019 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
+//
+#ifndef STDMESHERSGUI_NameCheckableGrpWdg_H
+#define STDMESHERSGUI_NameCheckableGrpWdg_H
+
+// SMESH includes
+#include "SMESH_StdMeshersGUI.hxx"
+
+// Qt includes
+#include <QGroupBox>
+
+#include <omniORB4/CORBA.h>
+
+class QButtonGroup;
+class QLineEdit;
+
+/*!
+ * \brief A QGroupBox holding several radio buttons
+ */
+class STDMESHERSGUI_EXPORT StdMeshersGUI_NameCheckableGrpWdg : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ StdMeshersGUI_NameCheckableGrpWdg(const QString& groupTitle,
+ const QString& nameLabel);
+
+ QString getName();
+
+ void setName( CORBA::String_var name );
+ void setDefaultName( QString name );
+
+private:
+ QLineEdit* myNameLineEdit;
+};
+
+#endif // STDMESHERSGUI_NameCheckableGrpWdg_H
#include "StdMeshersGUI_PropagationHelperWdg.h"
#include "StdMeshersGUI_QuadrangleParamWdg.h"
#include "StdMeshersGUI_RadioButtonsGrpWdg.h"
+#include "StdMeshersGUI_NameCheckableGrpWdg.h"
#include "StdMeshersGUI_SubShapeSelectorWdg.h"
#include <SALOMEDSClient_Study.hxx>
}
}
+//================================================================================
+/*!
+ * \brief Remove a group, whose name is stored by hypothesis, upon group name modification
+ * \param [in] oldName - old group name
+ * \param [in] newName - new group name
+ * \param [in] type - group type
+ */
+//================================================================================
+
+void StdMeshersGUI_StdHypothesisCreator::
+removeOldGroup(const char* oldName, const char* newName, SMESH::ElementType type) const
+{
+ if ( !oldName || !oldName[0] )
+ return; // old name undefined
+ if ( newName && strcmp( oldName, newName ) == 0 )
+ return; // same name
+
+ SMESH::SMESH_Hypothesis_var h = hypothesis();
+ SMESH::SObjectList listSOmesh = SMESH::GetMeshesUsingAlgoOrHypothesis( h );
+ for ( size_t i = 0; i < listSOmesh.size(); i++ )
+ {
+ _PTR(SObject) submSO = listSOmesh[i];
+ SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( submSO );
+ SMESH::SMESH_subMesh_var subMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>( submSO );
+ if( !subMesh->_is_nil() )
+ mesh = subMesh->GetFather();
+ if ( mesh->_is_nil() )
+ continue;
+ SMESH::ListOfGroups_var groups = mesh->GetGroups();
+ for ( CORBA::ULong iG = 0; iG < groups->length(); iG++ )
+ {
+ if ( groups[iG]->GetType() != type )
+ continue;
+ CORBA::String_var name = groups[iG]->GetName();
+ if ( strcmp( name.in(), oldName ))
+ continue;
+ mesh->RemoveGroup( groups[iG] );
+ }
+ }
+}
+
//================================================================================
/*!
* \brief Check parameter values before accept()
- * \retval bool - true if OK
+ * \retval bool - true if OK
*/
//================================================================================
{
h->SetFaces( idsWg->GetListOfIDs(), params[4].myValue.toInt() );
}
+
+ if ( StdMeshersGUI_NameCheckableGrpWdg* nameWg =
+ widget< StdMeshersGUI_NameCheckableGrpWdg >( 6 ))
+ {
+ CORBA::String_var oldName = h->GetGroupName();
+ h->SetGroupName( nameWg->getName().toUtf8().data() );
+ CORBA::String_var newName = h->GetGroupName();
+ removeOldGroup( oldName, newName, SMESH::VOLUME );
+ }
}
else if( hypType()=="ViscousLayers2D" )
{
{
h->SetEdges( idsWg->GetListOfIDs(), params[3].myValue.toInt() );
}
+
+ if ( StdMeshersGUI_NameCheckableGrpWdg* nameWg =
+ widget< StdMeshersGUI_NameCheckableGrpWdg >( 5 ))
+ {
+ CORBA::String_var oldName = h->GetGroupName();
+ h->SetGroupName( nameWg->getName().toUtf8().data() );
+ CORBA::String_var newName = h->GetGroupName();
+ removeOldGroup( oldName, newName, SMESH::FACE );
+ }
}
// else if( hypType()=="QuadrangleParams" )
// {
item.myName = tr("SMESH_USE_PREESTIMATED_LENGTH");
p.append( item );
QCheckBox* aQCheckBox = new QCheckBox(dlg());
- if ( !noPreestimatedAtEdition && h->HavePreestimatedLength() ) {
+ if ( h->HavePreestimatedLength() ) {
aQCheckBox->setChecked( h->GetUsePreestimatedLength() );
connect( aQCheckBox, SIGNAL( stateChanged(int) ), this, SLOT( onValueChanged() ) );
}
}
customWidgets()->append ( idsWg );
}
+
+ item.setNoName();
+ p.append( item );
+ StdMeshersGUI_NameCheckableGrpWdg* nameWdg =
+ new StdMeshersGUI_NameCheckableGrpWdg( tr( "CREATE_GROUPS_FROM_LAYERS" ),
+ tr( "GROUP_NAME" ));
+ nameWdg->setName( h->GetGroupName() );
+ if ( nameWdg->getName().isEmpty() )
+ {
+ nameWdg->setDefaultName( type() );
+ nameWdg->setChecked( false );
+ }
+ customWidgets()->append ( nameWdg );
}
else if( hypType()=="ViscousLayers2D" )
{
}
customWidgets()->append ( idsWg );
}
+
+ item.setNoName();
+ p.append( item );
+ StdMeshersGUI_NameCheckableGrpWdg* nameWdg =
+ new StdMeshersGUI_NameCheckableGrpWdg( tr( "CREATE_GROUPS_FROM_LAYERS" ),
+ tr( "GROUP_NAME" ));
+ nameWdg->setName( h->GetGroupName() );
+ if ( nameWdg->getName().isEmpty() )
+ {
+ nameWdg->setDefaultName( type() );
+ nameWdg->setChecked( false );
+ }
+ customWidgets()->append ( nameWdg );
}
else
res = false;
param.myValue = w->checkedId();
return true;
}
+ if ( widget->inherits( "StdMeshersGUI_NameCheckableGrpWdg" ))
+ {
+ return true;
+ }
return false;
}
bool initVariableName(SMESH::SMESH_Hypothesis_var theHyp, StdParam& theParams, const char* theMethod) const;
QWidget* makeReverseEdgesWdg( SMESH::long_array_var edgeIDs,
CORBA::String_var shapeEntry) const;
+ void removeOldGroup(const char* oldName,
+ const char* newName,
+ SMESH::ElementType type) const;
<source>ICON_SMESH_TREE_HYPO_Geometric1D</source>
<translation>mesh_tree_hypo_length.png</translation>
</message>
+ <message>
+ <source>ICON_SMESH_TREE_HYPO_ImportSource1D</source>
+ <translation>mesh_tree_hypo_import_source_1d.png</translation>
+ </message>
+ <message>
+ <source>ICON_SMESH_TREE_HYPO_ImportSource2D</source>
+ <translation>mesh_tree_hypo_import_source_2d.png</translation>
+ </message>
<message>
<source>ICON_SMESH_TREE_HYPO_AutomaticLength</source>
<translation>mesh_tree_hypo_length.png</translation>
<source>ICON_SMESH_TREE_HYPO_Deflection1D</source>
<translation>mesh_tree_hypo_length.png</translation>
</message>
+ <message>
+ <source>ICON_SMESH_TREE_HYPO_FixedPoints1D</source>
+ <translation>mesh_tree_hypo_length.png</translation>
+ </message>
<message>
<source>ICON_SMESH_TREE_HYPO_Adaptive1D</source>
<translation>mesh_tree_hypo_length.png</translation>
<source>ICON_SMESH_TREE_HYPO_LayerDistribution</source>
<translation>mesh_tree_hypo_layers_distribution.png</translation>
</message>
+ <message>
+ <source>ICON_SMESH_TREE_HYPO_LayerDistribution2D</source>
+ <translation>mesh_tree_hypo_layers_distribution_2d.png</translation>
+ </message>
<message>
<source>ICON_SMESH_TREE_HYPO_LengthFromEdges</source>
<translation>mesh_tree_hypo_area.png</translation>
</message>
<message>
<source>ICON_SMESH_TREE_HYPO_NumberOfLayers2D</source>
- <translation>mesh_tree_hypo_layers_distribution.png</translation>
+ <translation>mesh_tree_hypo_layers_distribution_2d.png</translation>
</message>
<message>
<source>ICON_SMESH_TREE_HYPO_NumberOfSegments</source>
<source>EXTMETH_FACE_OFFSET</source>
<translation>Face offset</translation>
</message>
+ <message>
+ <source>CREATE_GROUPS_FROM_LAYERS</source>
+ <translation>Create groups from layers</translation>
+ </message>
+ <message>
+ <source>GROUP_NAME</source>
+ <translation>Group name</translation>
+ </message>
</context>
<context>
<name>@default</name>
<source>ADD_EDGES</source>
<translation>Implement Edges</translation>
</message>
+ <message>
+ <source>CREATE_FACES</source>
+ <translation>Create Faces</translation>
+ </message>
+ <message>
+ <source>CONSIDER_INTERNAL_FACES</source>
+ <translation>Consider Shared and Internal Faces</translation>
+ </message>
+ <message>
+ <source>USE_THRESHOLD_FOR_INTERNAL_FACES</source>
+ <translation>Apply Threshold to Shared / Internal Faces</translation>
+ </message>
<message>
<source>AXIS_X</source>
<translation>Axis X</translation>
StdMeshers_CartesianParameters3D_i.hxx
StdMeshers_Cartesian_3D_i.hxx
StdMeshers_PolygonPerFace_2D_i.hxx
+ StdMeshers_PolyhedronPerSolid_3D_i.hxx
)
IF(SALOME_SMESH_ENABLE_MEFISTO)
SET(StdMeshersEngine_HEADERS ${StdMeshersEngine_HEADERS} StdMeshers_MEFISTO_2D_i.hxx)
StdMeshers_Cartesian_3D_i.cxx
StdMeshers_Adaptive1D_i.cxx
StdMeshers_PolygonPerFace_2D_i.cxx
+ StdMeshers_PolyhedronPerSolid_3D_i.cxx
)
IF(SALOME_SMESH_ENABLE_MEFISTO)
coords[6] = zDir.PS.x;
coords[7] = zDir.PS.y;
coords[8] = zDir.PS.z;
+
+ const double* oldCoords = GetImpl()->GetAxisDirs();
+ bool isSame = true;
+ for ( int i = 0; i < 9 && isSame; ++i )
+ isSame = ( oldCoords[i] == coords[i] );
+ if ( isSame )
+ return;
+
try {
this->GetImpl()->SetAxisDirs(coords);
void StdMeshers_CartesianParameters3D_i::SetFixedPoint(const SMESH::PointStruct& ps,
CORBA::Boolean toUnset)
{
+ SMESH::PointStruct oldPS;
+ GetFixedPoint( oldPS );
+ if ( oldPS.x == ps.x && oldPS.y == ps.y && oldPS.z == ps.z )
+ return;
+
double p[3] = { ps.x, ps.y, ps.z };
GetImpl()->SetFixedPoint( p, toUnset );
return GetImpl()->GetToAddEdges();
}
+//=======================================================================
+//function : SetToConsiderInternalFaces
+//purpose : Enables treatment of geom faces, either shared by solids or internal.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D_i::SetToConsiderInternalFaces(CORBA::Boolean toTreat)
+{
+ if ( GetToConsiderInternalFaces() == toTreat )
+ return;
+ GetImpl()->SetToConsiderInternalFaces( toTreat );
+ SMESH::TPythonDump() << _this() << ".SetToConsiderInternalFaces( " << toTreat << " )";
+}
+
+//=======================================================================
+//function : GetToConsiderInternalFaces
+//purpose : Return true if treatment of internal geom faces is enabled
+//=======================================================================
+
+CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToConsiderInternalFaces()
+{
+ return GetImpl()->GetToConsiderInternalFaces();
+}
+
+//=======================================================================
+//function : SetToUseThresholdForInternalFaces
+//purpose : Enables applying size threshold to grid cells cut by internal geom faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D_i::SetToUseThresholdForInternalFaces(CORBA::Boolean toUse)
+{
+ if ( GetToUseThresholdForInternalFaces() == toUse )
+ return;
+ GetImpl()->SetToUseThresholdForInternalFaces( toUse );
+ SMESH::TPythonDump() << _this() << ".SetToUseThresholdForInternalFaces( " << toUse << " )";
+}
+
+//=======================================================================
+//function : GetToUseThresholdForInternalFaces
+//purpose : Return true if applying size threshold to grid cells cut by
+// internal geom faces is enabled
+//=======================================================================
+
+CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToUseThresholdForInternalFaces()
+{
+ return GetImpl()->GetToUseThresholdForInternalFaces();
+}
+
+//=======================================================================
+//function : SetToCreateFaces
+//purpose : Enables creation of mesh faces.
+//=======================================================================
+
+void StdMeshers_CartesianParameters3D_i::SetToCreateFaces(CORBA::Boolean toCreate)
+{
+ if ( GetToCreateFaces() == toCreate )
+ return;
+ GetImpl()->SetToCreateFaces( toCreate );
+ SMESH::TPythonDump() << _this() << ".SetToCreateFaces( " << toCreate << " )";
+}
+
+//=======================================================================
+//function : GetToCreateFaces
+//purpose : Check if creation of mesh faces enabled
+//=======================================================================
+
+CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToCreateFaces()
+{
+ return GetImpl()->GetToCreateFaces();
+}
+
//=======================================================================
//function : IsGridBySpacing
//purpose : Return true if the grid is defined by spacing functions and
/*!
- * \brief Enables implementation of geometrical edges into the mesh. If this feature
+ * \brief Enable implementation of geometrical edges into the mesh. If this feature
* is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
* they don't coincide with the grid lines
*/
CORBA::Boolean GetToAddEdges();
/*!
- * \brief Return true if the grid is defined by spacing functions and
+ * Enable treatment of geom faces, either shared by solids or internal.
+ */
+ void SetToConsiderInternalFaces(CORBA::Boolean toTreat);
+ CORBA::Boolean GetToConsiderInternalFaces();
+
+ /*!
+ * Enable applying size threshold to grid cells cut by internal geom faces.
+ */
+ void SetToUseThresholdForInternalFaces(CORBA::Boolean toUse);
+ CORBA::Boolean GetToUseThresholdForInternalFaces();
+
+ /*!
+ * Enable creation of mesh faces.
+ */
+ void SetToCreateFaces(CORBA::Boolean toCreate);
+ CORBA::Boolean GetToCreateFaces();
+
+
+ /*!
+ * \brief Return true if the grid is defined by spacing functions and
* not by node coordinates
*/
CORBA::Boolean IsGridBySpacing(CORBA::Short axis);
/*!
- * Returns axes at which number of hexahedra is maximal
+ * Return axes at which number of hexahedra is maximal
*/
void ComputeOptimalAxesDirs(GEOM::GEOM_Object_ptr shape,
CORBA::Boolean isOrthogonal,
SMESH::DirStruct& y,
SMESH::DirStruct& z) throw (SALOME::SALOME_Exception);
/*!
- * \brief Computes node coordinates by spacing functions
+ * \brief Compute node coordinates by spacing functions
* \param x0 - lower coordinate
* \param x1 - upper coordinate
* \param spaceFuns - space functions
--- /dev/null
+// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, 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 : StdMeshers_PolyhedronPerSolid_3D_i.cxx
+// Module : SMESH
+//
+
+#include "StdMeshers_PolyhedronPerSolid_3D_i.hxx"
+
+#include "SMESH_Gen.hxx"
+#include "StdMeshers_PolyhedronPerSolid_3D.hxx"
+
+//=============================================================================
+/*!
+ * Constructor
+ */
+//=============================================================================
+
+StdMeshers_PolyhedronPerSolid_3D_i::StdMeshers_PolyhedronPerSolid_3D_i( PortableServer::POA_ptr thePOA,
+ ::SMESH_Gen* theGenImpl )
+ : SALOME::GenericObj_i( thePOA ),
+ SMESH_Hypothesis_i( thePOA ),
+ SMESH_Algo_i( thePOA ),
+ SMESH_3D_Algo_i( thePOA )
+{
+ myBaseImpl = new ::StdMeshers_PolyhedronPerSolid_3D( theGenImpl->GetANewId(),
+ theGenImpl );
+}
+
+//=============================================================================
+/*!
+ * Destructor
+ */
+//=============================================================================
+
+StdMeshers_PolyhedronPerSolid_3D_i::~StdMeshers_PolyhedronPerSolid_3D_i()
+{
+}
--- /dev/null
+// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, 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 : StdMeshers_PolyhedronPerSolid_3D_i.hxx
+// Module : SMESH
+//
+#ifndef _SMESH_PolyhedronPerSolid_3D_I_HXX_
+#define _SMESH_PolyhedronPerSolid_3D_I_HXX_
+
+#include "SMESH_StdMeshers_I.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
+
+#include "SMESH_3D_Algo_i.hxx"
+
+class SMESH_Gen;
+
+// ======================================================
+// Polyhedron Per Solid 3D algorithm
+// ======================================================
+class STDMESHERS_I_EXPORT StdMeshers_PolyhedronPerSolid_3D_i:
+ public virtual POA_StdMeshers::StdMeshers_PolyhedronPerSolid_3D,
+ public virtual SMESH_3D_Algo_i
+{
+ public:
+ // Constructor
+ StdMeshers_PolyhedronPerSolid_3D_i( PortableServer::POA_ptr thePOA,
+ ::SMESH_Gen* theGenImpl );
+ // Destructor
+ virtual ~StdMeshers_PolyhedronPerSolid_3D_i();
+};
+
+#endif
return GetImpl()->GetStretchFactor();
}
+//================================================================================
+/*!
+ * \brief Set name of a group of layers elements
+ */
+//================================================================================
+
+void StdMeshers_ViscousLayers2D_i::SetGroupName(const char* name)
+{
+ if ( GetImpl()->GetGroupName() != name )
+ {
+ GetImpl()->SetGroupName( name );
+ SMESH::TPythonDump() << _this() << ".SetGroupName( '" << name << "' )";
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Return name of a group of layers elements
+ */
+//================================================================================
+
+char* StdMeshers_ViscousLayers2D_i::GetGroupName()
+{
+ return CORBA::string_dup( GetImpl()->GetGroupName().c_str() );
+}
+
+
//=============================================================================
/*!
* Get implementation
void SetStretchFactor(::CORBA::Double factor) throw ( SALOME::SALOME_Exception );
::CORBA::Double GetStretchFactor();
+ void SetGroupName(const char* name);
+ char* GetGroupName();
+
+
// Get implementation
::StdMeshers_ViscousLayers2D* GetImpl();
return (::StdMeshers::VLExtrusionMethod) GetImpl()->GetMethod();
}
+//================================================================================
+/*!
+ * \brief Set name of a group of layers elements
+ */
+//================================================================================
+
+void StdMeshers_ViscousLayers_i::SetGroupName(const char* name)
+{
+ if ( GetImpl()->GetGroupName() != name )
+ {
+ GetImpl()->SetGroupName( name );
+ SMESH::TPythonDump() << _this() << ".SetGroupName( '" << name << "' )";
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Return name of a group of layers elements
+ */
+//================================================================================
+
+char* StdMeshers_ViscousLayers_i::GetGroupName()
+{
+ return CORBA::string_dup( GetImpl()->GetGroupName().c_str() );
+}
+
//=============================================================================
/*!
* Get implementation
void SetMethod( ::StdMeshers::VLExtrusionMethod how );
::StdMeshers::VLExtrusionMethod GetMethod();
+ void SetGroupName(const char* name);
+ char* GetGroupName();
+
+
// Get implementation
::StdMeshers_ViscousLayers* GetImpl();
- // Verify whether hypothesis supports given entity type
+ // Verify whether hypothesis supports given entity type
CORBA::Boolean IsDimSupported( SMESH::Dimension type );
// Methods for copying mesh definition to other geometry
#include "StdMeshers_NumberOfLayers_i.hxx"
#include "StdMeshers_NumberOfSegments_i.hxx"
#include "StdMeshers_PolygonPerFace_2D_i.hxx"
+#include "StdMeshers_PolyhedronPerSolid_3D_i.hxx"
#include "StdMeshers_Prism_3D_i.hxx"
#include "StdMeshers_ProjectionSource1D_i.hxx"
#include "StdMeshers_ProjectionSource2D_i.hxx"
aCreator = new StdHypothesisCreator_i<StdMeshers_Cartesian_3D_i>;
else if (strcmp(aHypName, "PolygonPerFace_2D") == 0)
aCreator = new StdHypothesisCreator_i<StdMeshers_PolygonPerFace_2D_i>;
+ else if (strcmp(aHypName, "PolyhedronPerSolid_3D") == 0)
+ aCreator = new StdHypothesisCreator_i<StdMeshers_PolyhedronPerSolid_3D_i>;
else ;
return aCreator;
{
bool plus = false;
bool moins = false;
- int *offset = MAILLAGE1->CNX[TETRA4] + 4 * it4;
+ med_int *offset = MAILLAGE1->CNX[TETRA4] + 4 * it4;
for (int is = 0; is < 4; is++)
{
int ng = *(offset + is);
// cout << "Legacy " << tm << " effectif " << MAILLAGE1->EFFECTIFS_TYPES[tm] << endl;
int tailleType = Nnoeuds(tm);
- MAILLAGE2->CNX[tm] = (int*) malloc(sizeof(int) * tailleType * (MAILLAGE1->EFFECTIFS_TYPES[tm]
+ MAILLAGE2->CNX[tm] = (med_int*) malloc(sizeof(med_int) * tailleType * (MAILLAGE1->EFFECTIFS_TYPES[tm]
+ cptNouvellesMailles[tm]));
for (int i = 0; i < MAILLAGE1->EFFECTIFS_TYPES[tm]; i++)
for (int j = 0; j < tailleType; j++)
float A[3], B[3];
// Détermination des ng des extrémités de l'arête passée en argument na
- int * offset = MAILLAGE1->CNX[TETRA4] + 4 * it4;
+ med_int * offset = MAILLAGE1->CNX[TETRA4] + 4 * it4;
if (na == 0)
{
ngA = *(offset + 0);
{
cout << "\tMaille " << i << " :" << endl;
//Boucle sur les noeuds de la maille de numéro local i dans le type tm
- int * offset = CNX[tm] + nnoeuds * i;
+ med_int * offset = CNX[tm] + nnoeuds * i;
for (int j = 0; j < nnoeuds; j++)
{
int ngnoeud = *(offset + j);
med_int *famTYPE = (med_int*) malloc(sizeof(med_int) * nTYPE);
//med_int *conTYPE = (med_int*) malloc(sizeof(med_int)*tTYPE*nTYPE);
- CNX[TYPE] = (int*) malloc(sizeof(int) * tTYPE * nTYPE);
+ CNX[TYPE] = (med_int*) malloc(sizeof(med_int) * tTYPE * nTYPE);
med_bool inomTYPE, inumTYPE, ifamTYPE;
med_geometry_type typeBanaliseMED = InstanceMGE(TYPE);
// ************* Modification de la connectivité du type concerné
- int* CNX2;
+ med_int* CNX2;
int nNoeudsType = Nnoeuds(tm);
int tailleCNX2 = nNoeudsType * (EFFECTIFS_TYPES[tm] - listeMaillesSuppr.size());
- CNX2 = (int*) malloc(sizeof(int) * tailleCNX2);
+ CNX2 = (med_int*) malloc(sizeof(med_int) * tailleCNX2);
// Recopie sélective des connectivités
int isuppr = 0; // indice dans listeMaillesSuppr
int ih2 = 0; // nouveau numéro local ( remarque: ih2 = ih1 - isuppr )
// Le numéro global du j-ième noeud de la maille de numéro global i est stocké à l'adresse
// CNX[tm]+t*(i-1)+(j-1)
// (t = taille du type, i.e. nombre de noeuds de l'élément)
- std::map<TYPE_MAILLE, int*> CNX; // ****** MED-OBLIGATOIRE ******
+ std::map<TYPE_MAILLE, med_int*> CNX; // ****** MED-OBLIGATOIRE ******
// Enveloppes cubiques
std::map<TYPE_MAILLE, float*> EC;
/*!
* Conversion HL-MED d'une table de connectivités
*/
-void MESHCUT::conversionCNX(int *CNXtm, TYPE_MAILLE tm, int N)
+void MESHCUT::conversionCNX(med_int *CNXtm, TYPE_MAILLE tm, int N)
{
int n = Nnoeuds(tm);
std::string nomMaille(TYPE_MAILLE tm, int nl);
bool appartientVN(int n, std::vector<int> V);
float distance2(float x1, float y1, float z1, float x2, float y2, float z2);
- void conversionCNX(int *CNXtm, TYPE_MAILLE tm, int N);
+ void conversionCNX(med_int *CNXtm, TYPE_MAILLE tm, int N);
}