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 10fb7d4..3515fa4 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 1500621..6826ab0 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 26bdb8b..d7d64b8 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 f2b7d8c..cadd71e 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 c9a605f..9f4c59a 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 2a9859d..14af9af 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 1f5d63c..b0d756f 100644 (file)
Binary files a/doc/salome/gui/SMESH/images/pref21.png and b/doc/salome/gui/SMESH/images/pref21.png differ
index 4ad6ee0..f9b952f 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 aaf9ad6..b7bbffb 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 c666591..6fa98f9 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 692232f..d636b15 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 46605bb..3458728 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 f5aca44..05c4c0d 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 734011f..027518e 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 a4bb746..1f8bf76 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
@@ -1115,6 +1139,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
    */
   interface StdMeshers_Hexa_3D : SMESH::SMESH_3D_Algo
index cdb800e..f612bb0 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
   {
@@ -165,6 +174,15 @@ module SMESH
       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.
      * The returned hypothesis may be the one existing in a study and used
@@ -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 9a12269..405c626 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 b78f7a9..4af5621 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 14ed93a..d70cdd4 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 676c68a..fc7ba62 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 a8ed41c..68f17df 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 a4774fe..30f3ac4 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 76d85a0..d36b216 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 f5bb08e..26596f8 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 cae413d..f832ad9 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 e77f9a7..515629c 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 f73b4ec..86dc634 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 2148a15..fbb4f8b 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 1e9c147..9c34d8a 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 d1301c4..520e724 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 7201c52..cd5e431 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 5eadb13..7549d24 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 b7c6ef2..2104c79 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 503de16..8d5dee8 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 c540449..ba08d51 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 f7be404..9054ad8 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 63d946b..f88e9be 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 5522e31..0376704 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 e75b822..b50f5f1 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 eaaad91..2660647 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 904a04b..4f8840b 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 a1ee4ec..787a344 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 3dd5b06..1cfb876 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 36b530a..ed9e8d6 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;
@@ -1657,6 +1708,179 @@ void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
 
 //================================================================================
 /*!
+ * \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
  * \param theSetName - The name 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 d93e4a1..1a117d5 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 a8564b4..fe5b138 100644 (file)
@@ -291,6 +291,29 @@ namespace SMESH
 
   //================================================================================
   /*!
+   * \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 ec60574..8874d1a 100644 (file)
@@ -219,6 +219,9 @@ SMESHGUI_EXPORT
 
   SMESHGUI_EXPORT
   void UpdateActorsAfterUpdateStudy( SUIT_ViewWindow* wnd );
+
+  SMESHGUI_EXPORT
+  void UpdateActorsAfterUpdateStudy();
 };
 
 #endif // SMESHGUI_VTKUTILS_H
index 823032f..3993633 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 62e0db9..eba5718 100644 (file)
@@ -4678,6 +4678,10 @@ Please, create VTK viewer and try again</translation>
         <translation>Default Number of Segments</translation>
     </message>
     <message>
+        <source>PREF_USE_MESHGEMS_HYPOSET</source>
+        <translation>Use MeshGems meshers when assigning set of hypotheses</translation>
+    </message>
+    <message>
         <source>SMESH_PREF_MESH_LOADING</source>
         <translation>Mesh loading</translation>
     </message>
@@ -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 23f5a8d..f3ecad3 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>
@@ -4604,6 +4603,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</translation>
         <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>
     </message>
@@ -4616,6 +4619,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</translation>
         <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>
     </message>
@@ -4704,6 +4711,10 @@ Ouvrez une fenêtre VTK et essayez de nouveau</translation>
         <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>
     </message>
@@ -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 e2a4a99..92bbc6e 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 e274c77..9bb7079 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 10398d8..689f498 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 6117d45..ac0b696 100644 (file)
@@ -831,6 +831,43 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
 
 //================================================================================
 /*!
+ * \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
  * existing on the given geometry or to size of the geometry.
  *  \param theHypType - hypothesis type name
@@ -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 0cb93fb..b288eec 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 0b258bf..580663d 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())
@@ -1032,6 +1036,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 a2dac40..a7a7e45 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 421a0ba..b813fc3 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 2b831f8..d4e396c 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 40e97e4..0d79c01 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 58701b1..275acb0 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 0687ddc..6b90f80 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 8588202..8c8a4ce 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 696d4f3..2a62389 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 be5552d..e90d64a 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 dfad28a..df1d952 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 21bc0bb..fe479bb 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
@@ -740,6 +743,48 @@ bool StdMeshers_CartesianParameters3D::GetToAddEdges() const
 }
 
 //=======================================================================
+//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 089d19f..fc8ceff 100644 (file)
@@ -140,6 +140,25 @@ public:
   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
    */
   bool IsDefined() const;
@@ -171,6 +190,9 @@ public:
 
   double _sizeThreshold;
   bool   _toAddEdges;
+  bool   _toConsiderInternalFaces;
+  bool   _toUseThresholdForInternalFaces;
+  bool   _toCreateFaces;
 };
 
 #endif
index 85a984c..7805901 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,
@@ -318,6 +439,49 @@ namespace
   };
   // --------------------------------------------------------------------------
   /*!
+   * \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
    */
   struct FaceGridIntersector
@@ -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;
   }
   //================================================================================
   /*
@@ -825,6 +1134,35 @@ namespace
   }
   //================================================================================
   /*
+   * 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
    */
   LineIndexer Grid::GetLineIndexer(size_t iDir) const
@@ -930,6 +1268,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
    */
   void Grid::ComputeUVW(const gp_XYZ& P, double UVW[3])
@@ -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 ))
+        {
+