Salome HOME
22860: EDF 9944 SMESH: Regression when scaling a mesh
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index ef4c73e57652f563ebf206ba0b30a01603d61c22..1445061eb1d05cb0f4b40d5a6b6e67b1e8d7c908 100644 (file)
@@ -1,9 +1,9 @@
-# Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
-# version 2.1 of the License.
+# version 2.1 of the License, or (at your option) any later version.
 #
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -73,7 +73,7 @@
 ##   @defgroup l2_modif_invdiag  Diagonal inversion of elements
 ##   @defgroup l2_modif_unitetri Uniting triangles
 ##   @defgroup l2_modif_changori Changing orientation of elements
-##   @defgroup l2_modif_cutquadr Cutting quadrangles
+##   @defgroup l2_modif_cutquadr Cutting elements
 ##   @defgroup l2_modif_smooth   Smoothing
 ##   @defgroup l2_modif_extrurev Extrusion and Revolution
 ##   @defgroup l2_modif_patterns Pattern mapping
@@ -93,6 +93,16 @@ import SALOME
 import SALOMEDS
 import os
 
+class MeshMeta(type):
+    def __instancecheck__(cls, inst):
+        """Implement isinstance(inst, cls)."""
+        return any(cls.__subclasscheck__(c)
+                   for c in {type(inst), inst.__class__})
+
+    def __subclasscheck__(cls, sub):
+        """Implement issubclass(sub, cls)."""
+        return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
+
 ## @addtogroup l1_auxiliary
 ## @{
 
@@ -197,12 +207,15 @@ def GetName(obj):
     raise RuntimeError, "Null or invalid object"
 
 ## Prints error message if a hypothesis was not assigned.
-def TreatHypoStatus(status, hypName, geomName, isAlgo):
+def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
     if isAlgo:
         hypType = "algorithm"
     else:
         hypType = "hypothesis"
         pass
+    reason = ""
+    if hasattr( status, "__getitem__" ):
+        status,reason = status[0],status[1]
     if status == HYP_UNKNOWN_FATAL :
         reason = "for unknown reason"
     elif status == HYP_INCOMPATIBLE :
@@ -225,17 +238,24 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo):
     elif status == HYP_HIDING_ALGO:
         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
     elif status == HYP_NEED_SHAPE:
-        reason = "Algorithm can't work without shape"
+        reason = "algorithm can't work without shape"
+    elif status == HYP_INCOMPAT_HYPS:
+        pass
     else:
         return
-    hypName = '"' + hypName + '"'
-    geomName= '"' + geomName+ '"'
-    if status < HYP_UNKNOWN_FATAL and not geomName =='""':
-        print hypName, "was assigned to",    geomName,"but", reason
-    elif not geomName == '""':
-        print hypName, "was not assigned to",geomName,":", reason
+    where = geomName
+    if where:
+        where = '"%s"' % geomName
+        if mesh:
+            meshName = GetName( mesh )
+            if meshName and meshName != NO_NAME:
+                where = '"%s" in "%s"' % ( geomName, meshName )
+    if status < HYP_UNKNOWN_FATAL and where:
+        print '"%s" was assigned to %s but %s' %( hypName, where, reason )
+    elif where:
+        print '"%s" was not assigned to %s : %s' %( hypName, where, reason )
     else:
-        print hypName, "was not assigned:", reason
+        print '"%s" was not assigned : %s' %( hypName, reason )
         pass
 
 ## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
@@ -307,7 +327,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = range(4)
 
     # Methods of splitting a hexahedron into tetrahedra
-    Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3
+    Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
 
     def __new__(cls):
         global engine
@@ -373,10 +393,16 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     def init_smesh(self,theStudy,geompyD = None):
         #print "init_smesh"
         self.SetCurrentStudy(theStudy,geompyD)
-
-    ## Creates an empty Mesh. This mesh can have an underlying geometry.
-    #  @param obj the Geometrical object on which the mesh is built. If not defined,
-    #             the mesh will have no underlying geometry.
+        if theStudy:
+            global notebook
+            notebook.myStudy = theStudy
+
+    ## Creates a mesh. This can be either an empty mesh, possibly having an underlying geometry,
+    #  or a mesh wrapping a CORBA mesh given as a parameter.
+    #  @param obj either (1) a CORBA mesh (SMESH._objref_SMESH_Mesh) got e.g. by calling
+    #         salome.myStudy.FindObjectID("0:1:2:3").GetObject() or
+    #         (2) a Geometrical object for meshing or
+    #         (3) none.
     #  @param name the name for the new mesh.
     #  @return an instance of Mesh class.
     #  @ingroup l2_construct
@@ -440,7 +466,9 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @return SMESH.AxisStruct
     #  @ingroup l1_auxiliary
     def GetAxisStruct(self,theObj):
+        import GEOM
         edges = self.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"] )
@@ -452,14 +480,18 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             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])
-            return axis
+            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 )
             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
-            return axis
-        return None
+            axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
+        elif theObj.GetShapeType() == GEOM.VERTEX:
+            x,y,z = self.geompyD.PointCoordinates( theObj )
+            axis = AxisStruct( x,y,z, 1,0,0,)
+            axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
+        return axis
 
     # From SMESH_Gen interface:
     # ------------------------
@@ -504,6 +536,12 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             notebook = salome_notebook.NoteBook( theStudy )
         else:
             notebook = salome_notebook.NoteBook( salome_notebook.PseudoStudyForNoteBook() )
+        if theStudy:
+            sb = theStudy.NewBuilder()
+            sc = theStudy.FindComponent("SMESH")
+            if sc: sb.LoadWith(sc, self)
+            pass
+        pass
 
     ## Gets the current study
     #  @ingroup l1_auxiliary
@@ -552,8 +590,8 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return aMeshes, aStatus
 
     ## Creates a Mesh object importing data from the given GMF file.
-    #  GMF files have .mesh extension for the ASCII format and .meshb for
-    #  the bynary format.
+    #  GMF files must have .mesh extension for the ASCII format and .meshb for
+    #  the binary format.
     #  @return [ an instance of Mesh class, SMESH.ComputeError ]
     #  @ingroup l2_impexp
     def CreateMeshesFromGMF( self, theFileName ):
@@ -595,7 +633,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #                  pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart
     #  @param meshName a name of the new mesh
     #  @param toCopyGroups to create in the new mesh groups the copied elements belongs to
-    #  @param toKeepIDs to preserve IDs of the copied elements or not
+    #  @param toKeepIDs to preserve order of the copied elements or not
     #  @return an instance of Mesh class
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
         if (isinstance( meshPart, Mesh )):
@@ -851,11 +889,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
     ## Creates a filter from criteria
     #  @param criteria a list of criteria
+    #  @param binOp binary operator used when binary operator of criteria is undefined
     #  @return SMESH_Filter
     #
     #  <a href="../tui_filters_page.html#tui_filters">Example of Filters usage</a>
     #  @ingroup l1_controls
-    def GetFilterFromCriteria(self,criteria):
+    def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
+        for i in range( len( criteria ) - 1 ):
+            if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
+                criteria[i].BinaryOp = self.EnumToLong( binOp )
         aFilterMgr = self.CreateFilterManager()
         aFilter = aFilterMgr.CreateFilter()
         aFilter.SetCriteria(criteria)
@@ -982,6 +1024,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         if not hasattr(src1, "_narrow"): return None
         src1 = src1._narrow(SMESH.SMESH_IDSource)
         if not src1: return None
+        unRegister = genObjUnRegister()
         if id1 != 0:
             m = src1.GetMesh()
             e = m.GetMeshEditor()
@@ -989,6 +1032,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 src1 = e.MakeIDSource([id1], SMESH.FACE)
             else:
                 src1 = e.MakeIDSource([id1], SMESH.NODE)
+            unRegister.set( src1 )
             pass
         if hasattr(src2, "_narrow"):
             src2 = src2._narrow(SMESH.SMESH_IDSource)
@@ -999,11 +1043,12 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                     src2 = e.MakeIDSource([id2], SMESH.FACE)
                 else:
                     src2 = e.MakeIDSource([id2], SMESH.NODE)
+                unRegister.set( src2 )
                 pass
             pass
         aMeasurements = self.CreateMeasurements()
+        unRegister.set( aMeasurements )
         result = aMeasurements.MinDistance(src1, src2)
-        aMeasurements.UnRegister()
         return result
 
     ## Get bounding box of the specified object(s)
@@ -1043,6 +1088,44 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMeasurements.UnRegister()
         return result
 
+    ## Get sum of lengths of all 1D elements in the mesh object.
+    #  @param obj mesh, submesh or group
+    #  @return sum of lengths of all 1D elements
+    #  @ingroup l1_measurements
+    def GetLength(self, obj):
+        if isinstance(obj, Mesh): obj = obj.mesh
+        if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
+        aMeasurements = self.CreateMeasurements()
+        value = aMeasurements.Length(obj)
+        aMeasurements.UnRegister()
+        return value
+
+    ## Get sum of areas of all 2D elements in the mesh object.
+    #  @param obj mesh, submesh or group
+    #  @return sum of areas of all 2D elements
+    #  @ingroup l1_measurements
+    def GetArea(self, obj):
+        if isinstance(obj, Mesh): obj = obj.mesh
+        if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
+        aMeasurements = self.CreateMeasurements()
+        value = aMeasurements.Area(obj)
+        aMeasurements.UnRegister()
+        return value
+
+    ## Get sum of volumes of all 3D elements in the mesh object.
+    #  @param obj mesh, submesh or group
+    #  @return sum of volumes of all 3D elements
+    #  @ingroup l1_measurements
+    def GetVolume(self, obj):
+        if isinstance(obj, Mesh): obj = obj.mesh
+        if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
+        aMeasurements = self.CreateMeasurements()
+        value = aMeasurements.Volume(obj)
+        aMeasurements.UnRegister()
+        return value
+
+    pass # end of class smeshBuilder
+
 import omniORB
 #Registering the new proxy for SMESH_Gen
 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
@@ -1099,6 +1182,7 @@ def New( study, instance=None):
 #  new nodes and elements and by changing the existing entities), to get information
 #  about a mesh and to export a mesh into different formats.
 class Mesh:
+    __metaclass__ = MeshMeta
 
     geom = 0
     mesh = 0
@@ -1135,12 +1219,12 @@ class Mesh:
                     else:
                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
                     geompyD.addToStudy( self.geom, geo_name )
-                self.mesh = self.smeshpyD.CreateMesh(self.geom)
+                self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
 
             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
                 self.SetMesh(obj)
         else:
-            self.mesh = self.smeshpyD.CreateEmptyMesh()
+            self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
         if name:
             self.smeshpyD.SetName(self.mesh, name)
         elif objHasName:
@@ -1158,16 +1242,28 @@ class Mesh:
             if isinstance( attr, algoCreator ):
                 #print "algoCreator ", attrName
                 setattr( self, attrName, attr.copy( self ))
+                pass
+            pass
+        pass
 
+    ## Destructor. Clean-up resources
+    def __del__(self):
+        if self.mesh:
+            #self.mesh.UnRegister()
+            pass
+        pass
+        
     ## Initializes the Mesh object from an instance of SMESH_Mesh interface
     #  @param theMesh a SMESH_Mesh object
     #  @ingroup l2_construct
     def SetMesh(self, theMesh):
-        if self.mesh: self.mesh.UnRegister()
+        # 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.mesh.Register()
             self.geom = self.mesh.GetShapeToMesh()
+        pass
 
     ## Returns the mesh, that is an instance of SMESH_Mesh interface
     #  @return a SMESH_Mesh object
@@ -1446,7 +1542,7 @@ class Mesh:
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             salome.sg.updateObjBrowser(1)
 
-    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
+    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
@@ -1459,8 +1555,7 @@ class Mesh:
             self.Triangle().LengthFromEdges()
             pass
         if dim > 2 :
-            from salome.NETGENPlugin.NETGENPluginBuilder import NETGEN
-            self.Tetrahedron(NETGEN)
+            self.Tetrahedron()
             pass
         return self.Compute()
 
@@ -1495,14 +1590,25 @@ class Mesh:
             if not geom:
                 geom = self.mesh.GetShapeToMesh()
             pass
-        AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
-        status = self.mesh.AddHypothesis(geom, hyp)
-        isAlgo = hyp._narrow( SMESH_Algo )
+        isApplicable = True
+        if self.mesh.HasShapeToMesh():
+            hyp_type     = hyp.GetName()
+            lib_name     = hyp.GetLibName()
+            checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
+            if checkAll and geom:
+                checkAll = geom.GetType() == 37
+            isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
+        if isApplicable:
+            AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
+            status = self.mesh.AddHypothesis(geom, hyp)
+        else:
+            status = HYP_BAD_GEOMETRY,""
         hyp_name = GetName( hyp )
         geom_name = ""
         if geom:
-            geom_name = GetName( geom )
-        TreatHypoStatus( status, hyp_name, geom_name, isAlgo )
+            geom_name = geom.GetName()
+        isAlgo = hyp._narrow( SMESH_Algo )
+        TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
         return status
 
     ## Return True if an algorithm of hypothesis is assigned to a given shape
@@ -1573,15 +1679,24 @@ class Mesh:
     #         - 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 @a autoDimension is @c False, the space dimension is always 3.
+    #  @param fields : list of GEOM fields defined on the shape to mesh.
+    #  @param 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.
     #  @ingroup l2_impexp
     def ExportMED(self, f, auto_groups=0, version=MED_V2_2,
-                  overwrite=1, meshPart=None, autoDimension=True):
-        if meshPart:
+                  overwrite=1, meshPart=None, autoDimension=True, fields=[], geomAssocFields=''):
+        if meshPart or fields or geomAssocFields:
+            unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
-            self.mesh.ExportPartToMED( meshPart, f, auto_groups, version, overwrite, autoDimension)
+                unRegister.set( meshPart )
+            self.mesh.ExportPartToMED( meshPart, f, auto_groups, version, overwrite, autoDimension,
+                                       fields, geomAssocFields)
         else:
             self.mesh.ExportToMEDX(f, auto_groups, version, overwrite, autoDimension)
 
@@ -1600,8 +1715,10 @@ class Mesh:
     #  @ingroup l2_impexp
     def ExportDAT(self, f, meshPart=None):
         if meshPart:
+            unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+                unRegister.set( meshPart )
             self.mesh.ExportPartToDAT( meshPart, f )
         else:
             self.mesh.ExportDAT(f)
@@ -1612,8 +1729,10 @@ class Mesh:
     #  @ingroup l2_impexp
     def ExportUNV(self, f, meshPart=None):
         if meshPart:
+            unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+                unRegister.set( meshPart )
             self.mesh.ExportPartToUNV( meshPart, f )
         else:
             self.mesh.ExportUNV(f)
@@ -1625,8 +1744,10 @@ class Mesh:
     #  @ingroup l2_impexp
     def ExportSTL(self, f, ascii=1, meshPart=None):
         if meshPart:
+            unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+                unRegister.set( meshPart )
             self.mesh.ExportPartToSTL( meshPart, f, ascii )
         else:
             self.mesh.ExportSTL(f, ascii)
@@ -1637,8 +1758,10 @@ class Mesh:
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
     #  @ingroup l2_impexp
     def ExportCGNS(self, f, overwrite=1, meshPart=None):
+        unRegister = genObjUnRegister()
         if isinstance( meshPart, list ):
             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+            unRegister.set( meshPart )
         if isinstance( meshPart, Mesh ):
             meshPart = meshPart.mesh
         elif not meshPart:
@@ -1652,8 +1775,10 @@ class Mesh:
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
     #  @ingroup l2_impexp
     def ExportGMF(self, f, meshPart=None):
+        unRegister = genObjUnRegister()
         if isinstance( meshPart, list ):
             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+            unRegister.set( meshPart )
         if isinstance( meshPart, Mesh ):
             meshPart = meshPart.mesh
         elif not meshPart:
@@ -1757,7 +1882,12 @@ class Mesh:
     #  @ingroup l2_grps_create
     def MakeGroupByIds(self, groupName, elementType, elemIDs):
         group = self.mesh.CreateGroup(elementType, groupName)
-        group.Add(elemIDs)
+        if hasattr( elemIDs, "GetIDs" ):
+            if hasattr( elemIDs, "SetMesh" ):
+                elemIDs.SetMesh( self.GetMesh() )
+            group.AddFrom( elemIDs )
+        else:
+            group.Add(elemIDs)
         return group
 
     ## Creates a mesh group by the given conditions
@@ -1769,7 +1899,7 @@ class Mesh:
     #  @param UnaryOp FT_LogicalNOT or FT_Undefined
     #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
     #         FT_LyingOnGeom, FT_CoplanarFaces criteria
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroup(self,
                   groupName,
@@ -1786,40 +1916,32 @@ class Mesh:
     ## Creates a mesh group by the given criterion
     #  @param groupName the name of the mesh group
     #  @param Criterion the instance of Criterion class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByCriterion(self, groupName, Criterion):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aCriteria = []
-        aCriteria.append(Criterion)
-        aFilter.SetCriteria(aCriteria)
-        group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
-        return group
+        return self.MakeGroupByCriteria( groupName, [Criterion] )
 
     ## Creates a mesh group by the given criteria (list of criteria)
     #  @param groupName the name of the mesh group
     #  @param theCriteria the list of criteria
-    #  @return SMESH_Group
+    #  @param binOp binary operator used when binary operator of criteria is undefined
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
-    def MakeGroupByCriteria(self, groupName, theCriteria):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aFilter.SetCriteria(theCriteria)
+    def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
+        aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
         group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
         return group
 
     ## Creates a mesh group by the given filter
     #  @param groupName the name of the mesh group
     #  @param theFilter the instance of Filter class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByFilter(self, groupName, theFilter):
-        group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
-        theFilter.SetMesh( self.mesh )
-        group.AddFrom( theFilter )
+        #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
+        #theFilter.SetMesh( self.mesh )
+        #group.AddFrom( theFilter )
+        group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
         return group
 
     ## Removes a group
@@ -1832,7 +1954,7 @@ class Mesh:
     def RemoveGroupWithContents(self, group):
         self.mesh.RemoveGroupWithContents(group)
 
-    ## Gets the list of groups existing in the mesh
+    ## Gets the list of groups existing in the mesh in the order of creation (starting from the oldest one)
     #  @return a sequence of SMESH_GroupBase
     #  @ingroup l2_grps_create
     def GetGroups(self):
@@ -2219,6 +2341,12 @@ class Mesh:
     def GetElementGeomType(self, id):
         return self.mesh.GetElementGeomType(id)
 
+    ## Returns the shape type of mesh element
+    #  @return the value from SMESH::GeometryType enumeration
+    #  @ingroup l1_meshinfo
+    def GetElementShape(self, id):
+        return self.mesh.GetElementShape(id)
+
     ## Returns the list of submesh elements IDs
     #  @param Shape a geom object(sub-shape) IOR
     #         Shape must be the sub-shape of a ShapeToMesh()
@@ -2353,6 +2481,12 @@ class Mesh:
     def GetElemFaceNodes(self,elemId, faceIndex):
         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
 
+    ## Returns three components of normal of given mesh face
+    #  (or an empty array in KO case)
+    #  @ingroup l1_meshinfo
+    def GetFaceNormal(self, faceId, normalized=False):
+        return self.mesh.GetFaceNormal(faceId,normalized)
+
     ## Returns an element based on all given nodes.
     #  @ingroup l1_meshinfo
     def FindElementByNodes(self,nodes):
@@ -2438,7 +2572,7 @@ class Mesh:
 
         aMeasurements = self.smeshpyD.CreateMeasurements()
         aMeasure = aMeasurements.MinDistance(id1, id2)
-        aMeasurements.UnRegister()
+        genObjUnRegister([aMeasurements,id1, id2])
         return aMeasure
 
     ## Get bounding box of the specified object(s)
@@ -2457,7 +2591,7 @@ class Mesh:
 
     ## Get measure structure specifying bounding box data of the specified object(s)
     #  @param IDs single source object or list of source objects or list of nodes/elements IDs
-    #  @param isElem if @a objects is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
+    #  @param isElem if @a IDs is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
     #  @c False specifies that @a objects are nodes
     #  @return Measure structure
     #  @sa BoundingBox()
@@ -2471,6 +2605,7 @@ class Mesh:
         if len(IDs) > 0 and isinstance(IDs[0], int):
             IDs = [IDs]
         srclist = []
+        unRegister = genObjUnRegister()
         for o in IDs:
             if isinstance(o, Mesh):
                 srclist.append(o.mesh)
@@ -2483,11 +2618,12 @@ class Mesh:
                     srclist.append(self.editor.MakeIDSource(o, SMESH.FACE))
                 else:
                     srclist.append(self.editor.MakeIDSource(o, SMESH.NODE))
+                unRegister.set( srclist[-1] )
                 pass
             pass
         aMeasurements = self.smeshpyD.CreateMeasurements()
+        unRegister.set( aMeasurements )
         aMeasure = aMeasurements.BoundingBox(srclist)
-        aMeasurements.UnRegister()
         return aMeasure
 
     # Mesh edition (SMESH_MeshEditor functionality):
@@ -2540,10 +2676,12 @@ class Mesh:
     #          can be retrieved from the returned object by calling GetIDs()
     #  @ingroup l2_modif_add
     def Add0DElementsToAllNodes(self, theObject, theGroupName=""):
+        unRegister = genObjUnRegister()
         if isinstance( theObject, Mesh ):
             theObject = theObject.GetMesh()
         if isinstance( theObject, list ):
             theObject = self.GetIDSource( theObject, SMESH.ALL )
+            unRegister.set( theObject )
         return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName )
 
     ## Creates a ball element on a node with given ID.
@@ -2813,11 +2951,13 @@ class Mesh:
     #  @return number of reoriented faces
     #  @ingroup l2_modif_changori
     def Reorient2D(self, the2DObject, theDirection, theFaceOrPoint ):
+        unRegister = genObjUnRegister()
         # check the2DObject
         if isinstance( the2DObject, Mesh ):
             the2DObject = the2DObject.GetMesh()
         if isinstance( the2DObject, list ):
             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
+            unRegister.set( the2DObject )
         # check theDirection
         if isinstance( theDirection, geomBuilder.GEOM._objref_GEOM_Object):
             theDirection = self.smeshpyD.GetDirStruct( theDirection )
@@ -2837,6 +2977,37 @@ class Mesh:
             theFace = -1
         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
 
+    ## Reorient faces according to adjacent volumes.
+    #  @param the2DObject is a mesh, sub-mesh, group or list of
+    #         either IDs of faces or face groups.
+    #  @param the3DObject is a mesh, sub-mesh, group or list of IDs of volumes.
+    #  @param theOutsideNormal to orient faces to have their normals
+    #         pointing either \a outside or \a inside the adjacent volumes.
+    #  @return number of reoriented faces.
+    #  @ingroup l2_modif_changori
+    def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
+        unRegister = genObjUnRegister()
+        # check the2DObject
+        if not isinstance( the2DObject, list ):
+            the2DObject = [ the2DObject ]
+        elif the2DObject and isinstance( the2DObject[0], int ):
+            the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
+            unRegister.set( the2DObject )
+            the2DObject = [ the2DObject ]
+        for i,obj2D in enumerate( the2DObject ):
+            if isinstance( obj2D, Mesh ):
+                the2DObject[i] = obj2D.GetMesh()
+            if isinstance( obj2D, list ):
+                the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
+                unRegister.set( the2DObject[i] )
+        # check the3DObject
+        if isinstance( the3DObject, Mesh ):
+            the3DObject = the3DObject.GetMesh()
+        if isinstance( the3DObject, list ):
+            the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
+            unRegister.set( the3DObject )
+        return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
+
     ## Fuses the neighbouring triangles into quadrangles.
     #  @param IDsOfElements The triangles to be fused,
     #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
@@ -2907,12 +3078,14 @@ class Mesh:
     #         group or a list of face IDs. By default all quadrangles are split
     #  @ingroup l2_modif_cutquadr
     def QuadTo4Tri (self, theElements=[]):
+        unRegister = genObjUnRegister()
         if isinstance( theElements, Mesh ):
             theElements = theElements.mesh
         elif not theElements:
             theElements = self.mesh
         elif isinstance( theElements, list ):
             theElements = self.GetIDSource( theElements, SMESH.FACE )
+            unRegister.set( theElements )
         return self.editor.QuadTo4Tri( theElements )
 
     ## Splits quadrangles into triangles.
@@ -2947,16 +3120,60 @@ class Mesh:
         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
 
     ## Splits volumic elements into tetrahedrons
-    #  @param elemIDs either list of elements or mesh or group or submesh
-    #  @param method  flags passing splitting method: Hex_5Tet, Hex_6Tet, Hex_24Tet
-    #         Hex_5Tet - split the hexahedron into 5 tetrahedrons, etc
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param 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.
     #  @ingroup l2_modif_cutquadr
-    def SplitVolumesIntoTetra(self, elemIDs, method=smeshBuilder.Hex_5Tet ):
-        if isinstance( elemIDs, Mesh ):
-            elemIDs = elemIDs.GetMesh()
-        if ( isinstance( elemIDs, list )):
-            elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME)
-        self.editor.SplitVolumesIntoTetra(elemIDs, method)
+    def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
+        unRegister = genObjUnRegister()
+        if isinstance( elems, Mesh ):
+            elems = elems.GetMesh()
+        if ( isinstance( elems, list )):
+            elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
+            unRegister.set( elems )
+        self.editor.SplitVolumesIntoTetra(elems, method)
+
+    ## Splits hexahedra into prisms
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param startHexPoint a point used to find a hexahedron for which @a facetNormal
+    #         gives a normal vector defining facets to split into triangles.
+    #         @a startHexPoint can be either a triple of coordinates or a vertex.
+    #  @param facetNormal a normal to a facet to split into triangles of a
+    #         hexahedron found by @a startHexPoint.
+    #         @a facetNormal can be either a triple of coordinates or an edge.
+    #  @param method  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
+    #         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
+    #  @param allDomains if @c False, only hexahedra adjacent to one closest
+    #         to @a startHexPoint are split, else @a startHexPoint
+    #         is used to find the facet to split in all domains present in @a elems.
+    #  @ingroup l2_modif_cutquadr
+    def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
+                                 method=smeshBuilder.Hex_2Prisms, allDomains=False ):
+        # IDSource
+        unRegister = genObjUnRegister()
+        if isinstance( elems, Mesh ):
+            elems = elems.GetMesh()
+        if ( isinstance( elems, list )):
+            elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
+            unRegister.set( elems )
+            pass
+        # axis
+        if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
+            startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
+        elif isinstance( startHexPoint, list ):
+            startHexPoint = SMESH.PointStruct( startHexPoint[0],
+                                               startHexPoint[1],
+                                               startHexPoint[2])
+        if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
+            facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
+        elif isinstance( facetNormal, list ):
+            facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
+                                                       facetNormal[1],
+                                                       facetNormal[2])
+        self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
+
+        self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
 
     ## Splits quadrangle faces near triangular facets of volumes
     #
@@ -3106,7 +3323,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
@@ -3124,7 +3342,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothObject(self, theObject, IDsOfFixedNodes,
@@ -3140,7 +3359,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
@@ -3158,7 +3378,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
@@ -3172,11 +3393,11 @@ class Mesh:
     #  them with quadratic with the same id.
     #  @param theForce3d new node creation method:
     #         0 - the medium node lies at the geometrical entity from which the mesh element is built
-    #         1 - the medium node lies at the middle of the line segments connecting start and end node of a mesh element
+    #         1 - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
     #  @ingroup l2_modif_tofromqu
-    def ConvertToQuadratic(self, theForce3d, theSubMesh=None, theToBiQuad=False):
+    def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
         if isinstance( theSubMesh, Mesh ):
             theSubMesh = theSubMesh.mesh
         if theToBiQuad:
@@ -3222,16 +3443,18 @@ class Mesh:
     #     the new mesh else only boundary elements will be copied into the new mesh
     #  @param toCopyExistingBondary - if true, not only new but also pre-existing
     #     boundary elements will be copied into the new mesh
-    #  @return tuple (mesh, group) where bondary elements were added to
+    #  @return tuple (mesh, group) where boundary elements were added to
     #  @ingroup l2_modif_edit
     def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
                          toCopyElements=False, toCopyExistingBondary=False):
+        unRegister = genObjUnRegister()
         if isinstance( elements, Mesh ):
             elements = elements.GetMesh()
         if ( isinstance( elements, list )):
             elemType = SMESH.ALL
             if elements: elemType = self.GetElementType( elements[0], iselem=True)
             elements = self.editor.MakeIDSource(elements, elemType)
+            unRegister.set( elements )
         mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName,
                                                    toCopyElements,toCopyExistingBondary)
         if mesh: mesh = self.smeshpyD.Mesh(mesh)
@@ -3239,7 +3462,7 @@ class Mesh:
 
     ##
     # @brief Creates missing boundary elements around either the whole mesh or 
-    #    groups of 2D elements
+    #    groups of elements
     #  @param dimension - defines type of boundary elements to create
     #  @param groupName - a name of group to store all boundary elements in,
     #    "" means not to create the group
@@ -3247,7 +3470,7 @@ class Mesh:
     #    mesh + created boundary elements; "" means not to create the new mesh
     #  @param toCopyAll - if true, the whole initial mesh will be copied into
     #    the new mesh else only boundary elements will be copied into the new mesh
-    #  @param groups - groups of 2D elements to make boundary around
+    #  @param groups - groups of elements to make boundary around
     #  @retval tuple( long, mesh, groups )
     #                 long - number of added boundary elements
     #                 mesh - the mesh where elements were added to
@@ -3260,12 +3483,12 @@ class Mesh:
         if mesh: mesh = self.smeshpyD.Mesh(mesh)
         return nb, mesh, group
 
-    ## Renumber mesh nodes
+    ## Renumber mesh nodes (Obsolete, does nothing)
     #  @ingroup l2_modif_renumber
     def RenumberNodes(self):
         self.editor.RenumberNodes()
 
-    ## Renumber mesh elements
+    ## Renumber mesh elements (Obsole, does nothing)
     #  @ingroup l2_modif_renumber
     def RenumberElements(self):
         self.editor.RenumberElements()
@@ -3445,6 +3668,44 @@ class Mesh:
                                       ExtrFlags, SewTolerance)
         return []
 
+    ## Generates new elements by extrusion along the normal to a discretized surface or wire
+    #  @param Elements container of elements to extrude;
+    #         it can be Mesh, Group, Sub-mesh, Filter or list of IDs;
+    #         Only faces can be extruded so far. Sub-mesh sould be a sub-mesh on geom faces.
+    #  @param StepSize length of one extrusion step (the total extrusion
+    #         length will be \a NbOfSteps * \a StepSize ).
+    #  @param NbOfSteps number of extrusion steps.
+    #  @param ByAverageNormal if True each node is translated by \a StepSize
+    #         along the average of the normal vectors to the faces sharing the node;
+    #         else each node is translated along the same average normal till
+    #         intersection with the plane got by translation of the face sharing
+    #         the node along its own normal by \a StepSize.
+    #  @param UseInputElemsOnly to use only \a Elements when computing extrusion direction
+    #         for every node of \a Elements.
+    #  @param MakeGroups forces generation of new groups from existing ones.
+    #  @param Dim dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
+    #         is not yet implemented. This parameter is used if \a Elements contains
+    #         both faces and edges, i.e. \a Elements is a Mesh.
+    #  @return the list of created groups (SMESH_GroupBase) if \a MakeGroups=True,
+    #          empty list otherwise.
+    #  @ingroup l2_modif_extrurev
+    def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
+                          ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
+        unRegister = genObjUnRegister()
+        if isinstance( Elements, Mesh ):
+            Elements = Elements.GetMesh()
+        if isinstance( Elements, list ):
+            if not Elements:
+                raise RuntimeError, "List of element IDs is empty!"
+            if not isinstance( Elements[0], int ):
+                raise RuntimeError, "List must contain element IDs and not %s"% Elements[0]
+            Elements = self.GetIDSource( Elements, SMESH.ALL )
+            unRegister.set( Elements )
+        StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
+        self.mesh.SetParameters(Parameters)
+        return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
+                                             UseInputElemsOnly, ByAverageNormal, MakeGroups, Dim)
+
     ## Generates new elements by extrusion of the elements which belong to the object
     #  @param theObject the object which elements should be processed.
     #                   It can be a mesh, a sub mesh or a group.
@@ -3757,12 +4018,14 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_trsf
-    def Mirror(self, IDsOfElements, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
@@ -3777,12 +4040,14 @@ class Mesh:
     #  @param NewMeshName a name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType, MakeGroups=0, NewMeshName=""):
+    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
                                           MakeGroups, NewMeshName)
         return Mesh(self.smeshpyD,self.geompyD,mesh)
@@ -3796,12 +4061,14 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_trsf
-    def MirrorObject (self, theObject, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
@@ -3816,12 +4083,14 @@ class Mesh:
     #  @param NewMeshName the name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType,MakeGroups=0, NewMeshName=""):
+    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
-        if (isinstance(Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+        if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
                                                 MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD,self.geompyD,mesh )
@@ -3906,7 +4175,7 @@ class Mesh:
 
     ## Scales the object
     #  @param theObject - the object to translate (mesh, submesh, or group)
-    #  @param thePoint - base point for scale
+    #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param Copy - allows copying the translated elements
     #  @param MakeGroups - forces the generation of new groups from existing
@@ -3914,10 +4183,14 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True,
     #          empty list otherwise
     def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False):
+        unRegister = genObjUnRegister()
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject, SMESH.ALL)
+            unRegister.set( theObject )
+        if ( isinstance( thePoint, list )):
+            thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
@@ -3932,16 +4205,20 @@ class Mesh:
 
     ## Creates a new mesh from the translated object
     #  @param theObject - the object to translate (mesh, submesh, or group)
-    #  @param thePoint - base point for scale
+    #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param MakeGroups - forces the generation of new groups from existing ones
     #  @param NewMeshName - the name of the newly created mesh
     #  @return instance of Mesh class
     def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""):
+        unRegister = genObjUnRegister()
         if (isinstance(theObject, Mesh)):
             theObject = theObject.GetMesh()
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject,SMESH.ALL)
+            unRegister.set( theObject )
+        if ( isinstance( thePoint, list )):
+            thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
@@ -4036,9 +4313,9 @@ class Mesh:
         self.mesh.SetParameters(Parameters)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
 
-    ## Finds groups of ajacent nodes within Tolerance.
+    ## Finds groups of adjacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
-    #  @return the list of groups of nodes
+    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindCoincidentNodes (self, Tolerance):
         return self.editor.FindCoincidentNodes(Tolerance)
@@ -4047,26 +4324,28 @@ class Mesh:
     #  @param Tolerance the value of tolerance
     #  @param SubMeshOrGroup SubMesh or Group
     #  @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
-    #  @return the list of groups of nodes
+    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]):
+        unRegister = genObjUnRegister()
         if (isinstance( SubMeshOrGroup, Mesh )):
             SubMeshOrGroup = SubMeshOrGroup.GetMesh()
         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)
 
     ## Merges nodes
-    #  @param GroupsOfNodes the list of groups of nodes
+    #  @param GroupsOfNodes a list of pairs of nodes IDs for merging (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def MergeNodes (self, GroupsOfNodes):
         self.editor.MergeNodes(GroupsOfNodes)
 
     ## Finds the elements built on the same nodes.
     #  @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
-    #  @return a list of groups of equal elements
+    #  @return the list of pairs of equal elements IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindEqualElements (self, MeshOrSubMeshOrGroup):
         if ( isinstance( MeshOrSubMeshOrGroup, Mesh )):
@@ -4074,7 +4353,7 @@ class Mesh:
         return self.editor.FindEqualElements(MeshOrSubMeshOrGroup)
 
     ## Merges elements in each given group.
-    #  @param GroupsOfElementsID groups of elements for merging
+    #  @param GroupsOfElementsID a list of pairs of elements IDs for merging (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def MergeElements(self, GroupsOfElementsID):
         self.editor.MergeElements(GroupsOfElementsID)
@@ -4166,10 +4445,12 @@ class Mesh:
     # @return a group where the new elements are added. None if theGroupName == "".
     #  @ingroup l2_modif_edit
     def DoubleElements(self, theElements, theGroupName=""):
+        unRegister = genObjUnRegister()
         if isinstance( theElements, Mesh ):
             theElements = theElements.mesh
         elif isinstance( theElements, list ):
             theElements = self.GetIDSource( theElements, SMESH.ALL )
+            unRegister.set( theElements )
         return self.editor.DoubleElements(theElements, theGroupName)
 
     ## Creates a hole in a mesh by doubling the nodes of some particular elements
@@ -4327,9 +4608,11 @@ class Mesh:
     # Triangles are transformed in prisms, and quadrangles in hexahedrons.
     # @param theDomains - list of groups of volumes
     # @param createJointElems - if TRUE, create the elements
+    # @param onAllBoundaries - if TRUE, the nodes and elements are also created on
+    #        the boundary between \a theDomains and the rest mesh
     # @return TRUE if operation has been completed successfully, FALSE otherwise
-    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
-       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
+    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
+       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
 
     ## Double nodes on some external faces and create flat elements.
     # Flat elements are mainly used by some types of mechanic calculations.
@@ -4362,26 +4645,41 @@ class Mesh:
             val = 0
         return val
 
-    ## Get length of 1D element.
-    #  @param elemId mesh element ID
-    #  @return element's length value
+    ## Get length of 1D element or sum of lengths of all 1D mesh elements
+    #  @param elemId mesh element ID (if not defined - sum of length of all 1D elements will be calculated)
+    #  @return element's length value if \a elemId is specified or sum of all 1D mesh elements' lengths otherwise
     #  @ingroup l1_measurements
-    def GetLength(self, elemId):
-        return self._valueFromFunctor(SMESH.FT_Length, elemId)
+    def GetLength(self, elemId=None):
+        length = 0
+        if elemId == None:
+            length = self.smeshpyD.GetLength(self)
+        else:
+            length = self._valueFromFunctor(SMESH.FT_Length, elemId)
+        return length
 
-    ## Get area of 2D element.
-    #  @param elemId mesh element ID
-    #  @return element's area value
+    ## Get area of 2D element or sum of areas of all 2D mesh elements
+    #  @param elemId mesh element ID (if not defined - sum of areas of all 2D elements will be calculated)
+    #  @return element's area value if \a elemId is specified or sum of all 2D mesh elements' areas otherwise
     #  @ingroup l1_measurements
-    def GetArea(self, elemId):
-        return self._valueFromFunctor(SMESH.FT_Area, elemId)
+    def GetArea(self, elemId=None):
+        area = 0
+        if elemId == None:
+            area = self.smeshpyD.GetArea(self)
+        else:
+            area = self._valueFromFunctor(SMESH.FT_Area, elemId)
+        return area
 
-    ## Get volume of 3D element.
-    #  @param elemId mesh element ID
-    #  @return element's volume value
+    ## Get volume of 3D element or sum of volumes of all 3D mesh elements
+    #  @param elemId mesh element ID (if not defined - sum of volumes of all 3D elements will be calculated)
+    #  @return element's volume value if \a elemId is specified or sum of all 3D mesh elements' volumes otherwise
     #  @ingroup l1_measurements
-    def GetVolume(self, elemId):
-        return self._valueFromFunctor(SMESH.FT_Volume3D, elemId)
+    def GetVolume(self, elemId=None):
+        volume = 0
+        if elemId == None:
+            volume = self.smeshpyD.GetVolume(self)
+        else:
+            volume = self._valueFromFunctor(SMESH.FT_Volume3D, elemId)
+        return volume
 
     ## Get maximum element length.
     #  @param elemId mesh element ID
@@ -4433,8 +4731,31 @@ class Mesh:
     def GetSkew(self, elemId):
         return self._valueFromFunctor(SMESH.FT_Skew, elemId)
 
+    ## Return minimal and maximal value of a given functor.
+    #  @param funType a functor type, an item of SMESH.FunctorType enum
+    #         (one of SMESH.FunctorType._items)
+    #  @param meshPart a part of mesh (group, sub-mesh) to treat
+    #  @return tuple (min,max)
+    #  @ingroup l1_measurements
+    def GetMinMax(self, funType, meshPart=None):
+        unRegister = genObjUnRegister()
+        if isinstance( meshPart, list ):
+            meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+            unRegister.set( meshPart )
+        if isinstance( meshPart, Mesh ):
+            meshPart = meshPart.mesh
+        fun = self._getFunctor( funType )
+        if fun:
+            if meshPart:
+                hist = fun.GetLocalHistogram( 1, False, meshPart )
+            else:
+                hist = fun.GetHistogram( 1, False )
+            if hist:
+                return hist[0].min, hist[0].max
+        return None
+
     pass # end of Mesh class
-    
+
 ## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
@@ -4525,6 +4846,28 @@ class hypMethodWrapper:
                 raise ValueError, detail # wrong variable name
 
         return result
+    pass
+
+# A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+class genObjUnRegister:
+
+    def __init__(self, genObj=None):
+        self.genObjList = []
+        self.set( genObj )
+        return
+
+    def set(self, genObj):
+        "Store one or a list of of SALOME.GenericObj'es"
+        if isinstance( genObj, list ):
+            self.genObjList.extend( genObj )
+        else:
+            self.genObjList.append( genObj )
+        return
+
+    def __del__(self):
+        for genObj in self.genObjList:
+            if genObj and hasattr( genObj, "UnRegister" ):
+                genObj.UnRegister()
 
 for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
     #
@@ -4533,7 +4876,8 @@ for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
     try:
         exec( "from salome.%s.%s import *" % (pluginName, pluginBuilderName))
     except Exception, e:
-        print "Exception while loading %s: %s" % ( pluginBuilderName, e )
+       from salome_utils import verbose
+       if verbose(): print "Exception while loading %s: %s" % ( pluginBuilderName, e )
         continue
     exec( "from salome.%s import %s" % (pluginName, pluginBuilderName))
     plugin = eval( pluginBuilderName )