Salome HOME
Merge branch 'occ/shaper2smesh'
authorvsr <vsr@opencascade.com>
Fri, 21 Feb 2020 12:13:04 +0000 (15:13 +0300)
committervsr <vsr@opencascade.com>
Fri, 21 Feb 2020 14:00:22 +0000 (17:00 +0300)
106 files changed:
CMakeLists.txt
bin/smesh_setenv.py
doc/salome/examples/cartesian_algo.py
doc/salome/examples/defining_hypotheses_ex17.py
doc/salome/gui/SMESH/images/cartesian3D_hyp.png
doc/salome/gui/SMESH/images/hypo_sets.png
doc/salome/gui/SMESH/images/pref21.png
doc/salome/gui/SMESH/images/viscous_layers_2d_hyp.png
doc/salome/gui/SMESH/images/viscous_layers_hyp.png
doc/salome/gui/SMESH/input/additional_hypo.rst
doc/salome/gui/SMESH/input/basic_meshing_algos.rst
doc/salome/gui/SMESH/input/cartesian_algo.rst
doc/salome/gui/SMESH/input/constructing_meshes.rst
doc/salome/gui/SMESH/input/mesh_preferences.rst
idl/SMESH_BasicHypothesis.idl
idl/SMESH_Gen.idl
resources/CMakeLists.txt
resources/SalomeApp.xml.in
resources/StdMeshers.xml.in
resources/mesh_tree_hypo_import_source_1d.png [new file with mode: 0644]
resources/mesh_tree_hypo_import_source_2d.png [new file with mode: 0644]
resources/mesh_tree_hypo_layers_distribution_2d.png [new file with mode: 0644]
src/Controls/SMESH_Controls.cxx
src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx
src/DriverMED/DriverMED_W_SMESHDS_Mesh.cxx
src/DriverMED/DriverMED_W_SMESHDS_Mesh.h
src/MEDWrapper/MED_Common.hxx
src/MEFISTO2/Rn.h
src/OBJECT/SMESH_FaceOrientationFilter.cxx
src/SMDS/SMDS_BallElement.cxx
src/SMDS/SMDS_VolumeTool.cxx
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Hypothesis.hxx
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_Mesh.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESHDS/SMESHDS_SubMesh.cxx
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.cxx
src/SMESHGUI/SMESHGUI_GroupOnShapeDlg.h
src/SMESHGUI/SMESHGUI_Hypotheses.cxx
src/SMESHGUI/SMESHGUI_Hypotheses.h
src/SMESHGUI/SMESHGUI_HypothesesUtils.cxx
src/SMESHGUI/SMESHGUI_HypothesesUtils.h
src/SMESHGUI/SMESHGUI_MeshDlg.cxx
src/SMESHGUI/SMESHGUI_MeshDlg.h
src/SMESHGUI/SMESHGUI_MeshOp.cxx
src/SMESHGUI/SMESHGUI_MeshOp.h
src/SMESHGUI/SMESHGUI_VTKUtils.cxx
src/SMESHGUI/SMESHGUI_VTKUtils.h
src/SMESHGUI/SMESHGUI_XmlHandler.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESHGUI/SMESH_msg_fr.ts
src/SMESHUtils/SMESH_Delaunay.cxx
src/SMESH_I/CMakeLists.txt
src/SMESH_I/SMESH_2smeshpy.cxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_Gen_i_1.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Mesh_i.hxx
src/SMESH_I/SMESH_PreMeshInfo.cxx
src/SMESH_I/SMESH_PythonDump.cxx
src/SMESH_SWIG/StdMeshersBuilder.py
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG/smesh_algorithm.py
src/StdMeshers/CMakeLists.txt
src/StdMeshers/StdMeshers_CartesianParameters3D.cxx
src/StdMeshers/StdMeshers_CartesianParameters3D.hxx
src/StdMeshers/StdMeshers_Cartesian_3D.cxx
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_Geometric1D.cxx
src/StdMeshers/StdMeshers_PolygonPerFace_2D.cxx
src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Regular_1D.cxx
src/StdMeshers/StdMeshers_ViscousLayers.cxx
src/StdMeshers/StdMeshers_ViscousLayers.hxx
src/StdMeshers/StdMeshers_ViscousLayers2D.cxx
src/StdMeshersGUI/CMakeLists.txt
src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.h
src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.cxx [new file with mode: 0644]
src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.h [new file with mode: 0644]
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.cxx
src/StdMeshersGUI/StdMeshersGUI_StdHypothesisCreator.h
src/StdMeshersGUI/StdMeshers_images.ts
src/StdMeshersGUI/StdMeshers_msg_en.ts
src/StdMeshers_I/CMakeLists.txt
src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.cxx
src/StdMeshers_I/StdMeshers_CartesianParameters3D_i.hxx
src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.cxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.hxx [new file with mode: 0644]
src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.cxx
src/StdMeshers_I/StdMeshers_ViscousLayers2D_i.hxx
src/StdMeshers_I/StdMeshers_ViscousLayers_i.cxx
src/StdMeshers_I/StdMeshers_ViscousLayers_i.hxx
src/StdMeshers_I/StdMeshers_i.cxx
src/Tools/MeshCut/MeshCut_DC.cxx
src/Tools/MeshCut/MeshCut_Fonctions.cxx
src/Tools/MeshCut/MeshCut_Maillage.cxx
src/Tools/MeshCut/MeshCut_Maillage.hxx
src/Tools/MeshCut/MeshCut_Utils.cxx
src/Tools/MeshCut/MeshCut_Utils.hxx

index 10fb7d49246b561a49dcd6102a20d607b4a51fca..3515fa48d53d114b06f583afb45531afb076bc5e 100644 (file)
@@ -76,10 +76,11 @@ OPTION(SALOME_BUILD_TESTS "Build SALOME tests" ON)
 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)
 
@@ -87,6 +88,12 @@ IF(SALOME_SMESH_DYNLOAD_LOCAL)
   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)
@@ -94,7 +101,7 @@ IF(NOT WIN32)
   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
 # =============
index 1500621f89fcd61ae835936984d3f23d5c012cf1..6826ab0cefa898fac93585d5a9ce1ef53dfffd9b 100644 (file)
 # 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)
index 26bdb8bf0eaaad9c22bb0051e1561cb89f1c7c10..d7d64b8b7617bfbb8e813f812b52ea0509b3cb1e 100644 (file)
@@ -14,10 +14,13 @@ smesh =  smeshBuilder.New()
 
 # 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
@@ -38,7 +41,27 @@ mesh.Compute()
 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"]
index f2b7d8c20f4f21207ef87ac3a0e2c92ddcb80820..cadd71e24b0af4b1845677b98dc14820ee67e8d0 100644 (file)
@@ -33,16 +33,22 @@ mesh.Segment().NumberOfSegments( 4 )
 
 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)
@@ -55,12 +61,17 @@ edgeIds = geompy.SubShapeAllIDs( face1, geompy.ShapeType["EDGE"])[:-1]
 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()
index c9a605fea0ca0cec4e0d8ba14290e00db423cac9..9f4c59a033bf1f2081553c72d6c564c2d25db971 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/cartesian3D_hyp.png and b/doc/salome/gui/SMESH/images/cartesian3D_hyp.png differ
index 2a9859d231e9b79fe6e8de4d5611c00656334918..14af9af48a178f666fb66c0662ecc2328795ab82 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/hypo_sets.png and b/doc/salome/gui/SMESH/images/hypo_sets.png differ
index 1f5d63cf92ee2e0b0e7848f4546c6682c2959070..b0d756fd7f1fdb4713631ff7328fccde21706be3 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/pref21.png and b/doc/salome/gui/SMESH/images/pref21.png differ
index 4ad6ee0ec4720ea1ee8c55ead9d8bcdb0cb7946f..f9b952fd7f9379a54d1640e8d1613c7c30ba4039 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/viscous_layers_2d_hyp.png and b/doc/salome/gui/SMESH/images/viscous_layers_2d_hyp.png differ
index aaf9ad6588b7d531709855adedb204795e043562..b7bbffbe63787ec5983c7eea7571eb61a00b98db 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/viscous_layers_hyp.png and b/doc/salome/gui/SMESH/images/viscous_layers_hyp.png differ
index c6665910dcc8a817c06fa0d7863805b0f1bb7400..6fa98f9c29687becdc4a6b4da847f2e9299285af 100644 (file)
@@ -108,6 +108,8 @@ computations.
   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
 
index 692232fd13eff17bfbc9a6f6c4cae80fbda0063f..d636b15f9e100c5506d1e1686350113e5dc7b8ce 100644 (file)
@@ -53,6 +53,7 @@ An algorithm represents either an implementation of a certain meshing technique
    * :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.
index 46605bbe409bb60f7e62bb78e076669b5b5618ed..34587287163f679ba08c752055d88f1e74633c16 100644 (file)
@@ -52,6 +52,9 @@ This dialog allows to define
        .. 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.
index f5aca445734b3be786822858befb1c7d4acac3c5..05c4c0d39d08b42f9f1fb22f033f8577bc8ca75b 100644 (file)
@@ -160,7 +160,6 @@ To construct a mesh:
       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.
   
 
index 734011f1b2076ae2f04fcb79919439564d45a616..027518e91d6b510905319dae4486cbf590a23126 100644 (file)
@@ -101,6 +101,10 @@ General Preferences
 
   * **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.
index a4bb746a64ef4ad059e0c35039c5e9afcef0c6b9..1f8bf76f6f5a038049308b1aca4487a697950efc 100644 (file)
@@ -924,6 +924,9 @@ module StdMeshers
 
     void SetMethod( in VLExtrusionMethod how );
     VLExtrusionMethod GetMethod();
+
+    void SetGroupName(in string name);
+    string GetGroupName();
   };
 
   /*!
@@ -965,6 +968,9 @@ module StdMeshers
      */
     void SetStretchFactor(in double factor) raises (SALOME::SALOME_Exception);
     double GetStretchFactor();
+
+    void SetGroupName(in string name);
+    string GetGroupName();
   };
 
   /*!
@@ -1031,7 +1037,7 @@ module StdMeshers
     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
      */
@@ -1039,17 +1045,35 @@ module StdMeshers
     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
@@ -1114,6 +1138,13 @@ module StdMeshers
   {
   };
 
+  /*!
+   * 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
    */
index cdb800e87d8317736b0011750ccaa77662d669d5..f612bb08ec642e7fdd500edcdddcf353d93b5f2b 100644 (file)
@@ -116,6 +116,15 @@ module SMESH
   };
   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
   {
@@ -164,6 +173,15 @@ module SMESH
                                        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.
@@ -175,7 +193,7 @@ module SMESH
                                                    in string            theLibName,
                                                    in SMESH_Mesh        theMesh,
                                                    in GEOM::GEOM_Object theGeom,
-                                                   in boolean           byMesh)
+                                                   in HypInitParams     theWay)
       raises ( SALOME::SALOME_Exception );
 
     /*!
index 9a122695a272afed62c2d37ee3bff4dd6333c99e..405c626f78ce7d498ee08fa0d6ba855416491d2e 100644 (file)
 #
 
 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
@@ -29,212 +40,204 @@ SET(SMESH_RESOURCES_FILES
   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})
index b78f7a903e4c854df58309ea969cfa87d783a67c..4af56219a913e9b9c8307ba0a26f7ffee0aeed48 100644 (file)
@@ -76,6 +76,7 @@
     <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"/>
index 14ed93a0c9b0abefee7f9e86d5df842ed55b678a..d70cdd45e452b58ccbbfebcb10353bba9e7672f4 100644 (file)
     <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>
diff --git a/resources/mesh_tree_hypo_import_source_1d.png b/resources/mesh_tree_hypo_import_source_1d.png
new file mode 100644 (file)
index 0000000..8db6260
Binary files /dev/null and b/resources/mesh_tree_hypo_import_source_1d.png differ
diff --git a/resources/mesh_tree_hypo_import_source_2d.png b/resources/mesh_tree_hypo_import_source_2d.png
new file mode 100644 (file)
index 0000000..3d4e1e2
Binary files /dev/null and b/resources/mesh_tree_hypo_import_source_2d.png differ
diff --git a/resources/mesh_tree_hypo_layers_distribution_2d.png b/resources/mesh_tree_hypo_layers_distribution_2d.png
new file mode 100644 (file)
index 0000000..fb5082f
Binary files /dev/null and b/resources/mesh_tree_hypo_layers_distribution_2d.png differ
index 676c68aca662e0b24be7b68fbd17913e2f5a6a8d..fc7ba629b818dc78abcd10be7cda752a37276553 100644 (file)
@@ -142,13 +142,13 @@ namespace {
     //  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 );
@@ -491,7 +491,7 @@ double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P )
   //     }
   // }
   // { // polygons
-    
+
   // }
 
   if( myPrecision >= 0 )
@@ -765,19 +765,9 @@ double AspectRatio::GetValue( long theId )
 {
   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;
 }
 
@@ -850,7 +840,7 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
     //
     // 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
@@ -861,10 +851,10 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
                          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 ] ) ) );
@@ -894,24 +884,24 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
     //
     // 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;
@@ -2755,14 +2745,14 @@ bool FreeFaces::IsSatisfy( long theId )
       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);
 }
@@ -3171,7 +3161,7 @@ namespace
     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 ));
   }
 }
@@ -4272,6 +4262,7 @@ private:
   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);
@@ -4593,7 +4584,7 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node,
         {
           isNodeOut = false;
           if ( okShape )
-            *okShape = myWorkClassifiers[i]->Shape();
+            *okShape = myClassifiers[i].Shape();
           break;
         }
     }
@@ -4631,17 +4622,27 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape,
   {
     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:
index a8ed41c9c2a2f2e6badacd459d33d6ea5cc5ab25..68f17df380dcdfcb178840f1dc1c0c6085288f47 100644 (file)
@@ -266,7 +266,7 @@ Driver_Mesh::Status DriverMED_R_SMESHDS_Mesh::Perform()
             }
 #endif
             if ( !anIsNodeNum )
-              aNodeIds.swap( *(aBallInfo->myConn ));
+              aNodeIds.assign( aBallInfo->myConn->begin(), aBallInfo->myConn->end());
 
             // allocate array of diameters
             vtkIdType maxID = myMesh->MaxElementID() + aNbBalls;
index a4774fe23b778595dce82f295a990c69d2755ce5..30f3ac4a31223b8caaadccd4bba229b0aee15e02 100644 (file)
@@ -34,6 +34,7 @@
 #include "SMDS_MeshNode.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMESHDS_Mesh.hxx"
+#include "MED_Common.hxx"
 
 #include <med.h>
 
index 76d85a0ffde48694888d9ce7093fca8728e01b16..d36b2169a21790c9a18ae91c41134ce3dcc32f5f 100644 (file)
@@ -30,7 +30,7 @@
 #include "SMESH_DriverMED.hxx"
 
 #include "Driver_SMESHDS_Mesh.h"
-#include "MED_Common.hxx"
+//#include "MED_Common.hxx"
 
 #include <string>
 #include <list>
index f5bb08e403491f407ebbe3a2552219694f539301..26596f8b267404e47623f64534258a93894591bf 100644 (file)
@@ -31,7 +31,7 @@
 #include <set>
 #include <map>
 
-#include <hdf5.h>
+#include <med.h>
 
 #ifdef WIN32
 #pragma warning(disable:4099)
@@ -41,11 +41,12 @@ namespace MED
 {
   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;
 
index cae413d78e1b2cb5f488a03d05e2c6e080a8f7f6..f832ad9183e51a4b5845cf73cc8bec2d755f53fa 100644 (file)
@@ -180,12 +180,12 @@ class R4: public R3
 {
   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:  
index e77f9a7d80400502ac1d69880bcbf730062e31ac..515629ca9e754a92bf8074120b51b3e75a30c043 100644 (file)
 
 #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>
 
@@ -216,13 +216,16 @@ void GetFaceParams( vtkCell* theFace, double theNormal[3], double& theSize )
   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 ) +
index f73b4ec762318ead11379e39452dc44de9b5e3a0..86dc634c7a14b0efc58280b2cf77340d738e400e 100644 (file)
@@ -29,7 +29,7 @@
 
 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 );
index 2148a15a52da5c147a2ab99a85f08513daefc240..fbb4f8b00e9b4f6bf972803c47bd31665488d98f 100644 (file)
@@ -706,11 +706,12 @@ double SMDS_VolumeTool::GetSize() const
     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 );
@@ -721,9 +722,12 @@ double SMDS_VolumeTool::GetSize() const
         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 
   {
@@ -1203,11 +1207,13 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub
   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();
index 1e9c1471a1e404d52c46ef6385ab35fb437f9ca9..9c34d8a025127a486a8ed41c8ddfc592c5b3d736 100644 (file)
 
 using namespace std;
 
+// Environment variable separator
+#ifdef WIN32
+  #define env_sep ';'
+#else
+  #define env_sep ':'
+#endif
+
 //=============================================================================
 /*!
  *  Constructor
@@ -984,7 +991,7 @@ std::vector< std::string > SMESH_Gen::GetPluginXMLPaths()
     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
index d1301c452085ad858bf0829673a1845ae1364bac..520e724778660b118eed96874c23ee9da24eb53d 100644 (file)
@@ -95,11 +95,18 @@ public:
    */
   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.
index 7201c528048d72564ee623658c256ffa14ca062b..cd5e4315cd56773fa48ff6a1f6752525ebadff1d 100644 (file)
@@ -176,10 +176,18 @@ SMESH_Mesh::~SMESH_Mesh()
 {
   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
@@ -200,16 +208,6 @@ SMESH_Mesh::~SMESH_Mesh()
   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
@@ -1191,11 +1189,11 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   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;
@@ -1265,8 +1263,9 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   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 );
 }
 
 //=============================================================================
index 5eadb13c25de195710f9ba25553b68322bd5a0b3..7549d243118c6fbdfbc1e9ce0e536cb7ba8d953a 100644 (file)
@@ -44,6 +44,7 @@
 #include <map>
 #include <list>
 #include <vector>
+#include <ostream>
 
 #ifdef WIN32
 #pragma warning(disable:4251) // Warning DLL Interface ...
@@ -337,9 +338,10 @@ class SMESH_EXPORT SMESH_Mesh
 
   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 );
@@ -360,7 +362,7 @@ class SMESH_EXPORT SMESH_Mesh
   bool IsOrderOK( const SMESH_subMesh* smBefore,
                   const SMESH_subMesh* smAfter ) const;
 
-  std::ostream& Dump(ostream & save);
+  std::ostream& Dump(std::ostream & save);
   
 private:
 
index b7c6ef24a01bf335c05e4bc0fe0dd10a48b14879..2104c79201a169a71d80d56986caf70d78b988c9 100644 (file)
@@ -161,8 +161,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn
         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();
         }
       }
     }
@@ -9880,10 +9879,10 @@ SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
   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 ));
index 503de16b043de3485d5bb7f348ba433268761654..8d5dee889bf20bdef3113014d18d5dddab112a5e 100644 (file)
@@ -115,9 +115,12 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
           (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 );
@@ -178,8 +181,11 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
           (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 );
index c5404494a9bb390a259e578a6e29e0d0fe70f7e9..ba08d51011a880d5e2c693412a918a8823586cb7 100644 (file)
@@ -5115,9 +5115,9 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
   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);
@@ -5404,6 +5404,7 @@ void SMESHGUI::createPreferences()
                              "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,
index f7be40487a1ee486f0f779afc512c054f7f432eb..9054ad855a30fb13ff598b7e4ac2b3b34e30630d 100644 (file)
@@ -206,7 +206,7 @@ LightApp_Dialog* SMESHGUI_GroupOnShapeOp::dlg() const
  */
 //================================================================================
 
-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() ) {
@@ -232,7 +232,7 @@ static SMESH::ElementType elementType(GEOM::GEOM_Object_var geom)
         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 );
         }
       }
     }
@@ -241,7 +241,7 @@ static SMESH::ElementType elementType(GEOM::GEOM_Object_var geom)
       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 );
       }
     }
   }
@@ -336,7 +336,7 @@ bool SMESHGUI_GroupOnShapeOp::onApply()
       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;
 
index 63d946b7a82bb186e5f2239d7b503945e68ec89b..f88e9bef52db6fce54bff68f43dca32caecc424e 100644 (file)
@@ -49,6 +49,7 @@ public:
 
     virtual LightApp_Dialog*    dlg() const;  
     static QString              GetDefaultName(const QString& theOperation);
+    static SMESH::ElementType   ElementType(GEOM::GEOM_Object_var geom);
 
 public slots:
 
index 5522e314482121f3d72f3a22183146998255fd73..03767040cd3f67fe8946f37e73e6b1f448e1e06a 100644 (file)
 
 #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>
@@ -147,10 +148,14 @@ void SMESHGUI_GenericHypothesisCreator::editHypothesis( SMESH::SMESH_Hypothesis_
     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 );
@@ -180,10 +185,11 @@ QFrame* SMESHGUI_GenericHypothesisCreator::buildStdFrame()
   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 );
@@ -246,9 +252,12 @@ QFrame* SMESHGUI_GenericHypothesisCreator::buildStdFrame()
       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 );
     }
   }
@@ -331,6 +340,8 @@ void SMESHGUI_GenericHypothesisCreator::onDialogFinished( int result )
   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();
   }
@@ -671,6 +682,14 @@ SMESHGUI_HypothesisDlg::~SMESHGUI_HypothesisDlg()
   delete myCreator;
 }
 
+void SMESHGUI_HypothesisDlg::showEvent(QShowEvent *event)
+{
+  // resize( minimumSizeHint() );
+  // adjustSize();
+
+  QtxDialog::showEvent( event );
+}
+
 void SMESHGUI_HypothesisDlg::setCustomFrame( QFrame* f )
 {
   if( f )
@@ -779,32 +798,44 @@ HypothesisData::HypothesisData( const QString&     theTypeName,
 {
 }
 
-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
@@ -812,23 +843,24 @@ 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;
 }
@@ -858,16 +890,43 @@ bool HypothesesSet::getIsCustom() const
   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";
+}
index e75b8226294d510e1c76b08c16a4e73d322bf343..b50f5f128c5c44e3f641ceba02b6b6fc2b145773 100644 (file)
@@ -92,6 +92,8 @@ protected:
     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;
@@ -158,6 +160,7 @@ public:
   void setHIcon( const QPixmap& );
   void setCustomFrame( QFrame* );
   void setType( const QString& );
+  void showEvent(QShowEvent *event);
 
 protected slots:
   virtual void accept();
@@ -215,32 +218,54 @@ struct HypothesisData
 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;
 };
index eaaad911c314d9fc2eda03b7dd3382a9b3215cb9..2660647d3ed25affa0ab79abb3e6925e728d7598 100644 (file)
@@ -67,6 +67,7 @@
  #define LoadLib( name ) LoadLibrary( name )
  #define GetProc GetProcAddress
  #define UnLoadLib( handle ) FreeLibrary( handle );
+ #define env_sep ";"
 #else // WIN32
  #define LibHandle void*
  #ifdef DYNLOAD_LOCAL
@@ -76,6 +77,7 @@
  #endif // DYNLOAD_LOCAL
  #define GetProc dlsym
  #define UnLoadLib( handle ) dlclose( handle );
+ #define env_sep ":"
 #endif // WIN32
 
 #ifdef _DEBUG_
@@ -197,7 +199,7 @@ namespace SMESH
       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"),
@@ -329,8 +331,7 @@ namespace SMESH
         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 ));
       }
index 904a04b676807a2c5c77cdd8b3f551fa91a860d1..4f8840b2b8488e893c0f53fa1db331212954c9b0 100644 (file)
@@ -116,6 +116,7 @@ namespace SMESH
                                           SMESH::SMESH_Hypothesis_ptr );
 
   typedef std::vector<_PTR(SObject)> SObjectList;
+  SMESHGUI_EXPORT
   SObjectList GetMeshesUsingAlgoOrHypothesis( SMESH::SMESH_Hypothesis_ptr );
 
   SMESHGUI_EXPORT
index a1ee4ec9f25155bd38dbf39655f9181922fe8874..787a3446958e1c9436f05c32d6a9c8bb3c6f07af 100644 (file)
@@ -34,6 +34,7 @@
 #include <QtxToolButton.h>
 
 // Qt includes
+#include <QCheckBox>
 #include <QComboBox>
 #include <QCursor>
 #include <QGridLayout>
@@ -572,9 +573,12 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
   // 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 );
@@ -608,9 +612,10 @@ SMESHGUI_MeshDlg::SMESHGUI_MeshDlg( const bool theToCreate, const bool theIsMesh
   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();
 
@@ -658,7 +663,7 @@ void SMESHGUI_MeshDlg::setTitile( const bool theToCreate, const bool theIsMesh )
   {
     setWindowTitle( tr( theIsMesh ? "EDIT_MESH" : "EDIT_SUBMESH") );
   }
-  
+  myCreateGroupsCheck-> setVisible( theToCreate && theIsMesh );
 }
 
 //================================================================================
@@ -739,8 +744,11 @@ void SMESHGUI_MeshDlg::setHypoSets( const QStringList& theSets )
     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() );
 }
@@ -755,7 +763,7 @@ void SMESHGUI_MeshDlg::setHypoSets( const QStringList& theSets )
 //================================================================================
 void SMESHGUI_MeshDlg::onHypoSetPopup( QAction* a )
 {
-  emit hypoSet( a->text() );
+  emit hypoSet( a->data().toString() );
 }
   
 //================================================================================
@@ -916,3 +924,14 @@ void SMESHGUI_MeshDlg::setCurrentMeshType( const int theIndex )
   else
     myMeshType->setCurrentIndex( 0 );
 }
+
+//================================================================================
+/*!
+ * \brief Return state of "Create all Groups on Geometry" check-box
+ */
+//================================================================================
+
+bool SMESHGUI_MeshDlg::toCreateAllGroups()
+{
+  return myCreateGroupsCheck->isChecked();
+}
index 3dd5b0697881a354d95c491b95af7a68883adebd..1cfb8762f698baf82f03f2dd0cba5b55763a115a 100644 (file)
 #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
@@ -84,6 +85,8 @@ public:
   void                         setCurrentMeshType( const int );
   int                          currentMeshType();
 
+  bool                         toCreateAllGroups();
+
 signals:
   void                         hypoSet( const QString& );
   void                         geomSelectionByMesh( bool );
@@ -101,6 +104,7 @@ private slots:
   QToolButton*                 myHypoSetButton;
   QMenu*                       myGeomPopup;
   QComboBox*                   myMeshType;
+  QCheckBox*                   myCreateGroupsCheck;
 };
 
 /*!
index 36b530a391a342b0a4d0d9af2fece78bb2f98a2f..ed9e8d63c57f7e81e6ccad65349251c2d78494c5 100644 (file)
@@ -27,6 +27,7 @@
 
 #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>
 
 //================================================================================
 /*!
@@ -183,6 +188,8 @@ bool SMESHGUI_MeshOp::onApply()
     SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), aMess );
   }
 
+  myHypoSet = 0;
+
   return aResult;
 }
 
@@ -257,6 +264,7 @@ void SMESHGUI_MeshOp::startOperation()
 
   selectionDone();
 
+  myHypoSet = 0;
   myHasConcurrentSubBefore = false;
   myObjectToSelect.clear();
 }
@@ -286,8 +294,8 @@ void SMESHGUI_MeshOp::commitOperation()
 //================================================================================
 /*!
  * \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
  */
@@ -772,7 +780,7 @@ bool SMESHGUI_MeshOp::isCompatibleToGeometry(HypothesisData* theAlgoData,
 
   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;
@@ -783,7 +791,7 @@ bool SMESHGUI_MeshOp::isCompatibleToGeometry(HypothesisData* theAlgoData,
     toCheckIsApplicableToAll = ( myGeom->GetType() == GEOM_GROUP );
 
   isApplicable = SMESH::IsApplicable( theAlgoData->TypeName, myGeom, toCheckIsApplicableToAll );
-  myHypMapIsApplicable.insert( theAlgoData->Label, isApplicable );
+  myHypMapIsApplicable.insert( theAlgoData->TypeName, isApplicable );
   return isApplicable;
 }
 
@@ -1022,8 +1030,9 @@ void SMESHGUI_MeshOp::existingHyps( const int       theDim,
  */
 //================================================================================
 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();
@@ -1083,18 +1092,48 @@ SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
     }
   }
 
-  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;
 }
 
@@ -1221,25 +1260,14 @@ namespace
 
 //================================================================================
 /*!
- *  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();
@@ -1254,7 +1282,30 @@ void SMESHGUI_MeshOp::createHypothesis(const int theDim,
       }
     }
   }
-  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;
@@ -1655,6 +1706,179 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
   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
@@ -1664,6 +1888,7 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
 void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
 {
   HypothesesSet* aHypoSet = SMESH::GetHypothesesSet(theSetName);
+  myHypoSet = aHypoSet;
   if (!aHypoSet)
     return;
 
@@ -1676,38 +1901,68 @@ void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
     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;
 }
 
@@ -1755,7 +2010,7 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList )
       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() );
@@ -1801,7 +2056,36 @@ bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList )
       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;
 }
 
@@ -1854,7 +2138,7 @@ bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList
   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() )
@@ -2435,6 +2719,12 @@ bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
     }
   }
 
+  if ( aSubMeshVar->_is_nil() )
+  {
+    GEOM::GEOM_Object_var mainGeom = aMesh->GetShapeToMesh();
+    createSubMeshOnInternalEdges( aMesh, mainGeom );
+  }
+
   myHasConcurrentSubBefore =
     checkSubMeshConcurrency( aMesh, aSubMeshVar, /*askUser=*/!myHasConcurrentSubBefore );
 
@@ -2635,24 +2925,40 @@ void SMESHGUI_MeshOp::updateHypoSets()
   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 );
 }
index d93e4a12e19b9f007a21a60028f9d8ef79155628..1a117d53f8e0316e5005a7a5de76a66a66fc2cf6 100644 (file)
@@ -121,6 +121,8 @@ private:
   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);
@@ -137,8 +139,10 @@ private:
   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;
@@ -146,6 +150,7 @@ private:
   void                           updateMeshTypeList();
   void                           updateHypoSets();
   void                           setFilteredAlgoData();
+  QStringList                    getHypoNames();
 
 private:
 
@@ -172,6 +177,9 @@ private:
   bool                           myIgnoreAlgoSelection;
   int                            myDim, myType, myMaxShapeDim;
 
+  HypothesesSet*                 myHypoSet; // applied hypo-set
+  double                         myAverageSize; // entered at hypo-set processing
+
   QString                        myObjectToSelect;
 };
 
index a8564b42e4f4899b1ec358f236d4316ab2217ae3..fe5b138dcb36fd6dbb84a34a71db63488d259c51 100644 (file)
@@ -289,6 +289,29 @@ namespace SMESH
     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
index ec60574937f5c55c40e3cfa52c94c5fd0469d742..8874d1a80e9b6c5a623a0c867aad603013184909 100644 (file)
@@ -219,6 +219,9 @@ SMESHGUI_EXPORT
 
   SMESHGUI_EXPORT
   void UpdateActorsAfterUpdateStudy( SUIT_ViewWindow* wnd );
+
+  SMESHGUI_EXPORT
+  void UpdateActorsAfterUpdateStudy();
 };
 
 #endif // SMESHGUI_VTKUTILS_H
index 823032fca14b18ffee769ab2c08aea27752bcd19..3993633be21d0ae4b6a336a235b94ff14c58fce9 100644 (file)
@@ -201,14 +201,26 @@ bool SMESHGUI_XmlHandler::startElement (const QString&, const QString&,
   {
     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" ||
index 62e0db990851610e4e001bb01d725c89602c5d97..eba5718ed9ebc01b9573f3dcd5cf4ee7920f0dd1 100644 (file)
@@ -4677,6 +4677,10 @@ Please, create VTK viewer and try again</translation>
         <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>
@@ -6520,7 +6524,7 @@ Please specify them and try again</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>
@@ -6534,6 +6538,10 @@ Please specify them and try again</translation>
         <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>
@@ -8498,4 +8506,11 @@ red in the Object Browser.</translation>
         <translation>Option value</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_GenericHypothesisCreator</name>
+    <message>
+        <source>AverageLengthForHypoSet</source>
+        <translation>Mean Size</translation>
+    </message>
+</context>
 </TS>
index 23f5a8d891603504d7e0f25282aed8177d435598..f3ecad3be0df769660dea82a3020b3ac49961beb 100644 (file)
@@ -53,7 +53,7 @@
     </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&apos;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&apos;é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>
@@ -1803,7 +1803,7 @@ Voulez-vous continuer ?</translation>
     </message>
     <message>
         <source>SMESH_EXPORT_MED_VERSION_COLLISION</source>
-        <translation>La version MED du fichier &quot;%1&quot; n&apos;est pas connue 
+        <translation>La version MED du fichier &quot;%1&quot; n&apos;est pas connue
 ou ne correspond pas à la version choisie.
 Ecraser le fichier ?</translation>
     </message>
@@ -1855,8 +1855,7 @@ Voulez-vous continuer ?</translation>
     <message>
         <source>SMESH_FILE_EXISTS</source>
         <translation>Le fichier &quot;%1&quot; 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>
@@ -3154,7 +3153,7 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
     </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>
@@ -3846,7 +3845,7 @@ Utilisez le menu &quot;Visualiser une entité&quot; pour les afficher.
     </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>
@@ -4603,6 +4602,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</translation>
         <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>
@@ -4615,6 +4618,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</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>
@@ -4703,6 +4710,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</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>
@@ -4967,7 +4978,7 @@ Ouvrez une fenêtre VTK et essayez de nouveau</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>
@@ -5410,7 +5421,7 @@ Choisissez un groupe et essayez de nouveau</translation>
     </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>
@@ -5434,7 +5445,7 @@ Choisissez un groupe et essayez de nouveau</translation>
     </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>
@@ -5442,7 +5453,7 @@ Choisissez un groupe et essayez de nouveau</translation>
     </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>
@@ -5536,7 +5547,7 @@ Choisissez un groupe et essayez de nouveau</translation>
     <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>
@@ -5880,7 +5891,7 @@ Vérifiez la validité des informations données</translation>
     </message>
     <message>
         <source>NUMBEROFNODESINELEMENT</source>
-        <translation>Nombre de noeuds dans l&apos;élément</translation>
+        <translation>Nombre de nœuds dans l&apos;élément</translation>
     </message>
     <message>
         <source>COPY_FROM</source>
@@ -6448,7 +6459,7 @@ Indiquez-les et essayez de nouveau</translation>
     </message>
     <message>
         <source>HYPOTHESES_SETS</source>
-        <translation>Attribuer un jeu d&apos;hypothèses</translation>
+        <translation>Définir des hypothèses automatiques</translation>
     </message>
     <message>
         <source>MESH</source>
@@ -6462,6 +6473,34 @@ Indiquez-les et essayez de nouveau</translation>
         <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>
@@ -6524,7 +6563,7 @@ Spécifiez-le et essayez de nouveau</translation>
     </message>
     <message>
         <source>MT_HEXAHEDRAL</source>
-        <translation>Hexahèdre</translation>
+        <translation>Hexaèdre</translation>
     </message>
     <message>
         <source>MT_TETRAHEDRAL</source>
@@ -6555,7 +6594,7 @@ Sélectionnez un maillage ou un sous-maillage et essayez de nouveau</translation
     </message>
     <message>
         <source>CONCURRENT_SUBMESH_APPEARS</source>
-        <translation> 
+        <translation>
 L&apos;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&apos;est pas défini.
@@ -6587,7 +6626,7 @@ Il est probable que le fichier est corrompu ou contient un autre type de motif</
     </message>
     <message>
         <source>ERROR_OF_OPENING</source>
-        <translation>Il est impossible d&apos;ouvrir le fichier. 
+        <translation>Il est impossible d&apos;ouvrir le fichier.
 Vérifiez s&apos;il existe et si vous avez l&apos;autorisation</translation>
     </message>
     <message>
@@ -6637,7 +6676,7 @@ Il est impossible de lire les coordonnées des points dans le fichier</translati
     </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>
@@ -8143,7 +8182,7 @@ en raison de leurs types incompatibles:
     <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>
@@ -8399,4 +8438,11 @@ with red in the Object Browser.</translation>
         <translation>Valeur de l'option'</translation>
     </message>
 </context>
+<context>
+    <name>SMESHGUI_GenericHypothesisCreator</name>
+    <message>
+        <source>AverageLengthForHypoSet</source>
+        <translation>Taille moyenne</translation>
+    </message>
+</context>
 </TS>
index e2a4a99b6eedbddc9f205e4b2823178d1ee8d421..92bbc6e3b54ddeee29a3fedc0e9452ead6c97bca 100644 (file)
@@ -225,11 +225,8 @@ const BRepMesh_Triangle* SMESH_Delaunay::FindTriangle( const gp_XY&
     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 )
@@ -252,7 +249,9 @@ const BRepMesh_Triangle* SMESH_Delaunay::FindTriangle( const gp_XY&
       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;
       }
@@ -388,5 +387,5 @@ void SMESH_Delaunay::ToPython() const
   file.remove();
   file.openForWriting();
   file.write( text.c_str(), text.size() );
-  cout << "exec(open('" << fileName << "', 'rb').read())";
+  std::cout << "exec(open('" << fileName << "', 'rb').read())";
 }
index e274c7728dc70554614ac8bebfb962d1b3128f43..9bb707929b50d852d27f1949fdb068a5ee77f8c8 100644 (file)
@@ -23,6 +23,7 @@ INCLUDE_DIRECTORIES(
   ${OMNIORB_INCLUDE_DIR}
   ${OpenCASCADE_INCLUDE_DIR}
   ${HDF5_INCLUDE_DIRS}
+  ${MEDFILE_INCLUDE_DIRS}
   ${VTK_INCLUDE_DIRS}
   ${Boost_INCLUDE_DIRS}
   ${KERNEL_INCLUDE_DIRS}
index 10398d8fcb7721847bebd7eedbd78cebd8b4981c..689f498618521b4240972cf51e5ad9dd3c505a48 100644 (file)
@@ -1834,7 +1834,7 @@ _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId):
 
 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)
@@ -1987,7 +1987,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
       // 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))
@@ -3165,8 +3165,7 @@ void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd )
       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;
index 6117d454742e8c3c4bb6ef369673f683e770e2f8..ac0b696007a2f4329b6ecf2b404d421475d5c3e9 100644 (file)
@@ -829,6 +829,43 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
   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
@@ -844,14 +881,16 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
 //================================================================================
 
 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 ) )
@@ -906,17 +945,24 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
     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 );
   }
index 0cb93fbb95f2a1b240eb9f948d7cac02f1e7248d..b288eec86d3784c4dd7dbff3d78cfdd83b57b818 100644 (file)
@@ -170,12 +170,19 @@ public:
                                                 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 );
 
   /*
@@ -530,6 +537,7 @@ public:
                                       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);
index 0b258bf08fa08308ff106b98f40d3980a4fe6f83..580663d464707729b7e045d832c8e7ee0444fd2f 100644 (file)
@@ -840,21 +840,25 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishGroup (SMESH::SMESH_Mesh_ptr  theMesh,
         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() );
@@ -874,14 +878,14 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::PublishGroup (SMESH::SMESH_Mesh_ptr  theMesh,
 
 //=======================================================================
 //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())
@@ -1031,6 +1035,28 @@ void SMESH_Gen_i::highLightInvalid( SALOMEDS::SObject_ptr theSObject, bool isInv
   }
 }
 
+//=======================================================================
+//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  : 
index a2dac404ce7426600a13c05db7fedacbe5b4e726..a7a7e45eb69e223adbe6b7a7f2193139f2efcbe8 100644 (file)
@@ -171,13 +171,13 @@ char* SMESH_GroupBase_i::GetName()
 {
   ::SMESH_Group* aGroup = GetSmeshGroup();
   if (aGroup)
-    return CORBA::string_dup (aGroup->GetName());
+    return CORBA::string_dup( aGroup->GetName() );
   return CORBA::string_dup( "NO_NAME" );
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
index 421a0babf9d09ee7b3781f9222453746a5e7ec5d..b813fc37b4bd10dce08a26bf9db49edab06af1f1 100644 (file)
@@ -1390,8 +1390,11 @@ void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
   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 );
@@ -1434,14 +1437,11 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
                  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 );
index 2b831f8c9d34e59a239517787b723be32316dfa5..d4e396cbdfacd0556715d974ba7d7b1d655a9077 100644 (file)
@@ -114,6 +114,7 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
   _impl          = NULL;
   _gen_i         = gen_i;
   _id            = _idGenerator++;
+  _nbInvalidHypos= -1;
   _editor        = NULL;
   _previewEditor = NULL;
   _preMeshInfo   = NULL;
@@ -689,6 +690,8 @@ SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
   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();
@@ -697,7 +700,10 @@ SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
   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 );
 
@@ -3234,40 +3240,55 @@ namespace
     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;
   }
 }
 
index 40e97e4c3adb854c8c1fe979bcb15410e1a89b5f..0d79c015d74c7a4ec1e912308811e81255ae393c 100644 (file)
@@ -455,11 +455,9 @@ public:
   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
    *
@@ -733,12 +731,13 @@ private:
    */
   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;
index 58701b12364f4d179e4ece3be0b8763e77838e79..275acb0430aaf220fc1791cf56a1e0af42b2e892 100644 (file)
@@ -479,7 +479,7 @@ bool SMESH_PreMeshInfo::readMeshInfo()
   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);
index 0687ddc0c76eff149ef0c6f064d9b065b4ff7886..6b90f80f5fe3a82ee9e6ba451b3310d5e3ae8d2b 100644 (file)
@@ -668,7 +668,7 @@ namespace SMESH
   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
   }
 
@@ -696,7 +696,7 @@ namespace SMESH
 //function : DumpPython
 //purpose  :
 //=======================================================================
-Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Boolean  isPublished,
+Engines::TMPFile* SMESH_Gen_i::DumpPythonCORBA::Boolean  isPublished,
                                            CORBA::Boolean  isMultiFile,
                                            CORBA::Boolean& isValidScript)
 {
index 858820238ad520dc15547e89a0b6bbd581b030d3..8c8a4ced9ed58443984c7a396207ef72a193ecf8 100644 (file)
@@ -75,6 +75,11 @@ POLYGON     = "PolygonPerFace_2D"
 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))
@@ -174,10 +179,11 @@ class StdMeshersBuilder_Segment(Mesh_Algorithm):
             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() )
@@ -1670,6 +1676,44 @@ class StdMeshersBuilder_PolygonPerFace(Mesh_Algorithm):
 
     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.
 
index 696d4f3cc2155efd86426cfec444e62d2443b398..2a6238966f401e92c36ec8af83f72b22cd9b9e5f 100644 (file)
@@ -1239,6 +1239,27 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
 
         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.
@@ -2608,7 +2629,7 @@ class Mesh(metaclass = MeshMeta):
         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
@@ -7597,7 +7618,7 @@ class genObjUnRegister:
             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
     """
index be5552d8ecb640dd0d0d4bf47ccc0caad8352a7b..e90d64aa659d9f243dca91ceed338e6bdcdd04d0 100644 (file)
@@ -290,7 +290,8 @@ class Mesh_Algorithm:
         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:
@@ -319,8 +320,17 @@ class Mesh_Algorithm:
                         - 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():
@@ -342,11 +352,12 @@ class Mesh_Algorithm:
         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:
@@ -361,6 +372,15 @@ class Mesh_Algorithm:
                         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):
@@ -383,6 +403,7 @@ class Mesh_Algorithm:
         hyp.SetNumberLayers(numberOfLayers)
         hyp.SetStretchFactor(stretchFactor)
         hyp.SetEdges(edges, isEdgesToIgnore)
+        hyp.SetGroupName( groupName )
         self.mesh.AddHypothesis( hyp, self.geom )
         return hyp
 
index dfad28a865eb5ac0332f018592be1ca607c280c3..df1d952432f7598f66c2873971d91fa0162107b4 100644 (file)
@@ -130,6 +130,7 @@ SET(StdMeshers_HEADERS
   StdMeshers_Cartesian_3D.hxx
   StdMeshers_QuadFromMedialAxis_1D2D.hxx
   StdMeshers_PolygonPerFace_2D.hxx
+  StdMeshers_PolyhedronPerSolid_3D.hxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
@@ -195,6 +196,7 @@ SET(StdMeshers_SOURCES
   StdMeshers_Adaptive1D.cxx
   StdMeshers_QuadFromMedialAxis_1D2D.cxx
   StdMeshers_PolygonPerFace_2D.cxx
+  StdMeshers_PolyhedronPerSolid_3D.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
index 21bc0bbb180e147ae57cd93170045406d5d8247e..fe479bb1eb994a56def250c2f04804b4dd69aa2e 100644 (file)
@@ -64,7 +64,10 @@ StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int         h
                                                                    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
@@ -739,6 +742,48 @@ bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
   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
@@ -786,6 +831,10 @@ std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
   for ( int i = 0; i < 3; ++i )
     save << _fixedPoint[i] << " ";
 
+  save << " " << _toConsiderInternalFaces
+       << " " << _toUseThresholdForInternalFaces
+       << " " << _toCreateFaces;
+
   return save;
 }
 
@@ -844,6 +893,12 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
   for ( int i = 0; i < 3 && ok ; ++i )
     ok = static_cast<bool>( load >> _fixedPoint[i]);
 
+  if ( load >> _toConsiderInternalFaces )
+  {
+    load >> _toUseThresholdForInternalFaces;
+    load >> _toCreateFaces;
+  }
+
   return load;
 }
 
index 089d19f46f7b8cd1a008008a1f74d789403ea270..fc8ceff4c92b242a175542b8c8ab2c7c541728d3 100644 (file)
@@ -139,6 +139,25 @@ public:
   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
    */
@@ -171,6 +190,9 @@ public:
 
   double _sizeThreshold;
   bool   _toAddEdges;
+  bool   _toConsiderInternalFaces;
+  bool   _toUseThresholdForInternalFaces;
+  bool   _toCreateFaces;
 };
 
 #endif
index 85a984c309ac5078ab5aa9c4ab15aadada50d6e2..78059016fa05a9b2a150f60182eabaf9dc2906f4 100644 (file)
 //  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>
@@ -89,6 +95,8 @@
 
 #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_
@@ -161,7 +169,7 @@ bool StdMeshers_Cartesian_3D::CheckHypothesis (SMESH_Mesh&          aMesh,
 
 namespace
 {
-  typedef int TGeomID;
+  typedef int TGeomID; // IDs of sub-shapes
 
   //=============================================================================
   // Definitions of internal utils
@@ -170,7 +178,72 @@ namespace
     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; }
   };
   // --------------------------------------------------------------------------
   /*!
@@ -194,6 +267,7 @@ namespace
   struct F_IntersectPoint : public B_IntersectPoint
   {
     double             _paramOnLine;
+    double             _u, _v;
     mutable Transition _transition;
     mutable size_t     _indexOnLine;
 
@@ -207,7 +281,7 @@ namespace
   {
     gp_Pnt  _point;
     double  _uvw[3];
-    TGeomID _shapeID;
+    TGeomID _shapeID; // ID of EDGE or VERTEX
   };
   // --------------------------------------------------------------------------
   /*!
@@ -220,7 +294,9 @@ namespace
     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);
   };
   // --------------------------------------------------------------------------
   /*!
@@ -249,7 +325,7 @@ namespace
     {
       _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;
     }
 
@@ -288,10 +364,18 @@ namespace
 
     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
@@ -308,6 +392,43 @@ namespace
 
     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,
@@ -317,6 +438,49 @@ namespace
     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
    */
@@ -336,7 +500,7 @@ namespace
     {
       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 );
@@ -368,7 +532,7 @@ namespace
   {
     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;
@@ -406,36 +570,31 @@ namespace
     // --------------------------------------------------------------------------------
     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
       {
@@ -448,7 +607,7 @@ namespace
       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;
@@ -460,6 +619,27 @@ namespace
           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
@@ -469,7 +649,7 @@ namespace
       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
@@ -541,6 +721,43 @@ namespace
       }
     };
     // --------------------------------------------------------------------------------
+    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
@@ -573,14 +790,37 @@ namespace
     // --------------------------------------------------------------------------------
     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
@@ -602,26 +842,33 @@ namespace
     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);
@@ -629,7 +876,7 @@ namespace
                          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 );
@@ -640,11 +887,22 @@ namespace
                           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();
@@ -660,8 +918,16 @@ namespace
           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
@@ -756,29 +1022,72 @@ namespace
   }
   //================================================================================
   /*
-   * 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;
   }
   //================================================================================
   /*
@@ -824,6 +1133,35 @@ namespace
     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
    */
@@ -928,6 +1266,290 @@ namespace
       }
     }
   }
+  //================================================================================
+  /*
+   * 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
@@ -945,10 +1567,13 @@ namespace
   {
     // 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 );
@@ -968,26 +1593,30 @@ namespace
         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
@@ -998,24 +1627,21 @@ namespace
           // 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 );
@@ -1029,7 +1655,7 @@ namespace
         }
         // 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;
       }
     }
 
@@ -1040,13 +1666,19 @@ namespace
         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 ]);
           }
         }
 
@@ -1174,6 +1806,17 @@ namespace
           _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;
   }
   //================================================================================
   /*
@@ -1194,6 +1837,8 @@ namespace
     {
       F_IntersectPoint p;
       p._paramOnLine = _w;
+      p._u           = _u;
+      p._v           = _v;
       p._transition  = _transition;
       _intPoints.push_back( p );
     }
@@ -1428,8 +2073,8 @@ namespace
   /*!
    * \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;
 
@@ -1491,11 +2136,12 @@ namespace
   /*!
    * \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];
 
@@ -1520,23 +2166,198 @@ namespace
         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 );
     }
@@ -1547,25 +2368,28 @@ namespace
     _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];
@@ -1590,15 +2414,21 @@ namespace
           }
           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 )
@@ -1609,12 +2439,20 @@ namespace
       }
 
       // 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 ) {
@@ -1639,10 +2477,16 @@ namespace
             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 ];
@@ -1652,8 +2496,11 @@ namespace
               }
               else {
                 quad._eIntNodes.push_back( & _intNodes.back() );
+                newNodeUsed = true;
               }
             }
+            if ( !newNodeUsed )
+              _intNodes.pop_back();
           }
           break;
         }
@@ -1685,7 +2532,7 @@ namespace
         } // 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 ) {
@@ -1699,6 +2546,7 @@ namespace
         }
       } // loop on _eIntPoints
     }
+
     else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbFaceIntNodes == 0
     {
       _Link split;
@@ -1715,40 +2563,76 @@ namespace
         }
       }
     }
+    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
     // --------------------------------
 
@@ -1778,14 +2662,13 @@ namespace
       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
 
@@ -1815,16 +2698,20 @@ namespace
           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 )
@@ -1940,7 +2827,7 @@ namespace
           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
@@ -2106,7 +2993,8 @@ namespace
                 _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 );
             }
@@ -2130,7 +3018,7 @@ namespace
 
       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 )
       {
@@ -2251,15 +3139,16 @@ namespace
       } // 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;
@@ -2292,6 +3181,9 @@ namespace
           _volumeDefs._nodes.push_back( _polygons[ iF ]._links[ iL ].FirstNode() );
       }
     }
+    _volumeDefs._solidID = solid->ID();
+
+    return !_volumeDefs._nodes.empty();
   }
   //================================================================================
   /*!
@@ -2302,23 +3194,18 @@ namespace
   {
     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() ];
@@ -2327,23 +3214,15 @@ namespace
         {
           // 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;
@@ -2357,22 +3236,24 @@ namespace
     // 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() ))
@@ -2383,18 +3264,31 @@ namespace
                            _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 );
       }
     }
@@ -2406,16 +3300,30 @@ namespace
                         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 ];
@@ -2456,25 +3364,36 @@ namespace
     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 ];
@@ -2501,7 +3420,7 @@ namespace
         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;
@@ -2510,10 +3429,12 @@ namespace
         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 )
@@ -2541,15 +3462,17 @@ namespace
               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;
@@ -2560,62 +3483,292 @@ namespace
         // 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 )
@@ -2683,7 +3836,7 @@ namespace
   /*!
    * \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[] )
   {
@@ -2697,16 +3850,17 @@ namespace
     };
     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;
@@ -2798,8 +3952,10 @@ namespace
   /*!
    * \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,
@@ -2808,19 +3964,16 @@ namespace
                                     _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;
@@ -2841,7 +3994,7 @@ namespace
     }
 
     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;
@@ -2862,7 +4015,7 @@ namespace
         break;
       n = 0;
     }
-    if ( n && n != stopNode)
+    if ( n && n != stopNode )
     {
       if ( chn.empty() )
         chn.push_back( pn2 );
@@ -2870,17 +4023,29 @@ namespace
       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 ];
@@ -2894,16 +4059,16 @@ namespace
 
     // 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();
@@ -2916,10 +4081,9 @@ namespace
     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 )       
@@ -2940,7 +4104,7 @@ namespace
                                    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 );
@@ -2980,7 +4144,7 @@ namespace
         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);
@@ -2995,8 +4159,8 @@ namespace
           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 ))
             {
@@ -3015,7 +4179,7 @@ namespace
     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;
@@ -3063,14 +4227,14 @@ namespace
     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;
@@ -3092,46 +4256,81 @@ namespace
   /*!
    * \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;
@@ -3182,7 +4381,8 @@ namespace
         if ( firstIntPnt )
         {
           hasLinks = true;
-          allLinksOut = ( firstIntPnt->_transition == Trans_OUT );
+          allLinksOut = ( firstIntPnt->_transition == Trans_OUT &&
+                          !_grid->IsShared( firstIntPnt->_faceIDs[0] ));
         }
       }
       if ( hasLinks && allLinksOut )
@@ -3191,12 +4391,68 @@ namespace
     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 )
     {
@@ -3217,7 +4473,7 @@ namespace
 
     double initVolume = _sideLength[0] * _sideLength[1] * _sideLength[2];
 
-    return volume > initVolume / _sizeThreshold;
+    return volume > initVolume / _grid->_sizeThreshold;
   }
   //================================================================================
   /*!
@@ -3263,7 +4519,7 @@ namespace
         }
     }
     if ( nbN == 8 )
-      _volumeDefs.set( &nodes[0], 8 );
+      _volumeDefs.Set( &nodes[0], 8 );
 
     return nbN == 8;
   }
@@ -3295,7 +4551,7 @@ namespace
       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;
       }
 
@@ -3340,7 +4596,7 @@ namespace
         }
     }
     if ( nbN == 6 )
-      _volumeDefs.set( &nodes[0], 6 );
+      _volumeDefs.Set( &nodes[0], 6 );
 
     return ( nbN == 6 );
   }
@@ -3375,7 +4631,7 @@ namespace
       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;
       }
 
@@ -3408,6 +4664,467 @@ namespace
             ( _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();
+  }
 
   //================================================================================
   /*!
@@ -3524,50 +5241,46 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
   _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 );
 
@@ -3581,7 +5294,7 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
       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 );
@@ -3603,33 +5316,36 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
     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
@@ -3637,9 +5353,9 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
     }
 
     // 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 )
       {
@@ -3648,19 +5364,25 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh &         theMesh,
         {
           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;
@@ -3795,4 +5517,3 @@ void StdMeshers_Cartesian_3D::setSubmeshesComputed(SMESH_Mesh&         theMesh,
   for ( TopExp_Explorer soExp( theShape, TopAbs_SOLID ); soExp.More(); soExp.Next() )
     _EventListener::setAlwaysComputed( true, theMesh.GetSubMesh( soExp.Current() ));
 }
-
index 455af191ce838ccdf96dacacb25a97bb191a9ba6..6c6d4c2bedea7e66064297b9546acd6899b052b4 100644 (file)
@@ -665,7 +665,7 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
       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
 
index 8de8c92d21bd4f21daebf27372a4a2051febe0af..e8d9eaea6f3ccfd79e91295471e8de35cf941aca 100644 (file)
@@ -114,7 +114,7 @@ double StdMeshers_Geometric1D::GetCommonRatio() const
  */
 //=============================================================================
 
-ostream & StdMeshers_Geometric1D::SaveTo(ostream & save)
+std::ostream & StdMeshers_Geometric1D::SaveTo(std::ostream & save)
 {
   save << _begLength << " " << _ratio << " ";
 
@@ -129,7 +129,7 @@ ostream & StdMeshers_Geometric1D::SaveTo(ostream & save)
  */
 //=============================================================================
 
-istream & StdMeshers_Geometric1D::LoadFrom(istream & load)
+std::istream & StdMeshers_Geometric1D::LoadFrom(std::istream & load)
 {
   bool isOK = true;
   isOK = static_cast<bool>(load >> _begLength);
index c8d203d12eb54c9444e8d2da5d287b3af0a4ee29..76afc6a0c6b8c3b3678a26e0a29e9b0ac3a576b9 100644 (file)
 
 #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,
diff --git a/src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.cxx b/src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.cxx
new file mode 100644 (file)
index 0000000..6695eea
--- /dev/null
@@ -0,0 +1,618 @@
+// 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;
+}
diff --git a/src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.hxx b/src/StdMeshers/StdMeshers_PolyhedronPerSolid_3D.hxx
new file mode 100644 (file)
index 0000000..f6296aa
--- /dev/null
@@ -0,0 +1,58 @@
+// 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
index 12619c94fdbbc634de629eb3af705f42bab8e7f3..45e1c25b62b66b5ef6291b2e8a6b681c87c1defd 100644 (file)
@@ -974,6 +974,8 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh &     theMesh,
       an = eltSize;
       eltSize *= q;
       ++nbParams;
+      if ( q < 1. && eltSize < 1e-100 )
+        return error("Too small common ratio causes too many segments");
     }
     if ( nbParams > 1 )
     {
index 31669f15c2c440288befa861a784fe88bd430dd2..270330be4ed87c7136859482f8130fbd0b2191ac 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "StdMeshers_ViscousLayers.hxx"
 
+#include "ObjectPool.hxx"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_FacePosition.hxx"
@@ -33,6 +34,7 @@
 #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>
@@ -372,22 +375,7 @@ namespace VISCOUS_3D
     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; }
   };
@@ -583,6 +571,7 @@ namespace VISCOUS_3D
     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;
     }
@@ -623,12 +612,16 @@ namespace VISCOUS_3D
         _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; }
@@ -637,9 +630,19 @@ namespace VISCOUS_3D
     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;
   };
 
   //--------------------------------------------------------------------------------
@@ -684,6 +687,7 @@ namespace VISCOUS_3D
     _SolidData&      GetData() const { return *_data; }
 
     _EdgesOnShape(): _shapeID(-1), _subMesh(0), _toSmooth(false), _edgeSmoother(0) {}
+    ~_EdgesOnShape();
   };
 
   //--------------------------------------------------------------------------------
@@ -743,6 +747,7 @@ namespace VISCOUS_3D
     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
@@ -759,7 +764,7 @@ namespace VISCOUS_3D
     // _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
@@ -786,8 +791,8 @@ namespace VISCOUS_3D
 
     _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 );
@@ -888,6 +893,7 @@ namespace VISCOUS_3D
                             const double   refSign );
   };
   struct PyDump;
+  struct Periodicity;
   //--------------------------------------------------------------------------------
   /*!
    * \brief Builder of viscous layers
@@ -914,10 +920,12 @@ namespace VISCOUS_3D
     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,
@@ -1000,15 +1008,16 @@ namespace VISCOUS_3D
     // 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;
   };
   //--------------------------------------------------------------------------------
   /*!
@@ -1212,6 +1221,27 @@ namespace VISCOUS_3D
             ( 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
 
 
@@ -1222,7 +1252,8 @@ 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
@@ -1254,6 +1285,15 @@ void StdMeshers_ViscousLayers::SetMethod( ExtrusionMethod method )
   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,
@@ -1308,6 +1348,9 @@ std::ostream & StdMeshers_ViscousLayers::SaveTo(std::ostream & save)
     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)
@@ -1320,6 +1363,13 @@ 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
@@ -1353,6 +1403,36 @@ bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
     ( 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
 //================================================================================
 
@@ -1873,6 +1953,8 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh&         theMesh,
 {
   _mesh = & theMesh;
 
+  _Factory factory;
+
   // check if proxy mesh already computed
   TopExp_Explorer exp( theShape, TopAbs_SOLID );
   if ( !exp.More() )
@@ -1884,20 +1966,30 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh&         theMesh,
   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
@@ -1920,6 +2012,8 @@ SMESH_ComputeErrorPtr _ViscousBuilder::Compute(SMESH_Mesh&         theMesh,
 
     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 );
@@ -2146,7 +2240,7 @@ bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
     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 ))
@@ -2182,7 +2276,7 @@ bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
         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())
@@ -2262,7 +2356,7 @@ bool _ViscousBuilder::findFacesWithLayers(const bool onlyWith)
     }
   }
 
-  // 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 )
@@ -2487,17 +2581,6 @@ void _ViscousBuilder::getIgnoreFaces(const TopoDS_Shape&             solid,
 
 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();
@@ -2521,6 +2604,8 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
 
   dumpFunction(SMESH_Comment("makeLayers_")<<data._index);
 
+  vector< _EdgesOnShape >& edgesByGeom = data._edgesOnShape;
+
   data._stepSize = Precision::Infinite();
   data._stepSizeNodes[0] = 0;
 
@@ -2531,34 +2616,19 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
   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() )
@@ -2596,7 +2666,7 @@ bool _ViscousBuilder::makeLayer(_SolidData& data)
         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 );
@@ -3249,6 +3319,39 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data )
   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
@@ -3383,6 +3486,16 @@ bool _EdgesOnShape::GetNormal( const SMDS_MeshElement* face, gp_Vec& norm )
   return ok;
 }
 
+//================================================================================
+/*!
+ * \brief EdgesOnShape destructor
+ */
+//================================================================================
+
+_EdgesOnShape::~_EdgesOnShape()
+{
+  delete _edgeSmoother;
+}
 
 //================================================================================
 /*!
@@ -3397,12 +3510,13 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
 {
   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
@@ -3675,7 +3789,7 @@ bool _ViscousBuilder::setEdgeData(_LayerEdge&         edge,
   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
   }
 
@@ -4134,6 +4248,34 @@ bool _ViscousBuilder::findNeiborsOnEdge(const _LayerEdge*     edge,
   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
@@ -4161,7 +4303,6 @@ void _LayerEdge::SetDataByNeighbors( const SMDS_MeshNode* n1,
   _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()
@@ -4205,8 +4346,11 @@ gp_XYZ _LayerEdge::Copy( _LayerEdge&         other,
   _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 )
@@ -6927,7 +7071,7 @@ void _ViscousBuilder::findEdgesToUpdateNormalNearConvexFace( _ConvexFace &
       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;
       }
@@ -8269,7 +8413,7 @@ void _LayerEdge::MoveNearConcaVer( const _EdgesOnShape*    eov,
     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;
@@ -10141,6 +10285,11 @@ bool _ViscousBuilder::refine(_SolidData& data)
     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();
@@ -10171,14 +10320,20 @@ bool _ViscousBuilder::refine(_SolidData& data)
       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 )
         {
@@ -10191,16 +10346,18 @@ bool _ViscousBuilder::refine(_SolidData& data)
             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
@@ -10209,10 +10366,13 @@ bool _ViscousBuilder::refine(_SolidData& data)
       {
         // 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 )
         {
@@ -10231,9 +10391,9 @@ bool _ViscousBuilder::refine(_SolidData& data)
             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 );
           }
@@ -10241,15 +10401,15 @@ bool _ViscousBuilder::refine(_SolidData& data)
 
           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 );
           }
           }
@@ -10260,6 +10420,11 @@ bool _ViscousBuilder::refine(_SolidData& data)
         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
 
@@ -10279,6 +10444,440 @@ bool _ViscousBuilder::refine(_SolidData& data)
   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
@@ -10295,11 +10894,11 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
     _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 ))
@@ -10358,15 +10957,24 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
 
     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() )
@@ -10412,11 +11020,12 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
           }
         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 );
+          }
       }
     }
 
@@ -10488,13 +11097,16 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
         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 )
         {
@@ -10509,7 +11121,7 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
     }
 
     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 ) {
@@ -10528,24 +11140,24 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
     // 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();
@@ -10636,7 +11248,7 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
       //   }
       // }
 
-    } // while ( shrinked )
+    } // while ( shrunk )
 
     if ( !errMsg.empty() ) // Try to re-compute the shrink FACE
     {
@@ -10800,7 +11412,7 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
         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;
@@ -10844,7 +11456,7 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
   } // 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 )
@@ -11408,34 +12020,6 @@ gp_XY _SmoothNode::computeAngularPos(vector<gp_XY>& uv,
   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
@@ -11601,7 +12185,7 @@ void _Shrinker1D::RestoreParams()
 
 //================================================================================
 /*!
- * \brief Replace source nodes by target nodes in shrinked mesh edges
+ * \brief Replace source nodes by target nodes in shrunk mesh edges
  */
 //================================================================================
 
index 142f35b01fe35d7dbf19f96ead9da20ef277a907..7d7e362fd8863b8650647b28a49c29973b5ac756 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <vector>
 
+class SMDS_MeshGroup;
+
 /*!
  * \brief Hypothesis defining parameters of viscous layers
  */
@@ -73,6 +75,13 @@ public:
   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,
@@ -116,6 +125,7 @@ public:
   double           _thickness;
   double           _stretchFactor;
   ExtrusionMethod  _method;
+  std::string      _groupName;
 };
 
 class SMESH_subMesh;
index 6248200a732fdfa3beafa93ab7f166942a85422d..a0da0d5270d76d836e93bbb17ebab63ac0ced722 100644 (file)
@@ -2402,6 +2402,17 @@ bool _ViscousBuilder2D::refine()
       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 )
     {
@@ -2413,15 +2424,22 @@ bool _ViscousBuilder2D::refine()
       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
index 0b8834730210d149cae6e2dee75be59630530fb8..4393778db75d70e17609f5c11a8303ce44caeb7c 100644 (file)
@@ -82,6 +82,7 @@ SET(_moc_HEADERS
   StdMeshersGUI_CartesianParamCreator.h
   StdMeshersGUI_RadioButtonsGrpWdg.h
   StdMeshersGUI_PropagationHelperWdg.h
+  StdMeshersGUI_NameCheckableGrpWdg.h
 )
 
 IF(SALOME_USE_PLOT2DVIEWER)
@@ -117,6 +118,7 @@ SET(_other_SOURCES
   StdMeshersGUI_CartesianParamCreator.cxx
   StdMeshersGUI_RadioButtonsGrpWdg.cxx
   StdMeshersGUI_PropagationHelperWdg.cxx
+  StdMeshersGUI_NameCheckableGrpWdg.cxx
 )
 
 IF(SALOME_USE_PLOT2DVIEWER)
index b70d050910147d02330c004a438172c35986d354..f1271c105c6428878aed755641743123af900d68 100644 (file)
@@ -204,8 +204,8 @@ namespace StdMeshersGUI
     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 );
@@ -821,6 +821,15 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
   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 );
@@ -924,6 +933,8 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
   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&)),
@@ -999,6 +1010,9 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
     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 )
@@ -1086,6 +1100,9 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
     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 )
index 9ae66b9d82a2cc819b557f27fa6705c2af5e9576..f72b1e5314e3ccf2605d45dc5d5b867313ab5a09 100644 (file)
@@ -152,6 +152,9 @@ private:
   QLineEdit*                  myName;
   SMESHGUI_SpinBox*           myThreshold;
   QCheckBox*                  myAddEdges;
+  QCheckBox*                  myCreateFaces;
+  QCheckBox*                  myConsiderInternalFaces;
+  QCheckBox*                  myUseThresholdForInternalFaces;
 
   StdMeshersGUI::GridAxisTab* myAxisTabs[3];
   QGroupBox*                  myFixedPointGrp;
diff --git a/src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.cxx
new file mode 100644 (file)
index 0000000..5ea084b
--- /dev/null
@@ -0,0 +1,68 @@
+// 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() );
+}
diff --git a/src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.h b/src/StdMeshersGUI/StdMeshersGUI_NameCheckableGrpWdg.h
new file mode 100644 (file)
index 0000000..334df51
--- /dev/null
@@ -0,0 +1,53 @@
+// 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
index f52914bd478c06fd1927411dbcb6d1f9fad78bf5..8dc3f134922ea00e7882f0219d7062fb6b79342b 100644 (file)
@@ -39,6 +39,7 @@
 #include "StdMeshersGUI_PropagationHelperWdg.h"
 #include "StdMeshersGUI_QuadrangleParamWdg.h"
 #include "StdMeshersGUI_RadioButtonsGrpWdg.h"
+#include "StdMeshersGUI_NameCheckableGrpWdg.h"
 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
 
 #include <SALOMEDSClient_Study.hxx>
@@ -377,10 +378,51 @@ namespace {
   }
 }
 
+//================================================================================
+/*!
+ * \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
  */
 //================================================================================
 
@@ -728,6 +770,15 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
       {
         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" )
     {
@@ -746,6 +797,15 @@ QString StdMeshersGUI_StdHypothesisCreator::storeParams() const
       {
         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" )
     // {
@@ -841,7 +901,7 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
     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() ) );
     }
@@ -1250,6 +1310,19 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
       }
       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" )
   {
@@ -1308,6 +1381,19 @@ bool StdMeshersGUI_StdHypothesisCreator::stdParams( ListOfStdParams& p ) const
       }
       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;
@@ -1574,6 +1660,10 @@ bool StdMeshersGUI_StdHypothesisCreator::getParamFromCustomWidget( StdParam & pa
     param.myValue = w->checkedId();
     return true;
   }
+  if ( widget->inherits( "StdMeshersGUI_NameCheckableGrpWdg" ))
+  {
+    return true;
+  }
   return false;
 }
 
index 7e382ed3d51c4df4fcda1f3bf001b779547a54f4..0e984e4d27638eb98b02b1a06f50df6476930118 100644 (file)
@@ -66,6 +66,9 @@ protected:
   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;
   
 
 
index 36489516b219979ff3ed162762627cb5baf1851e..681bf7bed80000aadedbc890d174e1040688ddf9 100644 (file)
             <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>
index 351aed8f48fb3b3855b47e5536c40840a76c073c..0c0509f1996954e988f6f0a0e7697b1925d59f16 100644 (file)
@@ -59,6 +59,14 @@ this one for this mesh/sub-mesh.</translation>
         <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>
@@ -572,6 +580,18 @@ this one for this mesh/sub-mesh.</translation>
         <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>
index ceed790b4cb1e5195e0af9cfccddf506c1e22c7b..4b1c390bad06c391ab4d9d11ff38b9611157fb72 100644 (file)
@@ -119,6 +119,7 @@ SET(StdMeshersEngine_HEADERS
   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)
@@ -174,6 +175,7 @@ SET(StdMeshersEngine_SOURCES
   StdMeshers_Cartesian_3D_i.cxx
   StdMeshers_Adaptive1D_i.cxx 
   StdMeshers_PolygonPerFace_2D_i.cxx
+  StdMeshers_PolyhedronPerSolid_3D_i.cxx
 )
 
 IF(SALOME_SMESH_ENABLE_MEFISTO)
index ec36baf67f39d58c8aeaa5d5195f27895d923d1e..fa1cadfcb99065f6d9efac3c85bc2901b85d0eb3 100644 (file)
@@ -240,6 +240,14 @@ void StdMeshers_CartesianParameters3D_i::SetAxesDirs(const SMESH::DirStruct& xDi
   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);
 
@@ -283,6 +291,11 @@ void StdMeshers_CartesianParameters3D_i::GetAxesDirs(SMESH::DirStruct& xDir,
 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 );
 
@@ -335,6 +348,76 @@ CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetToAddEdges()
   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
index 03dad0cfbc62ccb25f0e44dae045c41d85eeb60c..1b273ce77b845eb6b6945c1ba3cba82269bedef1 100644 (file)
@@ -100,7 +100,7 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
 
 
   /*!
-   * \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
    */
@@ -108,13 +108,32 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
   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,
@@ -122,7 +141,7 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
                               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
diff --git a/src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.cxx b/src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.cxx
new file mode 100644 (file)
index 0000000..94d5648
--- /dev/null
@@ -0,0 +1,57 @@
+// 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()
+{
+}
diff --git a/src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.hxx b/src/StdMeshers_I/StdMeshers_PolyhedronPerSolid_3D_i.hxx
new file mode 100644 (file)
index 0000000..26bdffc
--- /dev/null
@@ -0,0 +1,53 @@
+// 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
index 376f156b0fb6ded28dc1096fb9dae5413a565011..0e03a4b1f97baf4af3d72a839fcedecac0e79211 100644 (file)
@@ -222,6 +222,33 @@ throw ( SALOME::SALOME_Exception )
   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
index 49dc69c8e3bd1c7af4516c56026a1c58576ca6fd..56f557c38071becb779e9592a3e160a5a3cf63a8 100644 (file)
@@ -64,6 +64,10 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers2D_i:
   void SetStretchFactor(::CORBA::Double factor) throw ( SALOME::SALOME_Exception );
   ::CORBA::Double GetStretchFactor();
 
+  void SetGroupName(const char* name);
+  char* GetGroupName();
+
+
   // Get implementation
   ::StdMeshers_ViscousLayers2D* GetImpl();
 
index 603ef55c3e9dd77a229e317707165d8c235b77f4..ab47e172574a850d54bf25114faae11a6a83151a 100644 (file)
@@ -253,6 +253,32 @@ void StdMeshers_ViscousLayers_i::SetMethod( ::StdMeshers::VLExtrusionMethod how
   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
index ac5f0e1ae83e0b963bc2c8f6d730acd12925e319..47200ce7244033ac0861f69f9745a1094cc46e51 100644 (file)
@@ -67,10 +67,14 @@ class STDMESHERS_I_EXPORT StdMeshers_ViscousLayers_i:
   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
index 602b00ae2fb18923ec64f2f3fcf1b4d1b2444431..676de466d35cb1a9a6073c495f219d00e8e64650 100644 (file)
@@ -57,6 +57,7 @@
 #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"
@@ -250,6 +251,8 @@ STDMESHERS_I_EXPORT
       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;
index fb80f4696be431a7e84ce81f5ec13fdb9b9a8abc..224667f60fdfebf77ee317bdceeacda3bcaa359d 100644 (file)
@@ -211,7 +211,7 @@ int main(int argc, char *argv[])
     {
       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);
@@ -1065,7 +1065,7 @@ int main(int argc, char *argv[])
           // 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++)
index ba8284d0da116b8e6270f2f5083acb7cd8d8e216..e99da4fc55fdc97a957726591e07db6b4dbf806e 100644 (file)
@@ -89,7 +89,7 @@ int MESHCUT::intersectionSegmentPlan(int it4, int na)
   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);
index c6cc137dd2331d146d6a1ade23ac2cde2a0ba427..d7e41ccb6b5f8dcd8311abd756e46c51a4de0985 100644 (file)
@@ -66,7 +66,7 @@ void Maillage::afficheMailles(TYPE_MAILLE tm)
         {
           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);
@@ -868,7 +868,7 @@ void Maillage::acquisitionTYPE_inputMED(TYPE_MAILLE TYPE, int nTYPE, med_idt fid
   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);
@@ -1705,10 +1705,10 @@ void Maillage::eliminationMailles(TYPE_MAILLE tm, vector<int> listeMaillesSuppr)
 
   // ************* 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 )
index 7ec14de78af5133b0d4aba49a898659525fd781c..6f984dd094e8d8af16a9e9e045364f2121b0b784 100644 (file)
@@ -75,7 +75,7 @@ namespace MESHCUT
       // 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;
index 5aa78dbb6bc377d2b00486d8151c2256505d7234..059ca3c8b952d6bfb20be6c8c2ea669093d9bfd8 100644 (file)
@@ -1035,7 +1035,7 @@ float MESHCUT::distance2(float x1, float y1, float z1, float x2, float y2, float
 /*!
  *  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);
index 94b3eb9688e516299414da20f511bb67dab2d287..72b9bfd4ea3d81325e5f82cf3749c1947860dbf2 100644 (file)
@@ -71,7 +71,7 @@ namespace MESHCUT
     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);
 
   }