Salome HOME
Restoring comment of unregister to investigate
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index d0dfc53dc7bbeb057a307894be0d373c88e3214c..ec65b9fa92be7c17356f01b6fd6b2a2d479ee0c0 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -38,8 +38,9 @@ SMESH.MED_MINOR_7 = 27 # back compatibility
 SMESH.MED_MINOR_8 = 28 # back compatibility
 SMESH.MED_MINOR_9 = 29 # back compatibility
 
-from   SMESH import *
-from   salome.smesh.smesh_algorithm import Mesh_Algorithm
+from SMESH import *
+from salome.smesh.smesh_algorithm import Mesh_Algorithm
+from StdMeshers import BlockCS
 
 import SALOME
 import SALOMEDS
@@ -215,7 +216,7 @@ NO_NAME = "NoName"
 def GetName(obj):
     """
     Return a name of an object
-    
+
     Returns:
         object name
     """
@@ -303,7 +304,9 @@ def AssureGeomPublished(mesh, geom, name=''):
     """
     Private method. Add geom (sub-shape of the main shape) into the study if not yet there
     """
-    if not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
+    if not mesh.smeshpyD.IsEnablePublish():
+        return
+    if not hasattr( geom, "GetShapeType" ):
         return
     if not geom.GetStudyEntry():
         ## get a name
@@ -316,27 +319,13 @@ def AssureGeomPublished(mesh, geom, name=''):
         mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
     return
 
-def FirstVertexOnCurve(mesh, edge):
-    """
-    Returns:
-        the first vertex of a geometrical edge by ignoring orientation
-    """
-    vv = mesh.geompyD.SubShapeAll( edge, geomBuilder.geomBuilder.ShapeType["VERTEX"])
-    if not vv:
-        raise TypeError("Given object has no vertices")
-    if len( vv ) == 1: return vv[0]
-    v0   = mesh.geompyD.MakeVertexOnCurve(edge,0.)
-    xyz  = mesh.geompyD.PointCoordinates( v0 ) # coords of the first vertex
-    xyz1 = mesh.geompyD.PointCoordinates( vv[0] )
-    xyz2 = mesh.geompyD.PointCoordinates( vv[1] )
-    dist1, dist2 = 0,0
-    for i in range(3):
-        dist1 += abs( xyz[i] - xyz1[i] )
-        dist2 += abs( xyz[i] - xyz2[i] )
-    if dist1 < dist2:
-        return vv[0]
-    else:
-        return vv[1]
+# def FirstVertexOnCurve(mesh, edge):
+#     """
+#     Returns:
+#         the first vertex of a geometrical edge by ignoring orientation
+#     """
+#     return mesh.geompyD.GetVertexByIndex( edge, 0, False )
+
 
 smeshInst = None
 """
@@ -440,26 +429,26 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
     def init_smesh(self,geompyD = None):
         """
         Set Geometry component
-        """    
+        """
         #print("init_smesh")
         self.UpdateStudy(geompyD)
         notebook.myStudy = salome.myStudy
 
     def Mesh(self, obj=0, name=0):
         """
-        Create a mesh. This mesh can be either 
+        Create a mesh. This mesh can be either
 
         * an empty mesh not bound to geometry, if *obj* == 0
         * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
         * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
 
         Parameters:
-            obj: either 
+            obj: either
 
                    1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
                       ::
 
-                        salome.myStudy.FindObjectID("0:1:2:3").GetObject() 
+                        salome.myStudy.FindObjectID("0:1:2:3").GetObject()
 
                    2. a geometrical object for meshing
                    3. none.
@@ -473,6 +462,39 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             obj,name = name,obj
         return Mesh(self, self.geompyD, obj, name)
 
+    def ParallelMesh(self, obj, param, nbThreads, name=0):
+        """
+        Create a parallel mesh.
+
+        Parameters:
+            obj: geometrical object for meshing
+            name: the name for the new mesh.
+            param: full mesh parameters
+            nbThreads: Number of threads for parallelisation.
+
+        Returns:
+            an instance of class :class:`ParallelMesh`.
+        """
+        return ParallelMesh(self, self.geompyD, obj, param, nbThreads, name)
+
+    def RemoveMesh( self, mesh ):
+        """
+        Delete a mesh
+        """
+        if isinstance( mesh, Mesh ):
+            mesh = mesh.GetMesh()
+            pass
+        if not isinstance( mesh, SMESH._objref_SMESH_Mesh ):
+            raise TypeError("%s is not a mesh" % mesh )
+        so = salome.ObjectToSObject( mesh )
+        if so:
+            sb = salome.myStudy.NewBuilder()
+            sb.RemoveObjectWithChildren( so )
+        else:
+            mesh.UnRegister()
+            pass
+        return
+
     def EnumToLong(self,theItem):
         """
         Return a long value from enumeration
@@ -511,8 +533,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Returns:
                 :class:`SMESH.PointStruct`
         """
-
-        [x, y, z] = self.geompyD.PointCoordinates(theVertex)
+        geompyD = theVertex.GetGen()
+        [x, y, z] = geompyD.PointCoordinates(theVertex)
         return PointStruct(x,y,z)
 
     def GetDirStruct(self,theVector):
@@ -525,13 +547,13 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Returns:
                 :class:`SMESH.DirStruct`
         """
-
-        vertices = self.geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
+        geompyD = theVector.GetGen()
+        vertices = geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
         if(len(vertices) != 2):
             print("Error: vector object is incorrect.")
             return None
-        p1 = self.geompyD.PointCoordinates(vertices[0])
-        p2 = self.geompyD.PointCoordinates(vertices[1])
+        p1 = geompyD.PointCoordinates(vertices[0])
+        p2 = geompyD.PointCoordinates(vertices[1])
         pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
         dirst = DirStruct(pnt)
         return dirst
@@ -561,28 +583,29 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             :class:`SMESH.AxisStruct`
         """
         import GEOM
-        edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
+        geompyD = theObj.GetGen()
+        edges = geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
         axis = None
         if len(edges) > 1:
-            vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
-            vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
-            vertex1 = self.geompyD.PointCoordinates(vertex1)
-            vertex2 = self.geompyD.PointCoordinates(vertex2)
-            vertex3 = self.geompyD.PointCoordinates(vertex3)
-            vertex4 = self.geompyD.PointCoordinates(vertex4)
+            vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
+            vertex3, vertex4 = geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
+            vertex1 = geompyD.PointCoordinates(vertex1)
+            vertex2 = geompyD.PointCoordinates(vertex2)
+            vertex3 = geompyD.PointCoordinates(vertex3)
+            vertex4 = geompyD.PointCoordinates(vertex4)
             v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
             normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
             axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
         elif len(edges) == 1:
-            vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
-            p1 = self.geompyD.PointCoordinates( vertex1 )
-            p2 = self.geompyD.PointCoordinates( vertex2 )
+            vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
+            p1 = geompyD.PointCoordinates( vertex1 )
+            p2 = geompyD.PointCoordinates( vertex2 )
             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
             axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
         elif theObj.GetShapeType() == GEOM.VERTEX:
-            x,y,z = self.geompyD.PointCoordinates( theObj )
+            x,y,z = geompyD.PointCoordinates( theObj )
             axis = AxisStruct( x,y,z, 1,0,0,)
             axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
         return axis
@@ -640,7 +663,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         if sc:
             sb.LoadWith(sc, self)
         pass
-    
+
     def SetEnablePublish( self, theIsEnablePublish ):
         """
         Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
@@ -669,7 +692,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Create a Mesh object(s) importing data from the given MED file
 
         Returns:
-                a tuple ( list of class :class:`Mesh` instances, 
+                a tuple ( list of class :class:`Mesh` instances,
                 :class:`SMESH.DriverMED_ReadStatus` )
         """
 
@@ -677,18 +700,6 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
-    def CreateMeshesFromSAUV( self,theFileName ):
-        """
-        Create a Mesh object(s) importing data from the given SAUV file
-
-        Returns:
-                a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
-        """
-
-        aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
-        aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
-        return aMeshes, aStatus
-
     def CreateMeshesFromSTL( self, theFileName ):
         """
         Create a Mesh object importing data from the given STL file
@@ -731,10 +742,10 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
 
     def Concatenate( self, meshes, uniteIdenticalGroups,
                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
-                     name = ""):
+                     name = "", meshToAppendTo = None):
         """
-        Concatenate the given meshes into one mesh. All groups of input meshes will be
-        present in the new mesh.
+        Concatenate the given meshes into one mesh, optionally to meshToAppendTo.
+        All groups of input meshes will be present in the new mesh.
 
         Parameters:
                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
@@ -743,32 +754,67 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
                 mergeTolerance: tolerance for merging nodes
                 allGroups: forces creation of groups corresponding to every input mesh
                 name: name of a new mesh
+                meshToAppendTo: a mesh to append all given meshes
 
         Returns:
                 an instance of class :class:`Mesh`
+
+        See also:
+                :meth:`Mesh.Append`
         """
 
         if not meshes: return None
-        for i,m in enumerate(meshes):
-            if isinstance(m, Mesh):
+        if not isinstance( meshes, list ):
+            meshes = [ meshes ]
+        for i,m in enumerate( meshes ):
+            if isinstance( m, Mesh ):
                 meshes[i] = m.GetMesh()
-        mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
-        meshes[0].SetParameters(Parameters)
+        mergeTolerance,Parameters,hasVars = ParseParameters( mergeTolerance )
+        if hasattr(meshes[0], "SetParameters"):
+            meshes[0].SetParameters( Parameters )
+        else:
+            meshes[0].GetMesh().SetParameters( Parameters )
+        if isinstance( meshToAppendTo, Mesh ):
+            meshToAppendTo = meshToAppendTo.GetMesh()
         if allGroups:
             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
-                self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
+                self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
+                mergeTolerance,meshToAppendTo )
         else:
             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
-                self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
-        aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
+                self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
+                mergeTolerance,meshToAppendTo )
+
+        aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name )
         return aMesh
 
+    def CreateDualMesh( self, mesh, meshName, adaptToShape):
+        """
+        Create a dual of a mesh.
+
+        Parameters:
+                mesh: Tetrahedron mesh
+                        :class:`mesh, <SMESH.SMESH_IDSource>`.
+
+                meshName: a name of the new mesh
+                adpatToShape: if true project boundary points on shape
+
+        Returns:
+                an instance of class :class:`Mesh`
+        """
+        if isinstance( mesh, Mesh ):
+            mesh = mesh.GetMesh()
+        print("calling createdualmesh from Python")
+        dualMesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName, adaptToShape)
+        return Mesh(self, self.geompyD, dualMesh)
+
+
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
         """
         Create a mesh by copying a part of another mesh.
 
         Parameters:
-                meshPart: a part of mesh to copy, either 
+                meshPart: a part of mesh to copy, either
                         :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
                         To copy nodes or elements not forming any mesh object,
                         pass result of :meth:`Mesh.GetIDSource` as *meshPart*
@@ -780,11 +826,46 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
                 an instance of class :class:`Mesh`
         """
 
-        if (isinstance( meshPart, Mesh )):
+        if isinstance( meshPart, Mesh ):
             meshPart = meshPart.GetMesh()
         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
         return Mesh(self, self.geompyD, mesh)
 
+    def CopyMeshWithGeom( self, sourceMesh, newGeom, meshName="", toCopyGroups=True,
+                          toReuseHypotheses=True, toCopyElements=True):
+        """
+        Create a mesh by copying a mesh definition (hypotheses and groups) to a new geometry.
+        It is supposed that the new geometry is a modified geometry of *sourceMesh*.
+        To facilitate and speed up the operation, consider using
+        "Set presentation parameters and sub-shapes from arguments" option in
+        a dialog of geometrical operation used to create the new geometry.
+
+        Parameters:
+                sourceMesh: the mesh to copy definition of.
+                newGeom: the new geometry.
+                meshName: an optional name of the new mesh. If omitted, the mesh name is kept.
+                toCopyGroups: to create groups in the new mesh.
+                toReuseHypotheses: to reuse hypotheses of the *sourceMesh*.
+                toCopyElements: to copy mesh elements present on non-modified sub-shapes of
+                                *sourceMesh*.
+        Returns:
+                tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries )
+                *invalidEntries* are study entries of objects whose
+                counterparts are not found in the *newGeom*, followed by entries
+                of mesh sub-objects that are invalid because they depend on a not found
+                preceding sub-shape
+        """
+        if isinstance( sourceMesh, Mesh ):
+            sourceMesh = sourceMesh.GetMesh()
+
+        ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries = \
+           SMESH._objref_SMESH_Gen.CopyMeshWithGeom( self, sourceMesh, newGeom, meshName,
+                                                     toCopyGroups,
+                                                     toReuseHypotheses,
+                                                     toCopyElements)
+        return ( ok, Mesh(self, self.geompyD, newMesh),
+                 newGroups, newSubMeshes, newHypotheses, invalidEntries )
+
     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
         """
         Return IDs of sub-shapes
@@ -903,7 +984,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
                     name = aCriterion.ThresholdStr
                     if not name:
                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
-                    aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
+                    geompyD = aThreshold.GetGen()
+                    aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
             # or a name of GEOM object
             elif isinstance( aThreshold, str ):
                 aCriterion.ThresholdStr = aThreshold
@@ -954,7 +1036,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
                     name = aThreshold.GetName()
                     if not name:
                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
-                    aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
+                    geompyD = aThreshold.GetGen()
+                    aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
             elif isinstance(aThreshold, int): # node id
                 aCriterion.Threshold = aThreshold
             elif isinstance(aThreshold, list): # 3 point coordinates
@@ -1142,6 +1225,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             functor = aFilterMgr.CreateLength()
         elif theCriterion == FT_Length2D:
             functor = aFilterMgr.CreateLength2D()
+        elif theCriterion == FT_Length3D:
+            functor = aFilterMgr.CreateLength3D()
         elif theCriterion == FT_Deflection2D:
             functor = aFilterMgr.CreateDeflection2D()
         elif theCriterion == FT_NodeConnectivityNumber:
@@ -1179,11 +1264,30 @@ 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.
-        Use :meth:`smeshBuilder.EnumToLong` to get an integer from 
-        an item of :class:`SMESH.EntityType`.
 
         Returns:
                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
@@ -1217,7 +1321,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Returns:
                 minimum distance value
 
-        See also: 
+        See also:
                 :meth:`GetMinDistance`
         """
 
@@ -1245,7 +1349,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
 
         Returns:
                 :class:`SMESH.Measure` structure or None if input data is invalid
-        See also: 
+        See also:
                 :meth:`MinDistance`
         """
 
@@ -1292,7 +1396,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Returns:
                 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
 
-        See also: 
+        See also:
                :meth:`GetBoundingBox`
         """
 
@@ -1313,7 +1417,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         Returns:
                 :class:`SMESH.Measure` structure
 
-        See also: 
+        See also:
                 :meth:`BoundingBox`
         """
 
@@ -1391,13 +1495,16 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
 
     def GetGravityCenter(self, obj):
         """
-        Get gravity center of all nodes of the mesh object.
-        
-        Parameters:            
+        Get gravity center of all nodes of a mesh object.
+
+        Parameters:
                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
 
-        Returns:        
-            Three components of the gravity center (x,y,z)
+        Returns:
+                Three components of the gravity center (x,y,z)
+
+        See also:
+                :meth:`Mesh.BaryCenter`
         """
         if isinstance(obj, Mesh): obj = obj.mesh
         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
@@ -1406,6 +1513,28 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
         aMeasurements.UnRegister()
         return pointStruct.x, pointStruct.y, pointStruct.z
 
+    def GetAngle(self, p1, p2, p3 ):
+        """
+        Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3)
+
+        Parameters:
+                p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct
+                          or list [x,y,z]
+
+        Returns:
+            Angle in radians
+        """
+        if isinstance( p1, list ): p1 = PointStruct(*p1)
+        if isinstance( p2, list ): p2 = PointStruct(*p2)
+        if isinstance( p3, list ): p3 = PointStruct(*p3)
+
+        aMeasurements = self.CreateMeasurements()
+        angle = aMeasurements.Angle(p1,p2,p3)
+        aMeasurements.UnRegister()
+
+        return angle
+
+
     pass # end of class smeshBuilder
 
 import omniORB
@@ -1458,7 +1587,7 @@ class Mesh(metaclass = MeshMeta):
     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
     new nodes and elements and by changing the existing entities), to get information
     about a mesh and to export a mesh in different formats.
-    """    
+    """
 
     geom = 0
     mesh = 0
@@ -1539,15 +1668,26 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
                 theMesh: a :class:`SMESH.SMESH_Mesh` object
         """
-
-
         # do not call Register() as this prevents mesh servant deletion at closing study
         #if self.mesh: self.mesh.UnRegister()
         self.mesh = theMesh
         if self.mesh:
             #self.mesh.Register()
             self.geom = self.mesh.GetShapeToMesh()
-        pass
+            if self.geom:
+                self.geompyD = None
+                try:
+                    if salome.sg.hasDesktop():
+                        so = salome.ObjectToSObject( self.geom )
+                        comp = so.GetFatherComponent()
+                        if comp.ComponentDataType() == "SHAPERSTUDY":
+                            import shaperBuilder
+                            self.geompyD = shaperBuilder.New()
+                except:
+                    pass
+                if not self.geompyD:
+                    self.geompyD = self.geom.GetGen()
+                pass
 
     def GetMesh(self):
         """
@@ -1559,6 +1699,18 @@ class Mesh(metaclass = MeshMeta):
 
         return self.mesh
 
+    def GetEngine(self):
+        """
+        Return a smeshBuilder instance created this mesh
+        """
+        return self.smeshpyD
+
+    def GetGeomEngine(self):
+        """
+        Return a geomBuilder instance
+        """
+        return self.geompyD
+
     def GetName(self):
         """
         Get the name of the mesh
@@ -1598,7 +1750,7 @@ class Mesh(metaclass = MeshMeta):
 
                    algo1D = mesh.Segment(geom=Edge_1)
 
-                creates a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
+                create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
                 The created sub-mesh can be retrieved from the algorithm::
 
                    submesh = algo1D.GetSubMesh()
@@ -1628,6 +1780,12 @@ class Mesh(metaclass = MeshMeta):
 
         self.mesh = self.smeshpyD.CreateMesh(geom)
 
+    def HasShapeToMesh(self):
+        """
+        Return ``True`` if this mesh is based on geometry
+        """
+        return self.mesh.HasShapeToMesh()
+
     def Load(self):
         """
         Load mesh from the study after opening the study
@@ -1720,7 +1878,6 @@ class Mesh(metaclass = MeshMeta):
                 geom = self.geom
         return self.smeshpyD.Evaluate(self.mesh, geom)
 
-
     def Compute(self, geom=0, discardModifs=False, refresh=False):
         """
         Compute the mesh and return the status of the computation
@@ -1737,10 +1894,7 @@ class Mesh(metaclass = MeshMeta):
         """
 
         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
-            if self.geom == 0:
-                geom = self.mesh.GetShapeToMesh()
-            else:
-                geom = self.geom
+            geom = self.mesh.GetShapeToMesh()
         ok = False
         try:
             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
@@ -1831,9 +1985,10 @@ class Mesh(metaclass = MeshMeta):
                 print(msg)
                 print(allReasons)
             pass
-        if salome.sg.hasDesktop():
-            if not isinstance( refresh, list): # not a call from subMesh.Compute()
-                if refresh: salome.sg.updateObjBrowser()
+        if salome.sg:
+            if salome.sg.hasDesktop():
+                if not isinstance( refresh, list): # not a call from subMesh.Compute()
+                    if refresh: salome.sg.updateObjBrowser()
 
         return ok
 
@@ -1960,10 +2115,20 @@ class Mesh(metaclass = MeshMeta):
 
     def SetMeshOrder(self, submeshes):
         """
-        Set order in which concurrent sub-meshes should be meshed
+        Set priority of sub-meshes. It works in two ways:
+
+        * For sub-meshes with assigned algorithms of same dimension generating mesh of
+          *several dimensions*, it sets the order in which the sub-meshes are computed.
+        * For the rest sub-meshes, it sets the order in which the sub-meshes are checked
+          when looking for meshing parameters to apply to a sub-shape. To impose the
+          order in which sub-meshes with uni-dimensional algorithms are computed,
+          call **submesh.Compute()** in a desired order.
 
         Parameters:
                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
+
+        Warning: the method is for setting the order for all sub-meshes at once:
+                 SetMeshOrder( [ [sm1, sm2, sm3], [sm4, sm5] ] )
         """
 
         return self.mesh.SetMeshOrder(submeshes)
@@ -1995,7 +2160,7 @@ class Mesh(metaclass = MeshMeta):
 
     def AutomaticTetrahedralization(self, fineness=0):
         """
-        Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
+        Compute a tetrahedral mesh using AutomaticLength + Triangle + Tetrahedron
 
         Parameters:
                 fineness: [0.0,1.0] defines mesh fineness
@@ -2157,6 +2322,78 @@ class Mesh(metaclass = MeshMeta):
             self.mesh.RemoveHypothesis( self.geom, hyp )
             pass
         pass
+
+    def ExportMEDCoupling(self, *args, **kwargs):
+        """
+        Export the mesh in a memory representation.
+
+        Parameters:
+            auto_groups (boolean): parameter for creating/not creating
+                    the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
+                    the typical use is auto_groups=False.
+            overwrite (boolean): parameter for overwriting/not overwriting the file
+            meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
+                    to export instead of the mesh
+            autoDimension: if *True* (default), a space dimension of a MED mesh can be either
+
+                    - 1D if all mesh nodes lie on OX coordinate axis, or
+                    - 2D if all mesh nodes lie on XOY coordinate plane, or
+                    - 3D in the rest cases.
+
+                    If *autoDimension* is *False*, the space dimension is always 3.
+            fields: list of GEOM fields defined on the shape to mesh.
+            geomAssocFields: each character of this string means a need to export a
+                    corresponding field; correspondence between fields and characters
+                    is following:
+
+                    - 'v' stands for "_vertices_" field;
+                    - 'e' stands for "_edges_" field;
+                    - 'f' stands for "_faces_" field;
+                    - 's' stands for "_solids_" field.
+
+            zTolerance (float): tolerance in Z direction. If Z coordinate of a node is
+                            close to zero within a given tolerance, the coordinate is set to zero.
+                            If *ZTolerance* is negative (default), the node coordinates are kept as is.
+            saveNumbers(boolean) : enable saving numbers of nodes and cells.
+            """
+        auto_groups     = args[0] if len(args) > 0 else False
+        meshPart        = args[1] if len(args) > 1 else None
+        autoDimension   = args[2] if len(args) > 2 else True
+        fields          = args[3] if len(args) > 3 else []
+        geomAssocFields = args[4] if len(args) > 4 else ''
+        z_tolerance     = args[5] if len(args) > 5 else -1.
+        saveNumbers     = args[6] if len(args) > 6 else True
+        # process keywords arguments
+        auto_groups     = kwargs.get("auto_groups", auto_groups)
+        meshPart        = kwargs.get("meshPart", meshPart)
+        autoDimension   = kwargs.get("autoDimension", autoDimension)
+        fields          = kwargs.get("fields", fields)
+        geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
+        z_tolerance     = kwargs.get("zTolerance", z_tolerance)
+        saveNumbers     = kwargs.get("saveNumbers", saveNumbers)
+
+        # invoke engine's function
+        if meshPart or fields or geomAssocFields or z_tolerance > 0 or not saveNumbers:
+            unRegister = genObjUnRegister()
+            if isinstance( meshPart, list ):
+                meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+                unRegister.set( meshPart )
+
+            z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
+            self.mesh.SetParameters(Parameters)
+
+            intPtr = self.mesh.ExportPartToMEDCoupling(meshPart, auto_groups, autoDimension,
+                                                       fields, geomAssocFields, z_tolerance,
+                                                       saveNumbers )
+            import medcoupling
+            dab = medcoupling.FromPyIntPtrToDataArrayByte(intPtr)
+            return medcoupling.MEDFileData.New(dab)
+        else:
+            intPtr = self.mesh.ExportMEDCoupling(auto_groups, autoDimension)
+            import medcoupling
+            dab = medcoupling.FromPyIntPtrToDataArrayByte(intPtr)
+            return medcoupling.MEDFileMesh.New(dab)
+
     def ExportMED(self, *args, **kwargs):
         """
         Export the mesh in a file in MED format
@@ -2167,12 +2404,16 @@ class Mesh(metaclass = MeshMeta):
                 auto_groups (boolean): parameter for creating/not creating
                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
                         the typical use is auto_groups=False.
-                minor (int): define the minor version (y, where version is x.y.z) of MED file format.
-                        The minor must be between 0 and the current minor version of MED file library.
-                        If minor is equal to -1, the minor version is not changed (default).
-                        The major version (x, where version is x.y.z) cannot be changed.
+                version (int): define the version (xy, where version is x.y.z) of MED file format.
+                        For instance med 3.2.1 is coded 3*10+2 = 32, med 4.0.0 is coded 4*10+0 = 40.
+                        The rules of compatibility to write a mesh in an older version than
+                        the current version depend on the current version. For instance,
+                        with med 4.0 it is possible to write/append med files in 4.0.0 (default)
+                        or 3.2.1 or 3.3.1 formats.
+                        If the version is equal to -1, the version is not changed (default).
                 overwrite (boolean): parameter for overwriting/not overwriting the file
-                meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
+                meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
+                        to export instead of the mesh
                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
 
                         - 1D if all mesh nodes lie on OX coordinate axis, or
@@ -2181,91 +2422,100 @@ class Mesh(metaclass = MeshMeta):
 
                         If *autoDimension* is *False*, the space dimension is always 3.
                 fields: list of GEOM fields defined on the shape to mesh.
-                geomAssocFields: each character of this string means a need to export a 
-                        corresponding field; correspondence between fields and characters is following:
-                        - 'v' stands for "_vertices _" field;
-                        - 'e' stands for "_edges _" field;
-                        - 'f' stands for "_faces _" field;
-                        - 's' stands for "_solids _" field.
+                geomAssocFields: each character of this string means a need to export a
+                        corresponding field; correspondence between fields and characters
+                        is following:
+
+                        - 'v' stands for "_vertices_" field;
+                        - 'e' stands for "_edges_" field;
+                        - 'f' stands for "_faces_" field;
+                        - 's' stands for "_solids_" field.
+
+                zTolerance (float): tolerance in Z direction. If Z coordinate of a node is
+                             close to zero within a given tolerance, the coordinate is set to zero.
+                             If *ZTolerance* is negative (default), the node coordinates are kept as is.
+                saveNumbers (boolean) : enable saving numbers of nodes and cells.
         """
         # process positional arguments
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
         fileName        = args[0]
         auto_groups     = args[1] if len(args) > 1 else False
-        minor           = args[2] if len(args) > 2 else -1
+        version         = args[2] if len(args) > 2 else -1
         overwrite       = args[3] if len(args) > 3 else True
         meshPart        = args[4] if len(args) > 4 else None
         autoDimension   = args[5] if len(args) > 5 else True
         fields          = args[6] if len(args) > 6 else []
         geomAssocFields = args[7] if len(args) > 7 else ''
+        z_tolerance     = args[8] if len(args) > 8 else -1.
+        saveNumbers     = args[9] if len(args) > 9 else True
         # process keywords arguments
         auto_groups     = kwargs.get("auto_groups", auto_groups)
-        minor           = kwargs.get("minor", minor)
+        version         = kwargs.get("version", version)
+        version         = kwargs.get("minor", version)
         overwrite       = kwargs.get("overwrite", overwrite)
         meshPart        = kwargs.get("meshPart", meshPart)
         autoDimension   = kwargs.get("autoDimension", autoDimension)
         fields          = kwargs.get("fields", fields)
         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
+        z_tolerance     = kwargs.get("zTolerance", z_tolerance)
+        saveNumbers     = kwargs.get("saveNumbers", saveNumbers)
+
+        if isinstance( meshPart, Mesh):
+            meshPart = meshPart.GetMesh()
+
         # invoke engine's function
-        if meshPart or fields or geomAssocFields:
+        if meshPart or fields or geomAssocFields or z_tolerance > 0 or not saveNumbers:
             unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
                 unRegister.set( meshPart )
-            self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
-                                       fields, geomAssocFields)
-        else:
-            self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
-
-    def ExportSAUV(self, f, auto_groups=0):
-        """
-        Export the mesh in a file in SAUV format
 
+            z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
+            self.mesh.SetParameters(Parameters)
 
-        Parameters:
-                f: is the file name
-                auto_groups: boolean parameter for creating/not creating
-                        the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
-                        the typical use is auto_groups=False.
-        """
-
-        self.mesh.ExportSAUV(f, auto_groups)
+            self.mesh.ExportPartToMED( meshPart, fileName, auto_groups,
+                                       version, overwrite, autoDimension,
+                                       fields, geomAssocFields, z_tolerance, saveNumbers )
+        else:
+            self.mesh.ExportMED(fileName, auto_groups, version, overwrite, autoDimension)
 
-    def ExportDAT(self, f, meshPart=None):
+    def ExportDAT(self, f, meshPart=None, renumber=True):
         """
         Export the mesh in a file in DAT format
 
         Parameters:
                 f: the file name
                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
+                renumber(boolean): enable renumbering nodes and cells in order to eliminate holes in numbering
         """
 
-        if meshPart:
+        if meshPart or not renumber:
             unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
                 unRegister.set( meshPart )
-            self.mesh.ExportPartToDAT( meshPart, f )
+            self.mesh.ExportPartToDAT( meshPart, f, renumber )
         else:
-            self.mesh.ExportDAT(f)
+            self.mesh.ExportDAT( f, renumber )
 
-    def ExportUNV(self, f, meshPart=None):
+    def ExportUNV(self, f, meshPart=None, renumber=True):
         """
         Export the mesh in a file in UNV format
 
         Parameters:
                 f: the file name
                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
+                renumber(boolean): enable renumbering nodes and cells in order to eliminate holes in numbering
         """
 
-        if meshPart:
+        if meshPart or not renumber:
             unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
                 unRegister.set( meshPart )
-            self.mesh.ExportPartToUNV( meshPart, f )
+            self.mesh.ExportPartToUNV( meshPart, f, renumber )
         else:
-            self.mesh.ExportUNV(f)
+            self.mesh.ExportUNV( f, renumber )
 
     def ExportSTL(self, f, ascii=1, meshPart=None):
         """
@@ -2349,7 +2599,7 @@ class Mesh(metaclass = MeshMeta):
 
                         If **autoDimension** is *False*, the space dimension is always 3.
         """
-    
+
         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
         # process positional arguments
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
@@ -2399,15 +2649,34 @@ class Mesh(metaclass = MeshMeta):
         minor = -1
         # invoke engine's function
         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
+        return
+
+
+    def Append(self, meshes, uniteIdenticalGroups = True,
+                     mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
+        """
+        Append given meshes into this mesh.
+        All groups of input meshes will be created in this mesh.
+
+        Parameters:
+                meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to append
+                uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
+                mergeNodesAndElements: if True, equal nodes and elements are merged
+                mergeTolerance: tolerance for merging nodes
+                allGroups: forces creation of groups corresponding to every input mesh
+        """
+        self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups,
+                                   mergeNodesAndElements, mergeTolerance, allGroups,
+                                   meshToAppendTo = self.GetMesh() )
 
     # Operations with groups:
     # ----------------------
     def CreateEmptyGroup(self, elementType, name):
         """
-        Create an empty mesh group
+        Create an empty standalone mesh group
 
         Parameters:
-                elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
+                elementType: the :class:`type <SMESH.ElementType>` of elements in the group;
                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
                 name: the name of the mesh group
 
@@ -2439,7 +2708,7 @@ class Mesh(metaclass = MeshMeta):
     def GroupOnGeom(self, grp, name="", typ=None):
         """
         Create a mesh group based on the geometrical object *grp*
-        and gives a *name*.
+        and give it a *name*.
         if *name* is not defined the name of the geometric group is used
 
         Parameters:
@@ -2467,14 +2736,22 @@ 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
         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
             typ = VOLUME
         elif tgeo == "COMPOUND":
-            sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
+            try:
+              sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
+            except:
+              # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of
+              # simplification of access in geomBuilder: omniORB.registerObjref
+              from SHAPERSTUDY_utils import getEngine
+              gen = getEngine()
+              if gen:
+                sub = gen.GetIShapesOperations().ExtractSubShapes(shape, self.geompyD.ShapeType["SHAPE"], False)
             if not sub:
                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
             return self._groupTypeFromShape( sub[0] )
@@ -2484,8 +2761,8 @@ class Mesh(metaclass = MeshMeta):
 
     def GroupOnFilter(self, typ, name, filter):
         """
-        Create a mesh group with given *name* based on the *filter* which
-        is a special type of group dynamically updating it's contents during
+        Create a mesh group with given *name* based on the *filter*.
+        It is a special type of group dynamically updating it's contents during
         mesh modification
 
         Parameters:
@@ -2629,21 +2906,25 @@ class Mesh(metaclass = MeshMeta):
 
         Parameters:
                 group (SMESH.SMESH_GroupBase): group to remove
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         self.mesh.RemoveGroupWithContents(group)
 
     def GetGroups(self, elemType = SMESH.ALL):
         """
-        Get the list of groups existing in the mesh in the order
-        of creation (starting from the oldest one)
+        Get the list of groups existing in the mesh in the order of creation
+        (starting from the oldest one)
 
         Parameters:
                 elemType (SMESH.ElementType): type of elements the groups contain;
                         by default groups of elements of all types are returned
 
         Returns:
-                a sequence of :class:`SMESH.SMESH_GroupBase`
+                a list of :class:`SMESH.SMESH_GroupBase`
         """
 
         groups = self.mesh.GetGroups()
@@ -2803,7 +3084,7 @@ class Mesh(metaclass = MeshMeta):
         Create a standalone group of entities basing on nodes of other groups.
 
         Parameters:
-                groups: list of reference :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
+                groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
                 elemType: a type of elements to include to the new group; either of
                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
                 name: a name of the new group.
@@ -2829,6 +3110,22 @@ class Mesh(metaclass = MeshMeta):
             groups = [groups]
         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
 
+    def FaceGroupsSeparatedByEdges( self, sharpAngle, createEdges=False, useExistingEdges=False ):
+        """
+        Distribute all faces of the mesh among groups using sharp edges and optionally
+        existing 1D elements as group boundaries.
+
+        Parameters:
+                sharpAngle: edge is considered sharp if an angle between normals of
+                            adjacent faces is more than \a sharpAngle in degrees.
+                createEdges (boolean): to create 1D elements for detected sharp edges.
+                useExistingEdges (boolean): to use existing edges as group boundaries
+        Returns:
+                ListOfGroups - the created :class:`groups <SMESH.SMESH_Group>`
+        """
+        sharpAngle,Parameters,hasVars = ParseParameters( sharpAngle )
+        self.mesh.SetParameters(Parameters)
+        return self.mesh.FaceGroupsSeparatedByEdges( sharpAngle, createEdges, useExistingEdges );
 
     def ConvertToStandalone(self, group):
         """
@@ -2947,8 +3244,6 @@ class Mesh(metaclass = MeshMeta):
     def GetMeshInfo(self, obj = None):
         """
         Get the mesh statistic.
-        Use :meth:`smeshBuilder.EnumToLong` to get an integer from 
-        an item of :class:`SMESH.EntityType`.
 
         Returns:
                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
@@ -3332,7 +3627,7 @@ class Mesh(metaclass = MeshMeta):
         Return the type of mesh element or node
 
         Returns:
-            the value from :class:`SMESH.ElementType` enumeration. 
+            the value from :class:`SMESH.ElementType` enumeration.
             Return SMESH.ALL if element or node with the given ID does not exist
         """
 
@@ -3438,16 +3733,20 @@ class Mesh(metaclass = MeshMeta):
 
         return self.mesh.GetNodeXYZ(id)
 
-    def GetNodeInverseElements(self, id):
+    def GetNodeInverseElements(self, id, elemType=SMESH.ALL):
         """
         Return list of IDs of inverse elements for the given node.
         If there is no node for the given ID - return an empty list
 
+        Parameters:
+                id: node ID
+                elementType: :class:`type of elements <SMESH.ElementType>` (SMESH.EDGE, SMESH.FACE, SMESH.VOLUME, etc.)
+
         Returns:
             list of integer values
         """
 
-        return self.mesh.GetNodeInverseElements(id)
+        return self.mesh.GetNodeInverseElements(id,elemType)
 
     def GetNodePosition(self,NodeID):
         """
@@ -3621,26 +3920,40 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             a list of three double values
+
+        See also:
+                :meth:`smeshBuilder.GetGravityCenter`
         """
 
         return self.mesh.BaryCenter(id)
 
-    def GetIdsFromFilter(self, theFilter):
+    def GetIdsFromFilter(self, filter, meshParts=[] ):
         """
         Pass mesh elements through the given filter and return IDs of fitting elements
 
         Parameters:
-                theFilter: :class:`SMESH.Filter`
+                filter: :class:`SMESH.Filter`
+                meshParts: list of mesh parts (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to filter
 
         Returns:
             a list of ids
 
         See Also:
             :meth:`SMESH.Filter.GetIDs`
+            :meth:`SMESH.Filter.GetElementsIdFromParts`
         """
 
-        theFilter.SetMesh( self.mesh )
-        return theFilter.GetIDs()
+        filter.SetMesh( self.mesh )
+
+        if meshParts:
+            if isinstance( meshParts, Mesh ):
+                filter.SetMesh( meshParts.GetMesh() )
+                return theFilter.GetIDs()
+            if isinstance( meshParts, SMESH._objref_SMESH_IDSource ):
+                meshParts = [ meshParts ]
+            return filter.GetElementsIdFromParts( meshParts )
+
+        return filter.GetIDs()
 
     # Get mesh measurements information:
     # ------------------------------------
@@ -3672,7 +3985,9 @@ class Mesh(metaclass = MeshMeta):
                 isElem2: *True* if *id2* is element id, *False* if it is node id
 
         Returns:
-            minimum distance value **GetMinDistance()**
+            minimum distance value
+        See Also:
+            :meth:`GetMinDistance`
         """
 
         aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
@@ -3724,7 +4039,7 @@ class Mesh(metaclass = MeshMeta):
         Returns:
             tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
 
-        See Also: 
+        See Also:
             :meth:`GetBoundingBox()`
         """
 
@@ -3747,7 +4062,7 @@ class Mesh(metaclass = MeshMeta):
         Returns:
             :class:`SMESH.Measure` structure
 
-        See Also: 
+        See Also:
             :meth:`BoundingBox()`
         """
 
@@ -3793,6 +4108,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True or False
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.RemoveElements(IDsOfElements)
@@ -3806,16 +4125,34 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True or False
+
+        Note:
+                This operation can create gaps in numeration of nodes.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.RemoveNodes(IDsOfNodes)
 
+    def RemoveNodeWithReconnection(self, nodeID ):
+        """
+        Remove a node along with changing surrounding faces to cover a hole.
+
+        Parameters:
+                nodeID: ID of node to remove
+        """
+
+        return self.editor.RemoveNodeWithReconnection( nodeID )
+
     def RemoveOrphanNodes(self):
         """
         Remove all orphan (free) nodes from mesh
 
         Returns:
             number of the removed nodes
+
+        Note:
+                This operation can create gaps in numeration of nodes.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.RemoveOrphanNodes()
@@ -3861,7 +4198,7 @@ class Mesh(metaclass = MeshMeta):
         Returns:
             an object (a new group or a temporary :class:`SMESH.SMESH_IDSource`) holding
             IDs of new and/or found 0D elements. IDs of 0D elements
-            can be retrieved from the returned object by 
+            can be retrieved from the returned object by
             calling :meth:`GetIDs() <SMESH.SMESH_IDSource.GetIDs>`
         """
 
@@ -3997,7 +4334,7 @@ class Mesh(metaclass = MeshMeta):
 
     def SetNodeOnVertex(self, NodeID, Vertex):
         """
-        Binds a node to a vertex
+        Bind a node to a vertex
 
         Parameters:
                 NodeID: a node ID
@@ -4020,7 +4357,7 @@ class Mesh(metaclass = MeshMeta):
 
     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
         """
-        Stores the node position on an edge
+        Store the node position on an edge
 
         Parameters:
                 NodeID: a node ID
@@ -4043,7 +4380,7 @@ class Mesh(metaclass = MeshMeta):
 
     def SetNodeOnFace(self, NodeID, Face, u, v):
         """
-        Stores node position on a face
+        Store node position on a face
 
         Parameters:
                 NodeID: a node ID
@@ -4067,7 +4404,7 @@ class Mesh(metaclass = MeshMeta):
 
     def SetNodeInVolume(self, NodeID, Solid):
         """
-        Binds a node to a solid
+        Bind a node to a solid
 
         Parameters:
                 NodeID: a node ID
@@ -4160,8 +4497,6 @@ class Mesh(metaclass = MeshMeta):
             the ID of a node
         """
 
-        #preview = self.mesh.GetMeshEditPreviewer()
-        #return preview.MoveClosestNodeToPoint(x, y, z, -1)
         return self.editor.FindNodeClosestTo(x, y, z)
 
     def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL, meshPart=None):
@@ -4182,10 +4517,23 @@ class Mesh(metaclass = MeshMeta):
         else:
             return self.editor.FindElementsByPoint(x, y, z, elementType)
 
+    def ProjectPoint(self, x,y,z, elementType, meshObject=None):
+        """
+        Project a point to a mesh object.
+        Return ID of an element of given type where the given point is projected
+        and coordinates of the projection point.
+        In the case if nothing found, return -1 and []
+        """
+        if isinstance( meshObject, Mesh ):
+            meshObject = meshObject.GetMesh()
+        if not meshObject:
+            meshObject = self.GetMesh()
+        return self.editor.ProjectPoint( x,y,z, elementType, meshObject )
+
     def GetPointState(self, x, y, z):
         """
         Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
-        0-IN, 1-OUT, 2-ON, 3-UNKNOWN.
+        smesh.TopAbs_IN, smesh.TopAbs_OUT, smesh.TopAbs_ON and smesh.TopAbs_UNKNOWN.
         UNKNOWN state means that either mesh is wrong or the analysis fails.
         """
 
@@ -4205,6 +4553,41 @@ class Mesh(metaclass = MeshMeta):
 
         return self.editor.IsCoherentOrientation2D()
 
+    def Get1DBranches( self, edges, startNode = 0 ):
+        """
+        Partition given 1D elements into groups of contiguous edges.
+        A node where number of meeting edges != 2 is a group end.
+        An optional startNode is used to orient groups it belongs to.
+
+        Returns:
+             A list of edge groups and a list of corresponding node groups,
+             where the group is a list of IDs of edges or nodes, like follows
+             [[[branch_edges_1],[branch_edges_2]], [[branch_nodes_1],[branch_nodes_2]]].
+             If a group is closed, the first and last nodes of the group are same.
+        """
+        if isinstance( edges, Mesh ):
+            edges = edges.GetMesh()
+        unRegister = genObjUnRegister()
+        if isinstance( edges, list ):
+            edges = self.GetIDSource( edges, SMESH.EDGE )
+            unRegister.set( edges )
+        return self.editor.Get1DBranches( edges, startNode )
+
+    def FindSharpEdges( self, angle, addExisting=False ):
+        """
+        Return sharp edges of faces and non-manifold ones.
+        Optionally add existing edges.
+
+        Parameters:
+                angle: angle (in degrees) between normals of adjacent faces to detect sharp edges
+                addExisting: to return existing edges (1D elements) as well
+
+        Returns:
+            list of FaceEdge structures
+        """
+        angle = ParseParameters( angle )[0]
+        return self.editor.FindSharpEdges( angle, addExisting )
+
     def MeshToPassThroughAPoint(self, x, y, z):
         """
         Find the node closest to a point and moves it to a point location
@@ -4245,10 +4628,38 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             False if proper faces were not found
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.DeleteDiag(NodeID1, NodeID2)
 
+    def AddNodeOnSegment(self, Node1, Node2, position = 0.5):
+        """
+        Replace each triangle bound by Node1-Node2 segment with
+        two triangles by connecting a node made on the link with a node
+        opposite to the link.
+
+        Parameters:
+                Node1: ID of the first node
+                Node2: ID of the second node
+                position: location [0,1] of the new node on the segment
+        """
+        return self.editor.AddNodeOnSegment(Node1, Node2, position)
+
+    def AddNodeOnFace(self, face, x, y, z):
+        """
+        Split a face into triangles by adding a new node onto the face
+        and connecting the new node with face nodes
+
+        Parameters:
+                face: ID of the face
+                x,y,z: coordinates of the new node
+        """
+        return self.editor.AddNodeOnFace(face, x, y, z)
+
     def Reorient(self, IDsOfElements=None):
         """
         Reorient elements by ids
@@ -4284,8 +4695,8 @@ class Mesh(metaclass = MeshMeta):
         Reorient faces contained in *the2DObject*.
 
         Parameters:
-                the2DObject: is a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` or list of IDs of 2D elements
-                theDirection: is a desired direction of normal of *theFace*.
+                the2DObject: a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` or list of IDs of 2D elements
+                theDirection: a desired direction of normal of *theFace*.
                         It can be either a GEOM vector or a list of coordinates [x,y,z].
                 theFaceOrPoint: defines a face of *the2DObject* whose normal will be
                         compared with theDirection. It can be either ID of face or a point
@@ -4322,6 +4733,29 @@ class Mesh(metaclass = MeshMeta):
             theFace = -1
         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
 
+    def Reorient2DByNeighbours(self, objectFaces, referenceFaces=[]):
+        """
+        Reorient faces contained in a list of *objectFaces*
+        equally to faces contained in a list of *referenceFaces*.
+
+        Parameters:
+                 objectFaces: list of :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` holding faces to reorient.
+                 referenceFaces: list of :class:`sub-mesh, group, filter <SMESH.SMESH_IDSource>` holding reference faces. It can be empty, then any face in *objectFaces* is used as the reference.
+
+        Returns:
+                 number of reoriented faces.
+        """
+        if not isinstance( objectFaces, list ):
+            objectFaces = [ objectFaces ]
+        for i,obj2D in enumerate( objectFaces ):
+            if isinstance( obj2D, Mesh ):
+                objectFaces[i] = obj2D.GetMesh()
+        if not isinstance( referenceFaces, list ):
+            referenceFaces = [ referenceFaces ]
+
+        return self.editor.Reorient2DByNeighbours( objectFaces, referenceFaces )
+
+
     def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
         """
         Reorient faces according to adjacent volumes.
@@ -4375,6 +4809,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
@@ -4399,6 +4837,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
@@ -4422,6 +4864,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
@@ -4445,6 +4891,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
@@ -4459,9 +4909,13 @@ class Mesh(metaclass = MeshMeta):
         a quadrangle.
 
         Parameters:
-                theElements: the faces to be splitted. This can be either 
+                theElements: the faces to be splitted. This can be either
                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
                         or a list of face IDs. By default all quadrangles are split
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         unRegister = genObjUnRegister()
         if isinstance( theElements, Mesh ):
@@ -4479,10 +4933,14 @@ class Mesh(metaclass = MeshMeta):
 
         Parameters:
                 IDsOfElements: the faces to be splitted
-                Diag13:        is used to choose a diagonal for splitting.
+                Diag13 (boolean):        is used to choose a diagonal for splitting.
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
@@ -4495,10 +4953,14 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
                 theObject: the object from which the list of elements is taken,
                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
-                Diag13:    is used to choose a diagonal for splitting.
+                Diag13 (boolean):    is used to choose a diagonal for splitting.
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
@@ -4516,9 +4978,13 @@ class Mesh(metaclass = MeshMeta):
                         to numerical functors.
 
         Returns:
-            * 1 if 1-3 diagonal is better, 
-            * 2 if 2-4 diagonal is better, 
+            * 1 if 1-3 diagonal is better,
+            * 2 if 2-4 diagonal is better,
             * 0 if error occurs.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
 
@@ -4531,6 +4997,10 @@ class Mesh(metaclass = MeshMeta):
                 method:  flags passing splitting method:
                         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
                         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         unRegister = genObjUnRegister()
         if isinstance( elems, Mesh ):
@@ -4555,6 +5025,10 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             elems: elements to split\: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or element IDs;
                 if None (default), all bi-quadratic elements will be split
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         unRegister = genObjUnRegister()
         if elems and isinstance( elems, list ) and isinstance( elems[0], int ):
@@ -4586,6 +5060,10 @@ class Mesh(metaclass = MeshMeta):
                 allDomains: if :code:`False`, only hexahedra adjacent to one closest
                         to *startHexPoint* are split, else *startHexPoint*
                         is used to find the facet to split in all domains present in *elems*.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         # IDSource
         unRegister = genObjUnRegister()
@@ -4615,6 +5093,10 @@ class Mesh(metaclass = MeshMeta):
     def SplitQuadsNearTriangularFacets(self):
         """
         Split quadrangle faces near triangular facets of volumes
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
         faces_array = self.GetElementsByType(SMESH.FACE)
         for face_id in faces_array:
@@ -4649,7 +5131,7 @@ class Mesh(metaclass = MeshMeta):
         This operation uses :doc:`pattern_mapping` functionality for splitting.
 
         Parameters:
-                theObject: the object from which the list of hexahedrons is taken; 
+                theObject: the object from which the list of hexahedrons is taken;
                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
                 theNode000,theNode001: within the range [0,7]; gives the orientation of the
                         pattern relatively each hexahedron: the (0,0,0) key-point of the pattern
@@ -4659,6 +5141,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 #    Pattern:
 #                     5.---------.6
@@ -4723,6 +5209,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             True in case of success, False otherwise.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 #        Pattern:     5.---------.6
 #                     /|#       /|
@@ -4880,6 +5370,10 @@ class Mesh(metaclass = MeshMeta):
 
         Warning:
             If *theSubMesh* is provided, the mesh can become non-conformal
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         if isinstance( theSubMesh, Mesh ):
@@ -4907,6 +5401,10 @@ class Mesh(metaclass = MeshMeta):
 
         Warning:
             If *theSubMesh* is provided, the mesh can become non-conformal
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         if theSubMesh:
@@ -4980,7 +5478,7 @@ class Mesh(metaclass = MeshMeta):
                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` of elements to make boundary around
 
         Returns:
-                tuple( long, mesh, groups )
+                tuple( long, mesh, group )
                        - long - number of added boundary elements
                        - mesh - the :class:`Mesh` where elements were added to
                        - group - the :class:`group <SMESH.SMESH_Group>` of boundary elements or None
@@ -5125,7 +5623,7 @@ class Mesh(metaclass = MeshMeta):
                 of all steps, else - size of each step
 
         Returns:
-            the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, 
+            the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
             empty list otherwise
         """
 
@@ -5157,7 +5655,8 @@ class Mesh(metaclass = MeshMeta):
                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
 
     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
-                              scaleFactors=[], linearVariation=False, basePoint=[] ):
+                              scaleFactors=[], linearVariation=False, basePoint=[],
+                              angles=[], anglesVariation=False):
         """
         Generate new elements by extrusion of the given elements and nodes
 
@@ -5171,15 +5670,19 @@ class Mesh(metaclass = MeshMeta):
             NbOfSteps: the number of steps
             MakeGroups: forces the generation of new groups from existing ones
             scaleFactors: optional scale factors to apply during extrusion
-            linearVariation: if *True*, scaleFactors are spread over all *scaleFactors*,
-                else scaleFactors[i] is applied to nodes at the i-th extrusion step
-            basePoint: optional scaling center; if not provided, a gravity center of
+            linearVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
+                else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
+            basePoint: optional scaling and rotation center; if not provided, a gravity center of
                 nodes and elements being extruded is used as the scaling center.
                 It can be either
 
                         - a list of tree components of the point or
                         - a node ID or
                         - a GEOM point
+            angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
+            anglesVariation: forces the computation of rotation angles as linear
+                variation of the given *angles* along path steps
         Returns:
             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
 
@@ -5204,13 +5707,17 @@ class Mesh(metaclass = MeshMeta):
             basePoint = self.geompyD.PointCoordinates( basePoint )
 
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
-        Parameters = StepVector.PS.parameters + var_separator + Parameters
+        scaleFactors,scaleParameters,hasVars = ParseParameters(scaleFactors)
+        angles,angleParameters,hasVars = ParseAngles(angles)
+        Parameters = StepVector.PS.parameters + var_separator + \
+                     Parameters + var_separator + \
+                     scaleParameters + var_separator + angleParameters
         self.mesh.SetParameters(Parameters)
 
         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
-                                                  StepVector, NbOfSteps,
+                                                  StepVector, NbOfSteps, MakeGroups,
                                                   scaleFactors, linearVariation, basePoint,
-                                                  MakeGroups)
+                                                  angles, anglesVariation )
 
 
     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
@@ -5271,6 +5778,8 @@ class Mesh(metaclass = MeshMeta):
         if isinstance( Elements, list ):
             if not Elements:
                 raise RuntimeError("Elements empty!")
+            if isinstance( Elements[0], Mesh ):
+                Elements = [ Elements[0].GetMesh() ]
             if isinstance( Elements[0], int ):
                 Elements = self.GetIDSource( Elements, SMESH.ALL )
                 unRegister.set( Elements )
@@ -5372,9 +5881,10 @@ class Mesh(metaclass = MeshMeta):
         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
                                              ExtrFlags, SewTolerance, MakeGroups)
 
-    def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None,
+    def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathObject, PathShape=None,
                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
-                                  HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False):
+                                  HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
+                                  ScaleFactors=[], ScalesVariation=False):
         """
         Generate new elements by extrusion of the given elements and nodes along the path.
         The path of extrusion must be a meshed edge.
@@ -5383,23 +5893,25 @@ class Mesh(metaclass = MeshMeta):
             Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
             Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
             Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
-            PathMesh: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
-            PathShape: shape (edge) defines the sub-mesh of PathMesh if PathMesh
-                contains not only path segments, else it can be None
+            PathObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` containing edges along which proceeds the extrusion
+            PathShape: optional shape (edge or wire) which defines the sub-mesh of the mesh defined by *PathObject* if the mesh contains not only path segments, else it can be None
             NodeStart: the first or the last node on the path. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             LinearVariation: forces the computation of rotation angles as linear
                 variation of the given Angles along path steps
             HasRefPoint: allows using the reference point
-            RefPoint: the reference point around which the shape is rotated (the mass center of the
-                shape by default). The User can specify any point as the Reference Point. 
+            RefPoint: optional scaling and rotation center (mass center of the extruded
+                elements by default). The User can specify any point as the Reference Point.
                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
             MakeGroups: forces the generation of new groups from existing ones
+            ScaleFactors: optional scale factors to apply during extrusion
+            ScalesVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
+                else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
 
         Returns:
-            list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
+            list of created :class:`groups <SMESH.SMESH_GroupBase>` and
             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
         Example: :ref:`tui_extrusion_along_path`
         """
@@ -5414,15 +5926,18 @@ class Mesh(metaclass = MeshMeta):
         if isinstance( RefPoint, list ):
             if not RefPoint: RefPoint = [0,0,0]
             RefPoint = SMESH.PointStruct( *RefPoint )
-        if isinstance( PathMesh, Mesh ):
-            PathMesh = PathMesh.GetMesh()
+        if isinstance( PathObject, Mesh ):
+            PathObject = PathObject.GetMesh()
         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
-        Parameters = AnglesParameters + var_separator + RefPoint.parameters
+        ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors)
+        Parameters = AnglesParameters + var_separator + \
+                     RefPoint.parameters + var_separator + ScalesParameters
         self.mesh.SetParameters(Parameters)
         return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces,
-                                                     PathMesh, PathShape, NodeStart,
+                                                     PathObject, PathShape, NodeStart,
                                                      HasAngles, Angles, LinearVariation,
-                                                     HasRefPoint, RefPoint, MakeGroups)
+                                                     HasRefPoint, RefPoint, MakeGroups,
+                                                     ScaleFactors, ScalesVariation)
 
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
                             HasAngles=False, Angles=[], LinearVariation=False,
@@ -5436,9 +5951,9 @@ class Mesh(metaclass = MeshMeta):
             Base: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`, or list of ids of elements for extrusion
             Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
             NodeStart: the start node from Path. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles in radians
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             LinearVariation: forces the computation of rotation angles as linear
                 variation of the given Angles along path steps
             HasRefPoint: allows using the reference point
@@ -5479,9 +5994,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles in radians
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5497,6 +6012,8 @@ class Mesh(metaclass = MeshMeta):
         Example: :ref:`tui_extrusion_along_path`
         """
 
+        if not IDsOfElements:
+            IDsOfElements = [ self.GetMesh() ]
         n,e,f = [],IDsOfElements,IDsOfElements
         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape,
                                                NodeStart, HasAngles, Angles,
@@ -5518,9 +6035,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5530,7 +6047,7 @@ class Mesh(metaclass = MeshMeta):
                 variation of the given Angles along path steps
 
         Returns:
-            list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
+            list of created :class:`groups <SMESH.SMESH_GroupBase>` and
             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
         Example: :ref:`tui_extrusion_along_path`
@@ -5556,9 +6073,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint:  the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5568,7 +6085,7 @@ class Mesh(metaclass = MeshMeta):
                 variation of the given Angles along path steps
 
         Returns:
-            list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
+            list of created :class:`groups <SMESH.SMESH_GroupBase>` and
             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
         Example: :ref:`tui_extrusion_along_path`
@@ -5594,9 +6111,9 @@ class Mesh(metaclass = MeshMeta):
             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
             PathShape: shape (edge) defines the sub-mesh for the path
             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
-            HasAngles: allows the shape to be rotated around the path
-                to get the resulting mesh in a helical fashion
-            Angles: list of angles
+            HasAngles: not used obsolete
+            Angles: list of angles in radians. Nodes at each extrusion step are rotated
+                around *basePoint*, additionally to previous steps.
             HasRefPoint: allows using the reference point
             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
                 The User can specify any point as the Reference Point.
@@ -5606,7 +6123,7 @@ class Mesh(metaclass = MeshMeta):
                 variation of the given Angles along path steps
 
         Returns:
-            list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
+            list of created :class:`groups <SMESH.SMESH_GroupBase>` and
             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
         Example: :ref:`tui_extrusion_along_path`
@@ -5626,7 +6143,7 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             IDsOfElements: list of elements ids
             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
-            theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
+            theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
                 If the *Mirror* is a geom object this parameter is unnecessary
             Copy: allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
             MakeGroups: forces the generation of new groups from existing ones (if Copy)
@@ -5654,7 +6171,7 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             IDsOfElements: the list of elements ids
             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
-            theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
+            theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
                 If the *Mirror* is a geom object this parameter is unnecessary
             MakeGroups: to generate new groups from existing ones
             NewMeshName: a name of the new mesh to create
@@ -5681,7 +6198,7 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
-            theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
+            theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
                 If the *Mirror* is a geom object this parameter is unnecessary
             Copy: allows copying the element (Copy==True) or replacing it with its mirror (Copy==False)
             MakeGroups: forces the generation of new groups from existing ones (if Copy)
@@ -5709,7 +6226,7 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
-            theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
+            theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
                 If the *Mirror* is a geom object this parameter is unnecessary
             MakeGroups: forces the generation of new groups from existing ones
             NewMeshName: the name of the new mesh to create
@@ -6016,7 +6533,7 @@ class Mesh(metaclass = MeshMeta):
             theObject (SMESH.SMESH_IDSource): the source object (mesh, sub-mesh, group or filter)
             theValue (float): signed offset size
             MakeGroups (boolean): forces the generation of new groups from existing ones
-            CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, 
+            CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements,
                           False means to remove original elements.
             NewMeshName (string): the name of a mesh to create. If empty, offset elements are added to this mesh
 
@@ -6029,8 +6546,8 @@ class Mesh(metaclass = MeshMeta):
         theValue,Parameters,hasVars = ParseParameters(Value)
         mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName)
         self.mesh.SetParameters(Parameters)
-        if mesh_groups[0]:
-            return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
+        if mesh_groups[0]:
+            return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
         return mesh_groups
 
     def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
@@ -6056,7 +6573,7 @@ class Mesh(metaclass = MeshMeta):
 
         Parameters:
             Tolerance: the value of tolerance
-            SubMeshOrGroup: :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`
+            SubMeshOrGroup: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or of node IDs
             exceptNodes: list of either SubMeshes, Groups or node IDs to exclude from search
             SeparateCornerAndMediumNodes: if *True*, in quadratic mesh puts
                 corner and medium nodes in separate groups thus preventing
@@ -6067,13 +6584,23 @@ class Mesh(metaclass = MeshMeta):
         """
 
         unRegister = genObjUnRegister()
-        if (isinstance( SubMeshOrGroup, Mesh )):
-            SubMeshOrGroup = SubMeshOrGroup.GetMesh()
+        if not isinstance( SubMeshOrGroup, list ):
+            SubMeshOrGroup = [ SubMeshOrGroup ]
+        for i,obj in enumerate( SubMeshOrGroup ):
+            if isinstance( obj, Mesh ):
+                SubMeshOrGroup = [ obj.GetMesh() ]
+                break
+            if isinstance( obj, int ):
+                SubMeshOrGroup = [ self.GetIDSource( SubMeshOrGroup, SMESH.NODE )]
+                unRegister.set( SubMeshOrGroup )
+                break
+
         if not isinstance( exceptNodes, list ):
             exceptNodes = [ exceptNodes ]
         if exceptNodes and isinstance( exceptNodes[0], int ):
             exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
             unRegister.set( exceptNodes )
+
         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
                                                         exceptNodes, SeparateCornerAndMediumNodes)
 
@@ -6084,48 +6611,88 @@ class Mesh(metaclass = MeshMeta):
         Parameters:
             GroupsOfNodes: a list of groups of nodes IDs for merging.
                 E.g. [[1,12,13],[25,4]] means that nodes 12, 13 and 4 will be removed and replaced
-                in all elements and groups by nodes 1 and 25 correspondingly
+                in all elements and mesh groups by nodes 1 and 25 correspondingly
             NodesToKeep: nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
                 If *NodesToKeep* does not include a node to keep for some group to merge,
                 then the first node in the group is kept.
             AvoidMakingHoles: prevent merging nodes which cause removal of elements becoming
                 invalid
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
-        # NodesToKeep are converted to SMESH.SMESH_IDSource in meshEditor.MergeNodes()
         self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles )
 
-    def FindEqualElements (self, MeshOrSubMeshOrGroup=None):
+    def FindEqualElements (self, MeshOrSubMeshOrGroup=None, exceptElements=[]):
         """
         Find the elements built on the same nodes.
 
         Parameters:
-            MeshOrSubMeshOrGroup: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
+            MeshOrSubMeshOrGroup: :class:`mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or element IDs to check for equal elements
+            exceptElements: list of either SubMeshes, Groups or elements IDs to exclude from search
+
 
         Returns:
             the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
         """
 
-        if not MeshOrSubMeshOrGroup:
-            MeshOrSubMeshOrGroup=self.mesh
+        unRegister = genObjUnRegister()
+        if MeshOrSubMeshOrGroup is None:
+            MeshOrSubMeshOrGroup = [ self.mesh ]
         elif isinstance( MeshOrSubMeshOrGroup, Mesh ):
-            MeshOrSubMeshOrGroup = MeshOrSubMeshOrGroup.GetMesh()
-        return self.editor.FindEqualElements( MeshOrSubMeshOrGroup )
-
-    def MergeElements(self, GroupsOfElementsID):
+            MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup.GetMesh() ]
+        elif not isinstance( MeshOrSubMeshOrGroup, list ):
+            MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup ]
+        if isinstance( MeshOrSubMeshOrGroup[0], int ):
+            MeshOrSubMeshOrGroup = [ self.GetIDSource( MeshOrSubMeshOrGroup, SMESH.ALL )]
+            unRegister.set( MeshOrSubMeshOrGroup )
+        for item in MeshOrSubMeshOrGroup:
+            if isinstance( item, Mesh ):
+                MeshOrSubMeshOrGroup = [ item.GetMesh() ]
+
+        if not isinstance( exceptElements, list ):
+            exceptElements = [ exceptElements ]
+        if exceptElements and isinstance( exceptElements[0], int ):
+            exceptElements = [ self.GetIDSource( exceptElements, SMESH.ALL )]
+            unRegister.set( exceptElements )
+
+        return self.editor.FindEqualElements( MeshOrSubMeshOrGroup, exceptElements )
+
+    def MergeElements(self, GroupsOfElementsID, ElementsToKeep=[]):
         """
         Merge elements in each given group.
 
         Parameters:
             GroupsOfElementsID: a list of groups (lists) of elements IDs for merging
                 (e.g. [[1,12,13],[25,4]] means that elements 12, 13 and 4 will be removed and
-                replaced in all groups by elements 1 and 25)
+                replaced in all mesh groups by elements 1 and 25)
+            ElementsToKeep: elements to keep in the mesh: a list of groups, sub-meshes or node IDs.
+                If *ElementsToKeep* does not include an element to keep for some group to merge,
+                then the first element in the group is kept.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
-        self.editor.MergeElements(GroupsOfElementsID)
+        unRegister = genObjUnRegister()
+        if ElementsToKeep:
+            if not isinstance( ElementsToKeep, list ):
+                ElementsToKeep = [ ElementsToKeep ]
+            if isinstance( ElementsToKeep[0], int ):
+                ElementsToKeep = [ self.GetIDSource( ElementsToKeep, SMESH.ALL )]
+                unRegister.set( ElementsToKeep )
+
+        self.editor.MergeElements( GroupsOfElementsID, ElementsToKeep )
 
     def MergeEqualElements(self):
         """
         Leave one element and remove all other elements built on the same nodes.
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         self.editor.MergeEqualElements()
@@ -6140,14 +6707,17 @@ class Mesh(metaclass = MeshMeta):
 
         return self.editor.FindFreeBorders( ClosedOnly )
 
-    def FillHole(self, holeNodes):
+    def FillHole(self, holeNodes, groupName=""):
         """
         Fill with 2D elements a hole defined by a SMESH.FreeBorder.
 
         Parameters:
-            FreeBorder: either a SMESH.FreeBorder or a list on node IDs. These nodes
+            holeNodes: either a SMESH.FreeBorder or a list on node IDs. These nodes
                 must describe all sequential nodes of the hole border. The first and the last
                 nodes must be the same. Use :meth:`FindFreeBorders` to get nodes of holes.
+            groupName (string): name of a group to add new faces
+        Returns:
+            a :class:`group <SMESH.SMESH_GroupBase>` containing the new faces; or :code:`None` if `groupName` == ""
         """
 
 
@@ -6155,7 +6725,7 @@ class Mesh(metaclass = MeshMeta):
             holeNodes = SMESH.FreeBorder(nodeIDs=holeNodes)
         if not isinstance( holeNodes, SMESH.FreeBorder ):
             raise TypeError("holeNodes must be either SMESH.FreeBorder or list of integer and not %s" % holeNodes)
-        self.editor.FillHole( holeNodes )
+        return self.editor.FillHole( holeNodes, groupName )
 
     def FindCoincidentFreeBorders (self, tolerance=0.):
         """
@@ -6192,6 +6762,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             a number of successfully sewed groups
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         if freeBorders and isinstance( freeBorders, list ):
@@ -6223,6 +6797,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
+
+        Note:
+                This operation can create gaps in numeration of nodes or elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
@@ -6236,6 +6814,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
@@ -6248,6 +6830,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
+
+        Note:
+                This operation can create gaps in numeration of elements.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
@@ -6266,6 +6852,10 @@ class Mesh(metaclass = MeshMeta):
 
         Returns:
             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
+
+        Note:
+                This operation can create gaps in numeration of nodes.
+                Call :meth:`RenumberElements` to remove the gaps.
         """
 
         return self.editor.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
@@ -6274,7 +6864,7 @@ class Mesh(metaclass = MeshMeta):
 
     def ChangeElemNodes(self, ide, newIDs):
         """
-        Set new nodes for the given element.
+        Set new nodes for the given element. Number of nodes should be kept.
 
         Parameters:
             ide: the element ID
@@ -6324,7 +6914,7 @@ class Mesh(metaclass = MeshMeta):
 
         Parameters:
             theElements: container of elements to duplicate. It can be a
-                :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` 
+                :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
                 or a list of element IDs. If *theElements* is
                 a :class:`Mesh`, elements of highest dimension are duplicated
             theGroupName: a name of group to contain the generated elements.
@@ -6334,7 +6924,7 @@ class Mesh(metaclass = MeshMeta):
                 in any group.
 
         Returns:
-                a :class:`group <SMESH.SMESH_Group>` where the new elements are added. 
+                a :class:`group <SMESH.SMESH_Group>` where the new elements are added.
                 None if *theGroupName* == "".
         """
 
@@ -6603,9 +7193,9 @@ class Mesh(metaclass = MeshMeta):
         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
 
     def MakePolyLine(self, segments, groupName='', isPreview=False ):
-        """    
+        """
         Create a polyline consisting of 1D mesh elements each lying on a 2D element of
-        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+        the initial triangle mesh. Positions of new nodes are found by cutting the mesh by the
         plane passing through pairs of points specified by each :class:`SMESH.PolySegment` structure.
         If there are several paths connecting a pair of points, the shortest path is
         selected by the module. Position of the cutting plane is defined by the two
@@ -6615,13 +7205,13 @@ class Mesh(metaclass = MeshMeta):
         The vector goes from the middle point to the projection point. In case of planar
         mesh, the vector is normal to the mesh.
 
-        *segments* [i].vector returns the used vector which goes from the middle point to its projection.
+        In preview mode, *segments* [i].vector returns the used vector which goes from the middle point to its projection.
 
-        Parameters:        
+        Parameters:
             segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes.
             groupName: optional name of a group where created mesh segments will be added.
-            
-        """    
+
+        """
         editor = self.editor
         if isPreview:
             editor = self.mesh.GetMeshEditPreviewer()
@@ -6630,7 +7220,18 @@ class Mesh(metaclass = MeshMeta):
             segments[i].vector = seg.vector
         if isPreview:
             return editor.GetPreviewData()
-        return None        
+        return None
+
+    def MakeSlot(self, segmentGroup, width ):
+        """
+        Create a slot of given width around given 1D elements lying on a triangle mesh.
+        The slot is constructed by cutting faces by cylindrical surfaces made
+        around each segment. Segments are expected to be created by MakePolyLine().
+
+        Returns:
+               FaceEdge's located at the slot boundary
+        """
+        return self.editor.MakeSlot( segmentGroup, width )
 
     def GetFunctor(self, funcType ):
         """
@@ -6673,56 +7274,112 @@ class Mesh(metaclass = MeshMeta):
 
     def GetLength(self, elemId=None):
         """
-        Get length of 1D element or sum of lengths of all 1D mesh elements
+        Get length of given 1D elements or of all 1D mesh elements
 
         Parameters:
-            elemId: mesh element ID (if not defined - sum of length of all 1D elements will be calculated)
+            elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum length of all 1D elements will be calculated.
 
         Returns:
-            element's length value if *elemId* is specified or sum of all 1D mesh elements' lengths otherwise
+            Sum of lengths of given elements
         """
 
         length = 0
         if elemId == None:
             length = self.smeshpyD.GetLength(self)
+        elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
+            length = self.smeshpyD.GetLength(elemId)
+        elif elemId == []:
+            length = 0
+        elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
+            for obj in elemId:
+                length += self.smeshpyD.GetLength(obj)
+        elif isinstance(elemId, list) and isinstance(elemId[0], int):
+            unRegister = genObjUnRegister()
+            obj = self.GetIDSource( elemId )
+            unRegister.set( obj )
+            length = self.smeshpyD.GetLength( obj )
         else:
             length = self.FunctorValue(SMESH.FT_Length, elemId)
         return length
 
     def GetArea(self, elemId=None):
         """
-        Get area of 2D element or sum of areas of all 2D mesh elements
-        elemId mesh element ID (if not defined - sum of areas of all 2D elements will be calculated)
+        Get area of given 2D elements or of all 2D mesh elements
+
+        Parameters:
+            elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum area of all 2D elements will be calculated.
 
         Returns:
-            element's area value if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
+            Area of given element's if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
         """
 
         area = 0
         if elemId == None:
             area = self.smeshpyD.GetArea(self)
+        elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
+            area = self.smeshpyD.GetArea(elemId)
+        elif elemId == []:
+            area = 0
+        elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
+            for obj in elemId:
+                area += self.smeshpyD.GetArea(obj)
+        elif isinstance(elemId, list) and isinstance(elemId[0], int):
+            unRegister = genObjUnRegister()
+            obj = self.GetIDSource( elemId )
+            unRegister.set( obj )
+            area = self.smeshpyD.GetArea( obj )
         else:
             area = self.FunctorValue(SMESH.FT_Area, elemId)
         return area
 
     def GetVolume(self, elemId=None):
         """
-        Get volume of 3D element or sum of volumes of all 3D mesh elements
+        Get volume of given 3D elements or of all 3D mesh elements
 
         Parameters:
-            elemId: mesh element ID (if not defined - sum of volumes of all 3D elements will be calculated)
+            elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum volume of all 3D elements will be calculated.
 
         Returns:
-            element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
+            Sum element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
         """
 
         volume = 0
         if elemId == None:
-            volume = self.smeshpyD.GetVolume(self)
+            volume= self.smeshpyD.GetVolume(self)
+        elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
+            volume= self.smeshpyD.GetVolume(elemId)
+        elif elemId == []:
+            volume = 0
+        elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
+            for obj in elemId:
+                volume+= self.smeshpyD.GetVolume(obj)
+        elif isinstance(elemId, list) and isinstance(elemId[0], int):
+            unRegister = genObjUnRegister()
+            obj = self.GetIDSource( elemId )
+            unRegister.set( obj )
+            volume= self.smeshpyD.GetVolume( obj )
         else:
             volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
         return volume
 
+    def GetAngle(self, node1, node2, node3 ):
+        """
+        Computes a radian measure of an angle defined by 3 nodes: <(node1,node2,node3)
+
+        Parameters:
+                node1,node2,node3: IDs of the three nodes
+
+        Returns:
+            Angle in radians [0,PI]. -1 if failure case.
+        """
+        p1 = self.GetNodeXYZ( node1 )
+        p2 = self.GetNodeXYZ( node2 )
+        p3 = self.GetNodeXYZ( node3 )
+        if p1 and p2 and p3:
+            return self.smeshpyD.GetAngle( p1,p2,p3 )
+        return -1.
+
+
     def GetMaxElementLength(self, elemId):
         """
         Get maximum element length.
@@ -6844,6 +7501,121 @@ class Mesh(metaclass = MeshMeta):
     pass # end of Mesh class
 
 
+def _copy_netgen_param(dim, local_param, global_param):
+    if dim==1:
+        #TODO: Try to identify why we need to substract 1
+        local_param.NumberOfSegments(int(global_param.GetNbSegPerEdge())-1)
+    elif dim==2:
+        local_param.SetMaxSize(global_param.GetMaxSize())
+        local_param.SetMinSize(global_param.GetMinSize())
+        local_param.SetOptimize(global_param.GetOptimize())
+        local_param.SetFineness(global_param.GetFineness())
+        local_param.SetNbSegPerEdge(global_param.GetNbSegPerEdge())
+        local_param.SetNbSegPerRadius(global_param.GetNbSegPerRadius())
+        local_param.SetGrowthRate(global_param.GetGrowthRate()*0.9)
+        local_param.SetChordalError(global_param.GetChordalError())
+        local_param.SetChordalErrorEnabled(global_param.GetChordalErrorEnabled())
+        local_param.SetUseSurfaceCurvature(global_param.GetUseSurfaceCurvature())
+        local_param.SetUseDelauney(global_param.GetUseDelauney())
+        local_param.SetQuadAllowed(global_param.GetQuadAllowed())
+        local_param.SetWorstElemMeasure(global_param.GetWorstElemMeasure())
+        local_param.SetCheckChartBoundary(global_param.GetCheckChartBoundary())
+        local_param.SetNbThreads(global_param.GetNbThreads())
+    else:
+        local_param.SetMaxSize(global_param.GetMaxSize())
+        local_param.SetMinSize(global_param.GetMinSize())
+        local_param.SetOptimize(global_param.GetOptimize())
+        local_param.SetCheckOverlapping(global_param.GetCheckOverlapping())
+        local_param.SetCheckChartBoundary(global_param.GetCheckChartBoundary())
+        local_param.SetFineness(global_param.GetFineness())
+        local_param.SetNbSegPerEdge(global_param.GetNbSegPerEdge())
+        local_param.SetNbSegPerRadius(global_param.GetNbSegPerRadius())
+        local_param.SetGrowthRate(global_param.GetGrowthRate())
+        local_param.SetNbThreads(global_param.GetNbThreads())
+
+class ParallelMesh(Mesh):
+    """
+    Surcharge on Mesh for parallel computation of a mesh
+    """
+
+    def __init__(self, smeshpyD, geompyD, geom, param, nbThreads, name=0):
+        """
+        Create a parallel mesh.
+
+        Parameters:
+            geom: geometrical object for meshing
+            param: full mesh parameters
+            nbThreads: Number of threads for parallelisation.
+            name: the name for the new mesh.
+
+        Returns:
+            an instance of class :class:`ParallelMesh`.
+        """
+
+        if not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
+            raise ValueError("geom argument must be a geometry")
+
+        if not isinstance(param, NETGENPlugin._objref_NETGENPlugin_Hypothesis):
+            raise ValueError("param must come from NETGENPlugin")
+
+        if nbThreads < 1:
+            raise ValueError("Number of threads must be stricly greater than 1")
+
+        # Splitting geometry into 3D elements and all the 2D/1D into one compound
+        object_solids = geompyD.ExtractShapes(geom, geompyD.ShapeType["SOLID"],
+                                              True)
+
+        solids = []
+        isolid = 0
+        for solid in object_solids:
+            isolid += 1
+            geompyD.addToStudyInFather( geom, solid, 'Solid_{}'.format(isolid) )
+            solids.append(solid)
+
+        faces = []
+        iface = 0
+        for isolid, solid in enumerate(solids):
+            solid_faces = geompyD.ExtractShapes(solid, geompyD.ShapeType["FACE"],
+                                                True)
+            for face in solid_faces:
+                faces.append(face)
+                iface += 1
+                geompyD.addToStudyInFather(solid, face,
+                                           'Face_{}'.format(iface))
+
+        # Creating submesh for edges 1D/2D part
+
+        all_faces = geompyD.MakeCompound(faces)
+        geompyD.addToStudy(all_faces, 'Compound_1')
+        all_faces = geompyD.MakeGlueEdges(all_faces, 1e-07)
+        all_faces = geompyD.MakeGlueFaces(all_faces, 1e-07)
+        geompyD.addToStudy(all_faces, 'global2D')
+
+        super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom, name)
+
+        self.mesh.SetNbThreads(nbThreads)
+
+        self.UseExistingSegments()
+        self.UseExistingFaces()
+
+        algo2d = self.Triangle(geom=all_faces, algo="NETGEN_2D")
+        param2d = algo2d.Parameters()
+
+        _copy_netgen_param(2, param2d, param)
+
+        for solid_id, solid in enumerate(solids):
+            name = "Solid_{}".format(solid_id)
+            self.UseExistingSegments(geom=solid)
+            self.UseExistingFaces(geom=solid)
+            algo3d = self.Tetrahedron(geom=solid, algo="NETGEN_3D_Remote")
+
+            param3d = algo3d.Parameters()
+
+            _copy_netgen_param(3, param3d, param)
+
+    pass # End of ParallelMesh
+
+
 class meshProxy(SMESH._objref_SMESH_Mesh):
     """
     Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
@@ -6865,17 +7637,27 @@ class meshProxy(SMESH._objref_SMESH_Mesh):
     def ExportToMED(self, *args): # function removed
         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
-        while len(args) < 4:  # !!!! nb of parameters for ExportToMED IDL's method
-            args.append(True)
-        SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
+        args2 = list(args)
+        while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
+            args2.append(True)
+        SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
     def ExportPartToMED(self, *args): # 'version' parameter removed
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
         SMESH._objref_SMESH_Mesh.ExportPartToMED(self, *args)
     def ExportMED(self, *args): # signature of method changed
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
-        while len(args) < 4:  # !!!! nb of parameters for ExportToMED IDL's method
-            args.append(True)
-        SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
+        args2 = list(args)
+        while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
+            args2.append(True)
+        SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
+    def ExportUNV(self, *args): # renumber arg added
+        if len( args ) == 1:
+            args += True,
+        return SMESH._objref_SMESH_Mesh.ExportUNV(self, *args)
+    def ExportDAT(self, *args): # renumber arg added
+        if len( args ) == 1:
+            args += True,
+        return SMESH._objref_SMESH_Mesh.ExportDAT(self, *args)
     pass
 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
 
@@ -7131,7 +7913,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
     """