Salome HOME
22487: EDF 2778 SMESH: Add a GUI for the flat elements generation
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index 7028f073195510bbab4f9bfd46b2d8bfe08ef147..223cf9130641d3992182d67b70e9cba067548986 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
 ## @{
 
@@ -307,7 +317,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
@@ -520,25 +530,19 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return aMesh
 
     ## Creates a Mesh object(s) importing data from the given MED file
-    #  @return a list of Mesh class instances
+    #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromMED( self,theFileName ):
         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
-        aMeshes = []
-        for iMesh in range(len(aSmeshMeshes)) :
-            aMesh = Mesh(self, self.geompyD, aSmeshMeshes[iMesh])
-            aMeshes.append(aMesh)
+        aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
     ## Creates a Mesh object(s) importing data from the given SAUV file
-    #  @return a list of Mesh class instances
+    #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromSAUV( self,theFileName ):
         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
-        aMeshes = []
-        for iMesh in range(len(aSmeshMeshes)) :
-            aMesh = Mesh(self, self.geompyD, aSmeshMeshes[iMesh])
-            aMeshes.append(aMesh)
+        aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
     ## Creates a Mesh object importing data from the given STL file
@@ -550,18 +554,17 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return aMesh
 
     ## Creates Mesh objects importing data from the given CGNS file
-    #  @return an instance of Mesh class
+    #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromCGNS( self, theFileName ):
         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
-        aMeshes = []
-        for iMesh in range(len(aSmeshMeshes)) :
-            aMesh = Mesh(self, self.geompyD, aSmeshMeshes[iMesh])
-            aMeshes.append(aMesh)
+        aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
-    ## Creates a Mesh object importing data from the given GMF file
-    #  @return [ an instance of Mesh class, SMESH::ComputeError ]
+    ## Creates a Mesh object importing data from the given GMF file.
+    #  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 ):
         aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
@@ -675,10 +678,10 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                      Tolerance=1e-07):
         if not CritType in SMESH.FunctorType._items:
             raise TypeError, "CritType should be of SMESH.FunctorType"
-        aCriterion = self.GetEmptyCriterion()
+        aCriterion               = self.GetEmptyCriterion()
         aCriterion.TypeOfElement = elementType
-        aCriterion.Type = self.EnumToLong(CritType)
-        aCriterion.Tolerance = Tolerance
+        aCriterion.Type          = self.EnumToLong(CritType)
+        aCriterion.Tolerance     = Tolerance
 
         aThreshold = Threshold
 
@@ -732,6 +735,30 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             else:
                 raise ValueError,\
                       "The Threshold should be an ID of mesh face and not '%s'"%aThreshold
+        elif CritType == FT_ConnectedElements:
+            # Checks the Threshold
+            if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
+                aCriterion.ThresholdID = aThreshold.GetStudyEntry()
+                if not aCriterion.ThresholdID:
+                    name = aThreshold.GetName()
+                    if not name:
+                        name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
+                    aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
+            elif isinstance(aThreshold, int): # node id
+                aCriterion.Threshold = aThreshold
+            elif isinstance(aThreshold, list): # 3 point coordinates
+                if len( aThreshold ) < 3:
+                    raise ValueError, "too few point coordinates, must be 3"
+                aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
+            elif isinstance(aThreshold, str):
+                if aThreshold.isdigit():
+                    aCriterion.Threshold = aThreshold # node id
+                else:
+                    aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
+            else:
+                raise ValueError,\
+                      "The Threshold should either a VERTEX, or a node ID, "\
+                      "or a list of point coordinates and not '%s'"%aThreshold
         elif CritType == FT_ElemGeomType:
             # Checks the Threshold
             try:
@@ -808,6 +835,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @param UnaryOp  FT_LogicalNOT or FT_Undefined
     #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
     #         FT_LyingOnGeom, FT_CoplanarFaces and FT_EqualNodes criteria
+    #  @param mesh the mesh to initialize the filter with
     #  @return SMESH_Filter
     #
     #  <a href="../tui_filters_page.html#tui_filters">Example of Filters usage</a>
@@ -817,23 +845,31 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                   Compare=FT_EqualTo,
                   Threshold="",
                   UnaryOp=FT_Undefined,
-                  Tolerance=1e-07):
+                  Tolerance=1e-07,
+                  mesh=None):
         aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
         aFilterMgr = self.CreateFilterManager()
         aFilter = aFilterMgr.CreateFilter()
         aCriteria = []
         aCriteria.append(aCriterion)
         aFilter.SetCriteria(aCriteria)
+        if mesh:
+            if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
+            else                       : aFilter.SetMesh( mesh )
         aFilterMgr.UnRegister()
         return aFilter
 
     ## 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)
@@ -960,6 +996,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()
@@ -967,6 +1004,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)
@@ -977,11 +1015,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)
@@ -1021,6 +1060,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)
@@ -1077,6 +1154,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
@@ -1113,12 +1191,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:
@@ -1136,16 +1214,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
@@ -1334,7 +1424,10 @@ class Mesh:
                 if errText: errText += ". "
                 errText += err.comment
                 if allReasons != "":allReasons += "\n"
-                allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
+                if ok:
+                    allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
+                else:
+                    allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
                 pass
 
             # Treat hyp errors
@@ -1470,13 +1563,24 @@ 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 )
+            geom_name = geom.GetName()
+        isAlgo = hyp._narrow( SMESH_Algo )
         TreatHypoStatus( status, hyp_name, geom_name, isAlgo )
         return status
 
@@ -1544,14 +1648,30 @@ class Mesh:
     #  @param version MED format version(MED_V2_1 or MED_V2_2)
     #  @param overwrite boolean parameter for overwriting/not overwriting the file
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
+    #  @param autoDimension: if @c True (default), a space dimension of a MED mesh can be either
+    #         - 1D if all mesh nodes lie on OX coordinate axis, or
+    #         - 2D if all mesh nodes lie on XOY coordinate plane, or
+    #         - 3D in the rest cases.
+    #         If @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):
-        if meshPart:
+    def ExportMED(self, f, auto_groups=0, version=MED_V2_2,
+                  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 )
+                unRegister.set( meshPart )
+            self.mesh.ExportPartToMED( meshPart, f, auto_groups, version, overwrite, autoDimension,
+                                       fields, geomAssocFields)
         else:
-            self.mesh.ExportToMEDX(f, auto_groups, version, overwrite)
+            self.mesh.ExportToMEDX(f, auto_groups, version, overwrite, autoDimension)
 
     ## Exports the mesh in a file in SAUV format
     #  @param f is the file name
@@ -1568,8 +1688,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)
@@ -1580,8 +1702,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)
@@ -1593,8 +1717,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)
@@ -1605,21 +1731,27 @@ 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:
             meshPart = self.mesh
         self.mesh.ExportCGNS(meshPart, f, overwrite)
 
-    ## Exports the mesh in a file in GMF format
+    ## Exports the mesh in a file in GMF format.
+    #  GMF files must have .mesh extension for the ASCII format and .meshb for
+    #  the bynary format. Other extensions are not allowed.
     #  @param f is the file name
     #  @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:
@@ -1634,9 +1766,15 @@ class Mesh:
     #  @param opt boolean parameter for creating/not creating
     #         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
     #  @param overwrite boolean parameter for overwriting/not overwriting the file
+    #  @param autoDimension: if @c True (default), a space dimension of a MED mesh can be either
+    #         - 1D if all mesh nodes lie on OX coordinate axis, or
+    #         - 2D if all mesh nodes lie on XOY coordinate plane, or
+    #         - 3D in the rest cases.
+    #
+    #         If @a autoDimension is @c False, the space dimension is always 3.
     #  @ingroup l2_impexp
-    def ExportToMED(self, f, version, opt=0, overwrite=1):
-        self.mesh.ExportToMEDX(f, opt, version, overwrite)
+    def ExportToMED(self, f, version, opt=0, overwrite=1, autoDimension=True):
+        self.mesh.ExportToMEDX(f, opt, version, overwrite, autoDimension)
 
     # Operations with groups:
     # ----------------------
@@ -1792,7 +1930,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):
@@ -1942,12 +2080,6 @@ class Mesh:
     def GetIDSource(self, ids, elemType):
         return self.editor.MakeIDSource(ids, elemType)
 
-    ## Gets MED Mesh
-    #  @return an instance of SALOME_MED::MESH
-    #  @ingroup l1_auxiliary
-    def GetMEDMesh(self):
-        return self.mesh.GetMEDMesh()
-
 
     # Get informations about mesh contents:
     # ------------------------------------
@@ -2025,6 +2157,12 @@ class Mesh:
     def NbTrianglesOfOrder(self, elementOrder):
         return self.mesh.NbTrianglesOfOrder(elementOrder)
 
+    ## Returns the number of biquadratic triangles in the mesh
+    #  @return an integer value
+    #  @ingroup l1_meshinfo
+    def NbBiQuadTriangles(self):
+        return self.mesh.NbBiQuadTriangles()
+
     ## Returns the number of quadrangles in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
@@ -2179,6 +2317,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()
@@ -2313,6 +2457,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):
@@ -2398,7 +2548,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)
@@ -2431,6 +2581,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)
@@ -2443,11 +2594,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):
@@ -2500,10 +2652,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.
@@ -2773,11 +2927,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 )
@@ -2831,7 +2987,6 @@ class Mesh:
         return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
 
     ## Splits quadrangles into triangles.
-    #
     #  @param IDsOfElements the faces to be splitted.
     #  @param theCriterion   is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting. If @a theCriterion is None, which is a default
@@ -2862,6 +3017,22 @@ class Mesh:
         Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.QuadToTriObject(theObject, Functor)
 
+    ## Splits each of given quadrangles into 4 triangles. A node is added at the center of
+    #  a quadrangle.
+    #  @param theElements the faces to be splitted. This can be either mesh, sub-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.
     #  @param IDsOfElements the faces to be splitted
     #  @param Diag13        is used to choose a diagonal for splitting.
@@ -2894,16 +3065,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, 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 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 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
     #
@@ -3053,7 +3268,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,
@@ -3071,7 +3287,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,
@@ -3087,7 +3304,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,
@@ -3105,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 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,
@@ -3124,6 +3343,8 @@ class Mesh:
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
     #  @ingroup l2_modif_tofromqu
     def ConvertToQuadratic(self, theForce3d, theSubMesh=None, theToBiQuad=False):
+        if isinstance( theSubMesh, Mesh ):
+            theSubMesh = theSubMesh.mesh
         if theToBiQuad:
             self.editor.ConvertToBiQuadratic(theForce3d,theSubMesh)
         else:
@@ -3131,6 +3352,9 @@ class Mesh:
                 self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
             else:
                 self.editor.ConvertToQuadratic(theForce3d)
+        error = self.editor.GetLastError()
+        if error and error.comment:
+            print error.comment
             
     ## Converts the mesh from quadratic to ordinary,
     #  deletes old quadratic elements, \n replacing
@@ -3164,16 +3388,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)
@@ -3482,8 +3708,10 @@ class Mesh:
     #  @param LinearVariation forces the computation of rotation angles as linear
     #                         variation of the given Angles along path steps
     #  @param HasRefPoint allows using the reference point
-    #  @param RefPoint the point around which the shape is rotated (the mass center of the shape by default).
+    #  @param RefPoint the point around which the elements are rotated (the mass
+    #         center of the elements by default).
     #         The User can specify any point as the Reference Point.
+    #         RefPoint can be either GEOM Vertex, [x,y,z] or SMESH.PointStruct
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @param ElemType type of elements for extrusion (if param Base is a mesh)
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
@@ -3492,9 +3720,12 @@ class Mesh:
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
                             HasAngles, Angles, LinearVariation,
                             HasRefPoint, RefPoint, MakeGroups, ElemType):
-        if ( isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object)):
+        if isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object):
             RefPoint = self.smeshpyD.GetPointStruct(RefPoint)
             pass
+        elif isinstance( RefPoint, list ):
+            RefPoint = PointStruct(*RefPoint)
+            pass
         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
         Parameters = AnglesParameters + var_separator + RefPoint.parameters
         self.mesh.SetParameters(Parameters)
@@ -3851,10 +4082,12 @@ 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( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
@@ -3875,10 +4108,12 @@ class Mesh:
     #  @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( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
@@ -3973,9 +4208,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)
@@ -3984,26 +4219,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 )):
@@ -4011,7 +4248,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)
@@ -4086,7 +4323,32 @@ class Mesh:
     def GetLastCreatedElems(self):
         return self.editor.GetLastCreatedElems()
 
-     ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Clears sequences of nodes and elements created by mesh edition oparations
+    #  @ingroup l1_auxiliary
+    def ClearLastCreated(self):
+        self.editor.ClearLastCreated()
+
+    ## Creates Duplicates given elements, i.e. creates new elements based on the 
+    #  same nodes as the given ones.
+    #  @param theElements - container of elements to duplicate. It can be a Mesh,
+    #         sub-mesh, group, filter or a list of element IDs.
+    # @param theGroupName - a name of group to contain the generated elements.
+    #                    If a group with such a name already exists, the new elements
+    #                    are added to the existng group, else a new group is created.
+    #                    If \a theGroupName is empty, new elements are not added 
+    #                    in any group.
+    # @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
     #  @param theNodes identifiers of nodes to be doubled
     #  @param theModifiedElems identifiers of elements to be updated by the new (doubled)
     #         nodes. If list of element identifiers is empty then nodes are doubled but
@@ -4241,9 +4503,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.
@@ -4276,26 +4540,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
@@ -4348,7 +4627,7 @@ class Mesh:
         return self._valueFromFunctor(SMESH.FT_Skew, elemId)
 
     pass # end of Mesh class
-    
+
 ## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
@@ -4439,6 +4718,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( ":" ):
     #
@@ -4447,7 +4748,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 )