Salome HOME
Merge branch 'occ/shaper2smesh'
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index 8b62ca6d2a34bebde51c5c90e858b7840147bbc0..2a6238966f401e92c36ec8af83f72b22cd9b9e5f 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -303,7 +303,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 +318,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
 """
@@ -473,6 +461,24 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             obj,name = name,obj
         return Mesh(self, self.geompyD, obj, 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 +517,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 +531,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 +567,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
@@ -731,10 +738,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,24 +750,38 @@ 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 CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
@@ -780,11 +801,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 +959,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 +1011,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 +1200,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 +1239,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" }
@@ -1391,13 +1470,16 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
 
     def GetGravityCenter(self, obj):
         """
-        Get gravity center of all nodes of the mesh object.
+        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)
+                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 +1488,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
@@ -1539,14 +1643,15 @@ 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()
+            if self.geom:
+                self.geompyD = self.geom.GetGen()
+                pass
         pass
 
     def GetMesh(self):
@@ -1559,6 +1664,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 +1715,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 +1745,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
@@ -1960,7 +2083,14 @@ 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>`
@@ -2182,11 +2312,17 @@ 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.
+                        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.
         """
         # process positional arguments
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
@@ -2198,6 +2334,7 @@ class Mesh(metaclass = MeshMeta):
         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.
         # process keywords arguments
         auto_groups     = kwargs.get("auto_groups", auto_groups)
         minor           = kwargs.get("minor", minor)
@@ -2206,14 +2343,20 @@ class Mesh(metaclass = MeshMeta):
         autoDimension   = kwargs.get("autoDimension", autoDimension)
         fields          = kwargs.get("fields", fields)
         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
+        z_tolerance     = kwargs.get("zTolerance", z_tolerance)
+
         # invoke engine's function
-        if meshPart or fields or geomAssocFields:
+        if meshPart or fields or geomAssocFields or z_tolerance > 0:
             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)
+
             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
-                                       fields, geomAssocFields)
+                                       fields, geomAssocFields, z_tolerance)
         else:
             self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
 
@@ -2399,12 +2542,31 @@ 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; 
@@ -2439,7 +2601,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,7 +2629,7 @@ class Mesh(metaclass = MeshMeta):
         tgeo = str(shape.GetShapeType())
         if tgeo == "VERTEX":
             typ = NODE
-        elif tgeo == "EDGE":
+        elif tgeo == "EDGE" or tgeo == "WIRE":
             typ = EDGE
         elif tgeo == "FACE" or tgeo == "SHELL":
             typ = FACE
@@ -2484,8 +2646,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 +2791,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 +2969,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 +2995,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 +3129,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" }
@@ -3438,16 +3618,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 +3805,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 +3870,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)
@@ -3793,6 +3993,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,6 +4010,10 @@ 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)
@@ -3816,6 +4024,10 @@ class Mesh(metaclass = MeshMeta):
 
         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()
@@ -3997,7 +4209,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 +4232,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 +4255,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 +4279,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 +4372,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,6 +4392,19 @@ 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:
@@ -4205,6 +4428,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 elements, 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,6 +4503,10 @@ 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)
@@ -4284,8 +4546,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
@@ -4375,6 +4637,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 +4665,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 +4692,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 +4719,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()
@@ -4462,6 +4740,10 @@ class Mesh(metaclass = MeshMeta):
                 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 +4761,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 +4781,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()
@@ -4519,6 +4809,10 @@ class Mesh(metaclass = MeshMeta):
             * 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 +4825,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 +4853,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 +4888,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 +4921,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:
@@ -4659,6 +4969,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 +5037,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 +5198,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 +5229,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 +5306,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
@@ -5157,7 +5483,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 +5498,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 +5535,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 +5606,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 +5709,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,20 +5721,22 @@ 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 
@@ -5414,15 +5754,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 +5779,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 +5822,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 +5840,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 +5863,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.
@@ -5556,9 +5901,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.
@@ -5594,9 +5939,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.
@@ -6056,7 +6401,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 +6412,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 +6439,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 +6535,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 +6553,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 +6590,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 +6625,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 +6642,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 +6658,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 +6680,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 +6692,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
@@ -6605,7 +7023,7 @@ class Mesh(metaclass = MeshMeta):
     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,12 +7033,12 @@ 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:
@@ -6630,7 +7048,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 +7102,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.
@@ -6865,17 +7350,19 @@ 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)
     pass
 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
 
@@ -7131,7 +7618,7 @@ class genObjUnRegister:
             if genObj and hasattr( genObj, "UnRegister" ):
                 genObj.UnRegister()
 
-for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
+for pluginName in os.environ[ "SMESH_MeshersList" ].split( os.pathsep ):
     """
     Bind methods creating mesher plug-ins to the Mesh class
     """