Salome HOME
Remove reference to NETGEN from AutomaticTetrahedralization(), a default
[modules/smesh.git] / src / SMESH_SWIG / smeshDC.py
index 3c36b1be6721ceb0c135ebd36e2219e706a58b91..624030f9f21d990349e1b10201b9d871b3da0ca3 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2013  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
 #  Author : Francis KLOSS, OCC
 #  Module : SMESH
 
-"""
- \namespace smesh
- \brief Module smesh
-"""
+## @package smesh
+#  Python API for SALOME %Mesh module
 
 ## @defgroup l1_auxiliary Auxiliary methods and structures
 ## @defgroup l1_creating  Creating meshes
@@ -89,6 +87,7 @@ import geompyDC
 
 import SMESH # This is necessary for back compatibility
 from   SMESH import *
+from   smesh_algorithm import Mesh_Algorithm
 
 import SALOME
 import SALOMEDS
@@ -187,7 +186,10 @@ def GetName(obj):
         if isinstance(obj, SALOMEDS._objref_SObject):
             # study object
             return obj.GetName()
-        ior  = salome.orb.object_to_string(obj)
+        try:
+            ior  = salome.orb.object_to_string(obj)
+        except:
+            ior = None
         if ior:
             # CORBA object
             studies = salome.myStudyManager.GetOpenStudies()
@@ -256,7 +258,8 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo):
 def AssureGeomPublished(mesh, geom, name=''):
     if not isinstance( geom, geompyDC.GEOM._objref_GEOM_Object ):
         return
-    if not geom.IsSame( mesh.geom ) and not geom.GetStudyEntry():
+    if not geom.GetStudyEntry() and \
+           mesh.smeshpyD.GetCurrentStudy():
         ## set the study
         studyID = mesh.smeshpyD.GetCurrentStudy()._get_StudyId()
         if studyID != mesh.geompyD.myStudyId:
@@ -273,15 +276,15 @@ def AssureGeomPublished(mesh, geom, name=''):
 
 ## Return the first vertex of a geomertical edge by ignoring orienation
 def FirstVertexOnCurve(edge):
-    from geompy import SubShapeAll, ShapeType, KindOfShape, PointCoordinates
+    from geompy import SubShapeAll, ShapeType, MakeVertexOnCurve, PointCoordinates
     vv = SubShapeAll( edge, ShapeType["VERTEX"])
     if not vv:
         raise TypeError, "Given object has no vertices"
     if len( vv ) == 1: return vv[0]
-    info = KindOfShape(edge)
-    xyz = info[1:4] # coords of the first vertex
-    xyz1  = PointCoordinates( vv[0] )
-    xyz2  = PointCoordinates( vv[1] )
+    v0   = MakeVertexOnCurve(edge,0.)
+    xyz  = PointCoordinates( v0 ) # coords of the first vertex
+    xyz1 = PointCoordinates( vv[0] )
+    xyz2 = PointCoordinates( vv[1] )
     dist1, dist2 = 0,0
     for i in range(3):
         dist1 += abs( xyz[i] - xyz1[i] )
@@ -329,7 +332,6 @@ class smeshDC(SMESH._objref_SMESH_Gen):
         return Mesh(self,self.geompyD,obj,name)
 
     ## Returns a long value from enumeration
-    #  Should be used for SMESH.FunctorType enumeration
     #  @ingroup l1_controls
     def EnumToLong(self,theItem):
         return theItem._v
@@ -443,6 +445,11 @@ class smeshDC(SMESH._objref_SMESH_Gen):
         self.geompyD=geompyD
         self.SetGeomEngine(geompyD)
         SMESH._objref_SMESH_Gen.SetCurrentStudy(self,theStudy)
+        global notebook
+        if theStudy:
+            notebook = salome_notebook.NoteBook( theStudy )
+        else:
+            notebook = salome_notebook.NoteBook( salome_notebook.PseudoStudyForNoteBook() )
 
     ## Gets the current study
     #  @ingroup l1_auxiliary
@@ -499,6 +506,16 @@ class smeshDC(SMESH._objref_SMESH_Gen):
             aMeshes.append(aMesh)
         return aMeshes, aStatus
 
+    ## Creates a Mesh object importing data from the given GMF file
+    #  @return [ an instance of Mesh class, SMESH::ComputeError ]
+    #  @ingroup l2_impexp
+    def CreateMeshesFromGMF( self, theFileName ):
+        aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
+                                                                        theFileName,
+                                                                        True)
+        if error.comment: print "*** CreateMeshesFromGMF() errors:\n", error.comment
+        return Mesh(self, self.geompyD, aSmeshMesh), error
+
     ## Concatenate the given meshes into one mesh.
     #  @return an instance of Mesh class
     #  @param meshes the meshes to combine into one mesh
@@ -506,8 +523,10 @@ class smeshDC(SMESH._objref_SMESH_Gen):
     #  @param mergeNodesAndElements if true, equal nodes and elements aremerged
     #  @param mergeTolerance tolerance for merging nodes
     #  @param allGroups forces creation of groups of all elements
+    #  @param name name of a new mesh
     def Concatenate( self, meshes, uniteIdenticalGroups,
-                     mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
+                     mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
+                     name = ""):
         if not meshes: return None
         for i,m in enumerate(meshes):
             if isinstance(m, Mesh):
@@ -520,7 +539,7 @@ class smeshDC(SMESH._objref_SMESH_Gen):
         else:
             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
-        aMesh = Mesh(self, self.geompyD, aSmeshMesh)
+        aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
         return aMesh
 
     ## Create a mesh by copying a part of another mesh.
@@ -623,10 +642,16 @@ class smeshDC(SMESH._objref_SMESH_Gen):
 
         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
                         FT_BelongToCylinder, FT_LyingOnGeom]:
-            # Checks the Threshold
+            # Checks that Threshold is GEOM object
             if isinstance(aThreshold, geompyDC.GEOM._objref_GEOM_Object):
                 aCriterion.ThresholdStr = GetName(aThreshold)
-                aCriterion.ThresholdID = salome.ObjectToID(aThreshold)
+                aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
+                if not aCriterion.ThresholdID:
+                    name = aCriterion.ThresholdStr
+                    if not name:
+                        name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
+                    aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
+                    #raise RuntimeError, "Threshold shape must be published"
             else:
                 print "Error: The Threshold should be a shape."
                 return None
@@ -635,7 +660,7 @@ class smeshDC(SMESH._objref_SMESH_Gen):
                 UnaryOp = FT_Undefined
                 pass
         elif CritType == FT_RangeOfIds:
-            # Checks the Threshold
+            # Checks that Threshold is string
             if isinstance(aThreshold, str):
                 aCriterion.ThresholdStr = aThreshold
             else:
@@ -644,7 +669,7 @@ class smeshDC(SMESH._objref_SMESH_Gen):
         elif CritType == FT_CoplanarFaces:
             # Checks the Threshold
             if isinstance(aThreshold, int):
-                aCriterion.ThresholdID = "%s"%aThreshold
+                aCriterion.ThresholdID = str(aThreshold)
             elif isinstance(aThreshold, str):
                 ID = int(aThreshold)
                 if ID < 1:
@@ -666,6 +691,20 @@ class smeshDC(SMESH._objref_SMESH_Gen):
                     return None
                 pass
             pass
+        elif CritType == FT_EntityType:
+            # Checks the Threshold
+            try:
+                aCriterion.Threshold = self.EnumToLong(aThreshold)
+                assert( aThreshold in SMESH.EntityType._items )
+            except:
+                if isinstance(aThreshold, int):
+                    aCriterion.Threshold = aThreshold
+                else:
+                    print "Error: The Threshold should be an integer or SMESH.EntityType."
+                    return None
+                pass
+            pass
+        
         elif CritType == FT_GroupColor:
             # Checks the Threshold
             try:
@@ -752,37 +791,42 @@ class smeshDC(SMESH._objref_SMESH_Gen):
     #  @return SMESH_NumericalFunctor
     #  @ingroup l1_controls
     def GetFunctor(self,theCriterion):
+        if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
+            return theCriterion
         aFilterMgr = self.CreateFilterManager()
+        functor = None
         if theCriterion == FT_AspectRatio:
-            return aFilterMgr.CreateAspectRatio()
+            functor = aFilterMgr.CreateAspectRatio()
         elif theCriterion == FT_AspectRatio3D:
-            return aFilterMgr.CreateAspectRatio3D()
+            functor = aFilterMgr.CreateAspectRatio3D()
         elif theCriterion == FT_Warping:
-            return aFilterMgr.CreateWarping()
+            functor = aFilterMgr.CreateWarping()
         elif theCriterion == FT_MinimumAngle:
-            return aFilterMgr.CreateMinimumAngle()
+            functor = aFilterMgr.CreateMinimumAngle()
         elif theCriterion == FT_Taper:
-            return aFilterMgr.CreateTaper()
+            functor = aFilterMgr.CreateTaper()
         elif theCriterion == FT_Skew:
-            return aFilterMgr.CreateSkew()
+            functor = aFilterMgr.CreateSkew()
         elif theCriterion == FT_Area:
-            return aFilterMgr.CreateArea()
+            functor = aFilterMgr.CreateArea()
         elif theCriterion == FT_Volume3D:
-            return aFilterMgr.CreateVolume3D()
+            functor = aFilterMgr.CreateVolume3D()
         elif theCriterion == FT_MaxElementLength2D:
-            return aFilterMgr.CreateMaxElementLength2D()
+            functor = aFilterMgr.CreateMaxElementLength2D()
         elif theCriterion == FT_MaxElementLength3D:
-            return aFilterMgr.CreateMaxElementLength3D()
+            functor = aFilterMgr.CreateMaxElementLength3D()
         elif theCriterion == FT_MultiConnection:
-            return aFilterMgr.CreateMultiConnection()
+            functor = aFilterMgr.CreateMultiConnection()
         elif theCriterion == FT_MultiConnection2D:
-            return aFilterMgr.CreateMultiConnection2D()
+            functor = aFilterMgr.CreateMultiConnection2D()
         elif theCriterion == FT_Length:
-            return aFilterMgr.CreateLength()
+            functor = aFilterMgr.CreateLength()
         elif theCriterion == FT_Length2D:
-            return aFilterMgr.CreateLength2D()
+            functor = aFilterMgr.CreateLength2D()
         else:
             print "Error: given parameter is not numerical functor type."
+        aFilterMgr.UnRegister()
+        return functor
 
     ## Creates hypothesis
     #  @param theHType mesh hypothesis type (string)
@@ -956,16 +1000,22 @@ class Mesh:
         self.geompyD=geompyD
         if obj is None:
             obj = 0
+        objHasName = False
         if obj != 0:
             if isinstance(obj, geompyDC.GEOM._objref_GEOM_Object):
                 self.geom = obj
+                objHasName = True
                 # publish geom of mesh (issue 0021122)
-                if not self.geom.GetStudyEntry():
+                if not self.geom.GetStudyEntry() and smeshpyD.GetCurrentStudy():
+                    objHasName = False
                     studyID = smeshpyD.GetCurrentStudy()._get_StudyId()
                     if studyID != geompyD.myStudyId:
                         geompyD.init_geom( smeshpyD.GetCurrentStudy())
                         pass
-                    geo_name = "%s_%s"%(self.geom.GetShapeType(), id(self.geom)%100)
+                    if name:
+                        geo_name = name + " shape"
+                    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)
 
@@ -973,15 +1023,16 @@ class Mesh:
                 self.SetMesh(obj)
         else:
             self.mesh = self.smeshpyD.CreateEmptyMesh()
-        if name != 0:
+        if name:
             self.smeshpyD.SetName(self.mesh, name)
-        elif obj != 0:
-            self.smeshpyD.SetName(self.mesh, GetName(obj))
+        elif objHasName:
+            self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
 
         if not self.geom:
             self.geom = self.mesh.GetShapeToMesh()
 
-        self.editor = self.mesh.GetMeshEditor()
+        self.editor   = self.mesh.GetMeshEditor()
+        self.functors = [None] * SMESH.FT_Undefined._v
 
         # set self to algoCreator's
         for attrName in dir(self):
@@ -993,8 +1044,11 @@ class Mesh:
     #  @param theMesh a SMESH_Mesh object
     #  @ingroup l2_construct
     def SetMesh(self, theMesh):
+        if self.mesh: self.mesh.UnRegister()
         self.mesh = theMesh
-        self.geom = self.mesh.GetShapeToMesh()
+        if self.mesh:
+            self.mesh.Register()
+            self.geom = self.mesh.GetShapeToMesh()
 
     ## Returns the mesh, that is an instance of SMESH_Mesh interface
     #  @return a SMESH_Mesh object
@@ -1068,19 +1122,25 @@ class Mesh:
         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
 
     ## Returns the mesh dimension depending on the dimension of the underlying shape
+    #  or, if the mesh is not based on any shape, basing on deimension of elements
     #  @return mesh dimension as an integer value [0,3]
     #  @ingroup l1_auxiliary
     def MeshDimension(self):
-        shells = self.geompyD.SubShapeAllIDs( self.geom, geompyDC.ShapeType["SHELL"] )
-        if len( shells ) > 0 :
-            return 3
-        elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
-            return 2
-        elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
-            return 1
+        if self.mesh.HasShapeToMesh():
+            shells = self.geompyD.SubShapeAllIDs( self.geom, geompyDC.ShapeType["SOLID"] )
+            if len( shells ) > 0 :
+                return 3
+            elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
+                return 2
+            elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
+                return 1
+            else:
+                return 0;
         else:
-            return 0;
-        pass
+            if self.NbVolumes() > 0: return 3
+            if self.NbFaces()   > 0: return 2
+            if self.NbEdges()   > 0: return 1
+        return 0
 
     ## Evaluates size of prospective mesh on a shape
     #  @return a list where i-th element is a number of elements of i-th SMESH.EntityType
@@ -1158,15 +1218,18 @@ class Mesh:
                     except:
                         shapeText = " on subshape #%s" % (err.subShapeID)
                 errText = ""
-                stdErrors = ["OK",                 #COMPERR_OK
-                             "Invalid input mesh", #COMPERR_BAD_INPUT_MESH
-                             "std::exception",     #COMPERR_STD_EXCEPTION
-                             "OCC exception",      #COMPERR_OCC_EXCEPTION
-                             "SALOME exception",   #COMPERR_SLM_EXCEPTION
-                             "Unknown exception",  #COMPERR_EXCEPTION
+                stdErrors = ["OK",                   #COMPERR_OK
+                             "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
+                             "std::exception",       #COMPERR_STD_EXCEPTION
+                             "OCC exception",        #COMPERR_OCC_EXCEPTION
+                             "..",                   #COMPERR_SLM_EXCEPTION
+                             "Unknown exception",    #COMPERR_EXCEPTION
                              "Memory allocation problem", #COMPERR_MEMORY_PB
-                             "Algorithm failed",   #COMPERR_ALGO_FAILED
-                             "Unexpected geometry"]#COMPERR_BAD_SHAPE
+                             "Algorithm failed",     #COMPERR_ALGO_FAILED
+                             "Unexpected geometry",  #COMPERR_BAD_SHAPE
+                             "Warning",              #COMPERR_WARNING
+                             "Computation cancelled",#COMPERR_CANCELED
+                             "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
                 if err.code > 0:
                     if err.code < len(stdErrors): errText = stdErrors[err.code]
                 else:
@@ -1174,7 +1237,7 @@ class Mesh:
                 if errText: errText += ". "
                 errText += err.comment
                 if allReasons != "":allReasons += "\n"
-                allReasons += '"%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
+                allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
                 pass
 
             # Treat hyp errors
@@ -1200,22 +1263,27 @@ class Mesh:
                 elif err.state == HYP_BAD_GEOMETRY:
                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
                               'geometry' % ( glob, dim, name ))
+                elif err.state == HYP_HIDDEN_ALGO:
+                    reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
+                              'algorithm of upper dimension generating %sD mesh'
+                              % ( glob, dim, name, glob, dim ))
                 else:
-                    reason = "For unknown reason."+\
-                             " Revise Mesh.Compute() implementation in smeshDC.py!"
+                    reason = ("For unknown reason. "
+                              "Developer, revise Mesh.Compute() implementation in smeshDC.py!")
                     pass
                 if allReasons != "":allReasons += "\n"
-                allReasons += reason
+                allReasons += "-  " + reason
                 pass
-            if allReasons != "":
-                print '"' + GetName(self.mesh) + '"',"has not been computed:"
+            if not ok or allReasons != "":
+                msg = '"' + GetName(self.mesh) + '"'
+                if ok: msg += " has been computed with warnings"
+                else:  msg += " has not been computed"
+                if allReasons != "": msg += ":"
+                else:                msg += "."
+                print msg
                 print allReasons
-                ok = False
-            elif not ok:
-                print '"' + GetName(self.mesh) + '"',"has not been computed."
-                pass
             pass
-        if salome.sg.hasDesktop():
+        if salome.sg.hasDesktop() and self.mesh.GetStudyId() >= 0:
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
@@ -1239,7 +1307,8 @@ class Mesh:
     #  @ingroup l2_construct
     def Clear(self):
         self.mesh.Clear()
-        if salome.sg.hasDesktop():
+        if ( salome.sg.hasDesktop() and 
+             salome.myStudyManager.GetStudyByID( self.mesh.GetStudyId() )):
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
@@ -1268,8 +1337,7 @@ class Mesh:
             self.Triangle().LengthFromEdges()
             pass
         if dim > 2 :
-            from NETGENPluginDC import NETGEN
-            self.Tetrahedron(NETGEN)
+            self.Tetrahedron()
             pass
         return self.Compute()
 
@@ -1304,6 +1372,7 @@ 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 )
         hyp_name = GetName( hyp )
@@ -1319,7 +1388,7 @@ class Mesh:
     #  @return True of False
     #  @ingroup l2_hypotheses
     def IsUsedHypothesis(self, hyp, geom):
-        if not hyp or not geom:
+        if not hyp: # or not geom
             return False
         if isinstance( hyp, Mesh_Algorithm ):
             hyp = hyp.GetAlgorithm()
@@ -1339,11 +1408,16 @@ class Mesh:
         if isinstance( hyp, Mesh_Algorithm ):
             hyp = hyp.GetAlgorithm()
             pass
-        if not geom:
-            geom = self.geom
+        shape = geom
+        if not shape:
+            shape = self.geom
             pass
-        status = self.mesh.RemoveHypothesis(geom, hyp)
-        return status
+        if self.IsUsedHypothesis( hyp, shape ):
+            return self.mesh.RemoveHypothesis( shape, hyp )
+        hypName = GetName( hyp )
+        geoName = GetName( shape )
+        print "WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName )
+        return None
 
     ## Gets the list of hypotheses added on a geometry
     #  @param geom a sub-shape of mesh geometry
@@ -1361,19 +1435,7 @@ class Mesh:
             pass
         pass
 
-    ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead.
-    #  Exports the mesh in a file in MED format and chooses the \a version of MED format
-    ## allowing to overwrite the file if it exists or add the exported data to its contents
-    #  @param f the file name
-    #  @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
-    #  @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
-    #  @ingroup l2_impexp
-    def ExportToMED(self, f, version, opt=0, overwrite=1):
-        self.mesh.ExportToMEDX(f, opt, version, overwrite)
-
-    ## Exports the mesh in a file in MED format and chooses the \a version of MED format
+   ## Exports the mesh in a file in MED format and chooses the \a version of MED format
     ## allowing to overwrite the file if it exists or add the exported data to its contents
     #  @param f is the file name
     #  @param auto_groups boolean parameter for creating/not creating
@@ -1451,6 +1513,31 @@ class Mesh:
             meshPart = self.mesh
         self.mesh.ExportCGNS(meshPart, f, overwrite)
 
+    ## Exports the mesh in a file in GMF format
+    #  @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):
+        if isinstance( meshPart, list ):
+            meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+        if isinstance( meshPart, Mesh ):
+            meshPart = meshPart.mesh
+        elif not meshPart:
+            meshPart = self.mesh
+        self.mesh.ExportGMF(meshPart, f, True)
+
+    ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead.
+    #  Exports the mesh in a file in MED format and chooses the \a version of MED format
+    ## allowing to overwrite the file if it exists or add the exported data to its contents
+    #  @param f the file name
+    #  @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
+    #  @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
+    #  @ingroup l2_impexp
+    def ExportToMED(self, f, version, opt=0, overwrite=1):
+        self.mesh.ExportToMEDX(f, opt, version, overwrite)
+
     # Operations with groups:
     # ----------------------
 
@@ -1595,26 +1682,6 @@ class Mesh:
         group.AddFrom( theFilter )
         return group
 
-    ## Passes mesh elements through the given filter and return IDs of fitting elements
-    #  @param theFilter SMESH_Filter
-    #  @return a list of ids
-    #  @ingroup l1_controls
-    def GetIdsFromFilter(self, theFilter):
-        theFilter.SetMesh( self.mesh )
-        return theFilter.GetIDs()
-
-    ## Verifies whether a 2D mesh element has free edges (edges connected to one face only)\n
-    #  Returns a list of special structures (borders).
-    #  @return a list of SMESH.FreeEdges.Border structure: edge id and ids of two its nodes.
-    #  @ingroup l1_controls
-    def GetFreeBorders(self):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aPredicate = aFilterMgr.CreateFreeEdges()
-        aPredicate.SetMesh(self.mesh)
-        aBorders = aPredicate.GetBorders()
-        aFilterMgr.UnRegister()
-        return aBorders
-
     ## Removes a group
     #  @ingroup l2_grps_delete
     def RemoveGroup(self, group):
@@ -1766,14 +1833,14 @@ class Mesh:
     #  @return an instance of SMESH_MeshEditor
     #  @ingroup l1_modifying
     def GetMeshEditor(self):
-        return self.mesh.GetMeshEditor()
+        return self.editor
 
     ## Wrap a list of IDs of elements or nodes into SMESH_IDSource which
-    #  can be passed as argument to accepting mesh, group or sub-mesh
+    #  can be passed as argument to a method accepting mesh, group or sub-mesh
     #  @return an instance of SMESH_IDSource
     #  @ingroup l1_auxiliary
     def GetIDSource(self, ids, elemType):
-        return self.GetMeshEditor().MakeIDSource(ids, elemType)
+        return self.editor.MakeIDSource(ids, elemType)
 
     ## Gets MED Mesh
     #  @return an instance of SALOME_MED::MESH
@@ -1810,6 +1877,12 @@ class Mesh:
     def Nb0DElements(self):
         return self.mesh.Nb0DElements()
 
+    ## Returns the number of ball discrete elements in the mesh
+    #  @return an integer value
+    #  @ingroup l1_meshinfo
+    def NbBalls(self):
+        return self.mesh.NbBalls()
+
     ## Returns the number of edges in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
@@ -2026,7 +2099,7 @@ class Mesh:
     #  @ingroup l1_meshinfo
     def GetSubMeshNodesId(self, Shape, all):
         if ( isinstance( Shape, geompyDC.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         return self.mesh.GetSubMeshNodesId(ShapeID, all)
@@ -2073,6 +2146,12 @@ class Mesh:
     def GetNodePosition(self,NodeID):
         return self.mesh.GetNodePosition(NodeID)
 
+    ## @brief Returns the position of an element on the shape
+    #  @return SMESH::ElementPosition
+    #  @ingroup l1_meshinfo
+    def GetElementPosition(self,ElemID):
+        return self.mesh.GetElementPosition(ElemID)
+
     ## If the given element is a node, returns the ID of shape
     #  \n If there is no node for the given ID - returns -1
     #  @return an integer value
@@ -2095,7 +2174,7 @@ class Mesh:
     def GetElemNbNodes(self, id):
         return self.mesh.GetElemNbNodes(id)
 
-    ## Returns the node ID the given index for the given element
+    ## Returns the node ID the given (zero based) index for the given element
     #  \n If there is no element for the given ID - returns -1
     #  \n If there is no node for the given index - returns -2
     #  @return an integer value
@@ -2149,6 +2228,11 @@ class Mesh:
     def IsQuadratic(self, id):
         return self.mesh.IsQuadratic(id)
 
+    ## Returns diameter of a ball discrete element or zero in case of an invalid \a id
+    #  @ingroup l1_meshinfo
+    def GetBallDiameter(self, id):
+        return self.mesh.GetBallDiameter(id)
+
     ## Returns XYZ coordinates of the barycenter of the given element
     #  \n If there is no element for the given ID - returns an empty list
     #  @return a list of three double values
@@ -2156,6 +2240,26 @@ class Mesh:
     def BaryCenter(self, id):
         return self.mesh.BaryCenter(id)
 
+    ## Passes mesh elements through the given filter and return IDs of fitting elements
+    #  @param theFilter SMESH_Filter
+    #  @return a list of ids
+    #  @ingroup l1_controls
+    def GetIdsFromFilter(self, theFilter):
+        theFilter.SetMesh( self.mesh )
+        return theFilter.GetIDs()
+
+    ## Verifies whether a 2D mesh element has free edges (edges connected to one face only)\n
+    #  Returns a list of special structures (borders).
+    #  @return a list of SMESH.FreeEdges.Border structure: edge id and ids of two its nodes.
+    #  @ingroup l1_controls
+    def GetFreeBorders(self):
+        aFilterMgr = self.smeshpyD.CreateFilterManager()
+        aPredicate = aFilterMgr.CreateFreeEdges()
+        aPredicate.SetMesh(self.mesh)
+        aBorders = aPredicate.GetBorders()
+        aFilterMgr.UnRegister()
+        return aBorders
+
 
     # Get mesh measurements information:
     # ------------------------------------
@@ -2284,6 +2388,32 @@ class Mesh:
     def Add0DElement(self, IDOfNode):
         return self.editor.Add0DElement(IDOfNode)
 
+    ## Create 0D elements on all nodes of the given elements except those 
+    #  nodes on which a 0D element already exists.
+    #  @param theObject an object on whose nodes 0D elements will be created.
+    #         It can be mesh, sub-mesh, group, list of element IDs or a holder
+    #         of nodes IDs created by calling mesh.GetIDSource( nodes, SMESH.NODE )
+    #  @param theGroupName optional name of a group to add 0D elements created
+    #         and/or found on nodes of \a theObject.
+    #  @return an object (a new group or a temporary SMESH_IDSource) holding
+    #          IDs of new and/or found 0D elements. IDs of 0D elements 
+    #          can be retrieved from the returned object by calling GetIDs()
+    #  @ingroup l2_modif_add
+    def Add0DElementsToAllNodes(self, theObject, theGroupName=""):
+        if isinstance( theObject, Mesh ):
+            theObject = theObject.GetMesh()
+        if isinstance( theObject, list ):
+            theObject = self.GetIDSource( theObject, SMESH.ALL )
+        return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName )
+
+    ## Creates a ball element on a node with given ID.
+    #  @param IDOfNode the ID of node for creation of the element.
+    #  @param diameter the bal diameter.
+    #  @return the Id of the new ball element
+    #  @ingroup l2_modif_add
+    def AddBall(self, IDOfNode, diameter):
+        return self.editor.AddBall( IDOfNode, diameter )
+
     ## Creates a linear or quadratic edge (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
@@ -2470,7 +2600,7 @@ class Mesh:
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
     #  @param elementType type of elements to find (SMESH.ALL type
-    #         means elements of any type excluding nodes and 0D elements)
+    #         means elements of any type excluding nodes, discrete and 0D elements)
     #  @param meshPart a part of mesh (group, sub-mesh) to search within
     #  @return list of IDs of found elements
     #  @ingroup l2_modif_throughp
@@ -2480,7 +2610,8 @@ class Mesh:
         else:
             return self.editor.FindElementsByPoint(x, y, z, elementType)
 
-    # Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
+    # Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
+    # 0-IN, 1-OUT, 2-ON, 3-UNKNOWN
     # TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
 
     def GetPointState(self, x, y, z):
@@ -2531,32 +2662,62 @@ class Mesh:
             theObject = theObject.GetMesh()
         return self.editor.ReorientObject(theObject)
 
+    ## Reorient faces contained in \a the2DObject.
+    #  @param the2DObject is a mesh, sub-mesh, group or list of IDs of 2D elements
+    #  @param theDirection is a desired direction of normal of \a theFace.
+    #         It can be either a GEOM vector or a list of coordinates [x,y,z].
+    #  @param theFaceOrPoint defines a face of \a the2DObject whose normal will be
+    #         compared with theDirection. It can be either ID of face or a point
+    #         by which the face will be found. The point can be given as either
+    #         a GEOM vertex or a list of point coordinates.
+    #  @return number of reoriented faces
+    #  @ingroup l2_modif_changori
+    def Reorient2D(self, the2DObject, theDirection, theFaceOrPoint ):
+        # check the2DObject
+        if isinstance( the2DObject, Mesh ):
+            the2DObject = the2DObject.GetMesh()
+        if isinstance( the2DObject, list ):
+            the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
+        # check theDirection
+        if isinstance( theDirection, geompyDC.GEOM._objref_GEOM_Object):
+            theDirection = self.smeshpyD.GetDirStruct( theDirection )
+        if isinstance( theDirection, list ):
+            theDirection = self.smeshpyD.MakeDirStruct( *theDirection  )
+        # prepare theFace and thePoint
+        theFace = theFaceOrPoint
+        thePoint = PointStruct(0,0,0)
+        if isinstance( theFaceOrPoint, geompyDC.GEOM._objref_GEOM_Object):
+            thePoint = self.smeshpyD.GetPointStruct( theFaceOrPoint )
+            theFace = -1
+        if isinstance( theFaceOrPoint, list ):
+            thePoint = PointStruct( *theFaceOrPoint )
+            theFace = -1
+        if isinstance( theFaceOrPoint, PointStruct ):
+            thePoint = theFaceOrPoint
+            theFace = -1
+        return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
+
     ## Fuses the neighbouring triangles into quadrangles.
     #  @param IDsOfElements The triangles to be fused,
-    #  @param theCriterion  is FT_...; used to choose a neighbour to fuse with.
+    #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
+    #                       choose a neighbour to fuse with.
     #  @param MaxAngle      is the maximum angle between element normals at which the fusion
     #                       is still performed; theMaxAngle is mesured in radians.
     #                       Also it could be a name of variable which defines angle in degrees.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_unitetri
     def TriToQuad(self, IDsOfElements, theCriterion, MaxAngle):
-        flag = False
-        if isinstance(MaxAngle,str):
-            flag = True
         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
         self.mesh.SetParameters(Parameters)
         if not IDsOfElements:
             IDsOfElements = self.GetElementsId()
-        Functor = 0
-        if ( isinstance( theCriterion, SMESH._objref_NumericalFunctor ) ):
-            Functor = theCriterion
-        else:
-            Functor = self.smeshpyD.GetFunctor(theCriterion)
+        Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.TriToQuad(IDsOfElements, Functor, MaxAngle)
 
     ## Fuses the neighbouring triangles of the object into quadrangles
     #  @param theObject is mesh, submesh or group
-    #  @param theCriterion is FT_...; used to choose a neighbour to fuse with.
+    #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
+    #         choose a neighbour to fuse with.
     #  @param MaxAngle   a max angle between element normals at which the fusion
     #                   is still performed; theMaxAngle is mesured in radians.
     #  @return TRUE in case of success, FALSE otherwise.
@@ -2564,29 +2725,42 @@ class Mesh:
     def TriToQuadObject (self, theObject, theCriterion, MaxAngle):
         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
         self.mesh.SetParameters(Parameters)
-        if ( isinstance( theObject, Mesh )):
+        if isinstance( theObject, Mesh ):
             theObject = theObject.GetMesh()
-        return self.editor.TriToQuadObject(theObject, self.smeshpyD.GetFunctor(theCriterion), MaxAngle)
+        Functor = self.smeshpyD.GetFunctor(theCriterion)
+        return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
 
     ## Splits quadrangles into triangles.
+    #
     #  @param IDsOfElements the faces to be splitted.
-    #  @param theCriterion   FT_...; used to choose a diagonal for splitting.
+    #  @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
+    #         value, then quadrangles will be split by the smallest diagonal.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_cutquadr
-    def QuadToTri (self, IDsOfElements, theCriterion):
+    def QuadToTri (self, IDsOfElements, theCriterion = None):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
-        return self.editor.QuadToTri(IDsOfElements, self.smeshpyD.GetFunctor(theCriterion))
+        if theCriterion is None:
+            theCriterion = FT_MaxElementLength2D
+        Functor = self.smeshpyD.GetFunctor(theCriterion)
+        return self.editor.QuadToTri(IDsOfElements, Functor)
 
     ## Splits quadrangles into triangles.
-    #  @param theObject  the object from which the list of elements is taken, this is mesh, submesh or group
-    #  @param theCriterion   FT_...; used to choose a diagonal for splitting.
+    #  @param theObject the object from which the list of elements is taken,
+    #         this is mesh, submesh or group
+    #  @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
+    #         value, then quadrangles will be split by the smallest diagonal.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_cutquadr
-    def QuadToTriObject (self, theObject, theCriterion):
+    def QuadToTriObject (self, theObject, theCriterion = None):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
-        return self.editor.QuadToTriObject(theObject, self.smeshpyD.GetFunctor(theCriterion))
+        if theCriterion is None:
+            theCriterion = FT_MaxElementLength2D
+        Functor = self.smeshpyD.GetFunctor(theCriterion)
+        return self.editor.QuadToTriObject(theObject, Functor)
 
     ## Splits quadrangles into triangles.
     #  @param IDsOfElements the faces to be splitted
@@ -2599,7 +2773,8 @@ class Mesh:
         return self.editor.SplitQuad(IDsOfElements, Diag13)
 
     ## Splits quadrangles into triangles.
-    #  @param theObject the object from which the list of elements is taken, this is mesh, submesh or group
+    #  @param theObject the object from which the list of elements is taken,
+    #         this is mesh, submesh or group
     #  @param Diag13    is used to choose a diagonal for splitting.
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_cutquadr
@@ -2610,7 +2785,8 @@ class Mesh:
 
     ## Finds a better splitting of the given quadrangle.
     #  @param IDOfQuad   the ID of the quadrangle to be splitted.
-    #  @param theCriterion  FT_...; a criterion to choose a diagonal for splitting.
+    #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
+    #         choose a diagonal for splitting.
     #  @return 1 if 1-3 diagonal is better, 2 if 2-4
     #          diagonal is better, 0 if error occurs.
     #  @ingroup l2_modif_cutquadr
@@ -2839,19 +3015,23 @@ class Mesh:
         return self.editor.SmoothParametricObject(theObject, IDsOfFixedNodes,
                                                   MaxNbOfIterations, MaxAspectRatio, Method)
 
-    ## Converts the mesh to quadratic, deletes old elements, replacing
+    ## Converts the mesh to quadratic or bi-quadratic, deletes old elements, replacing
     #  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
     #  @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):
-        if theSubMesh:
-            self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
+    def ConvertToQuadratic(self, theForce3d, theSubMesh=None, theToBiQuad=False):
+        if theToBiQuad:
+            self.editor.ConvertToBiQuadratic(theForce3d,theSubMesh)
         else:
-            self.editor.ConvertToQuadratic(theForce3d)
-
+            if theSubMesh:
+                self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
+            else:
+                self.editor.ConvertToQuadratic(theForce3d)
+            
     ## Converts the mesh from quadratic to ordinary,
     #  deletes old quadratic elements, \n replacing
     #  them with ordinary mesh elements with the same id.
@@ -3053,7 +3233,9 @@ class Mesh:
 
     ## Generates new elements by extrusion of the elements with given ids
     #  @param IDsOfElements the list of elements ids for extrusion
-    #  @param StepVector vector or DirStruct, defining the direction and value of extrusion for one step (the total extrusion length will be NbOfSteps * ||StepVector||)
+    #  @param StepVector vector or DirStruct or 3 vector components, defining
+    #         the direction and value of extrusion for one step (the total extrusion
+    #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @param IsNodes is True if elements with given ids are nodes
@@ -3062,8 +3244,10 @@ class Mesh:
     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
-        if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)):
+        if isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object):
             StepVector = self.smeshpyD.GetDirStruct(StepVector)
+        if isinstance( StepVector, list ):
+            StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
         Parameters = StepVector.PS.parameters + var_separator + Parameters
         self.mesh.SetParameters(Parameters)
@@ -3080,7 +3264,9 @@ class Mesh:
 
     ## Generates new elements by extrusion of the elements with given ids
     #  @param IDsOfElements is ids of elements
-    #  @param StepVector vector, defining the direction and value of extrusion
+    #  @param StepVector vector or DirStruct or 3 vector components, defining
+    #         the direction and value of extrusion for one step (the total extrusion
+    #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param ExtrFlags sets flags for extrusion
     #  @param SewTolerance uses for comparing locations of nodes if flag
@@ -3092,6 +3278,8 @@ class Mesh:
                           ExtrFlags, SewTolerance, MakeGroups=False):
         if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)):
             StepVector = self.smeshpyD.GetDirStruct(StepVector)
+        if isinstance( StepVector, list ):
+            StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
         if MakeGroups:
             return self.editor.AdvancedExtrusionMakeGroups(IDsOfElements, StepVector, NbOfSteps,
                                                            ExtrFlags, SewTolerance)
@@ -3102,7 +3290,9 @@ class Mesh:
     ## 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.
-    #  @param StepVector vector, defining the direction and value of extrusion for one step (the total extrusion length will be NbOfSteps * ||StepVector||)
+    #  @param StepVector vector or DirStruct or 3 vector components, defining
+    #         the direction and value of extrusion for one step (the total extrusion
+    #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @param  IsNodes is True if elements which belong to the object are nodes
@@ -3113,6 +3303,8 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)):
             StepVector = self.smeshpyD.GetDirStruct(StepVector)
+        if isinstance( StepVector, list ):
+            StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
         Parameters = StepVector.PS.parameters + var_separator + Parameters
         self.mesh.SetParameters(Parameters)
@@ -3130,7 +3322,9 @@ class Mesh:
     ## Generates new elements by extrusion of the elements which belong to the object
     #  @param theObject object which elements should be processed.
     #                   It can be a mesh, a sub mesh or a group.
-    #  @param StepVector vector, defining the direction and value of extrusion for one step (the total extrusion length will be NbOfSteps * ||StepVector||)
+    #  @param StepVector vector or DirStruct or 3 vector components, defining
+    #         the direction and value of extrusion for one step (the total extrusion
+    #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups to generate new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -3140,6 +3334,8 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)):
             StepVector = self.smeshpyD.GetDirStruct(StepVector)
+        if isinstance( StepVector, list ):
+            StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
         Parameters = StepVector.PS.parameters + var_separator + Parameters
         self.mesh.SetParameters(Parameters)
@@ -3151,7 +3347,9 @@ class Mesh:
     ## Generates new elements by extrusion of the elements which belong to the object
     #  @param theObject object which elements should be processed.
     #                   It can be a mesh, a sub mesh or a group.
-    #  @param StepVector vector, defining the direction and value of extrusion for one step (the total extrusion length will be NbOfSteps * ||StepVector||)
+    #  @param StepVector vector or DirStruct or 3 vector components, defining
+    #         the direction and value of extrusion for one step (the total extrusion
+    #         length will be NbOfSteps * ||StepVector||)
     #  @param NbOfSteps the number of steps
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -3161,6 +3359,8 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( StepVector, geompyDC.GEOM._objref_GEOM_Object)):
             StepVector = self.smeshpyD.GetDirStruct(StepVector)
+        if isinstance( StepVector, list ):
+            StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
         Parameters = StepVector.PS.parameters + var_separator + Parameters
         self.mesh.SetParameters(Parameters)
@@ -3465,7 +3665,7 @@ class Mesh:
 
     ## Translates the elements
     #  @param IDsOfElements list of elements ids
-    #  @param Vector the direction of translation (DirStruct or vector)
+    #  @param Vector the direction of translation (DirStruct or vector or 3 vector components)
     #  @param Copy allows copying the translated elements
     #  @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
@@ -3475,6 +3675,8 @@ class Mesh:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Vector, geompyDC.GEOM._objref_GEOM_Object)):
             Vector = self.smeshpyD.GetDirStruct(Vector)
+        if isinstance( Vector, list ):
+            Vector = self.smeshpyD.MakeDirStruct(*Vector)
         self.mesh.SetParameters(Vector.PS.parameters)
         if Copy and MakeGroups:
             return self.editor.TranslateMakeGroups(IDsOfElements, Vector)
@@ -3483,7 +3685,7 @@ class Mesh:
 
     ## Creates a new mesh of translated elements
     #  @param IDsOfElements list of elements ids
-    #  @param Vector the direction of translation (DirStruct or vector)
+    #  @param Vector the direction of translation (DirStruct or vector or 3 vector components)
     #  @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
@@ -3493,13 +3695,15 @@ class Mesh:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Vector, geompyDC.GEOM._objref_GEOM_Object)):
             Vector = self.smeshpyD.GetDirStruct(Vector)
+        if isinstance( Vector, list ):
+            Vector = self.smeshpyD.MakeDirStruct(*Vector)
         self.mesh.SetParameters(Vector.PS.parameters)
         mesh = self.editor.TranslateMakeMesh(IDsOfElements, Vector, MakeGroups, NewMeshName)
         return Mesh ( self.smeshpyD, self.geompyD, mesh )
 
     ## Translates the object
     #  @param theObject the object to translate (mesh, submesh, or group)
-    #  @param Vector direction of translation (DirStruct or geom vector)
+    #  @param Vector direction of translation (DirStruct or geom vector or 3 vector components)
     #  @param Copy allows copying the translated elements
     #  @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
@@ -3509,6 +3713,8 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( Vector, geompyDC.GEOM._objref_GEOM_Object)):
             Vector = self.smeshpyD.GetDirStruct(Vector)
+        if isinstance( Vector, list ):
+            Vector = self.smeshpyD.MakeDirStruct(*Vector)
         self.mesh.SetParameters(Vector.PS.parameters)
         if Copy and MakeGroups:
             return self.editor.TranslateObjectMakeGroups(theObject, Vector)
@@ -3517,16 +3723,18 @@ class Mesh:
 
     ## Creates a new mesh from the translated object
     #  @param theObject the object to translate (mesh, submesh, or group)
-    #  @param Vector the direction of translation (DirStruct or geom vector)
+    #  @param Vector the direction of translation (DirStruct or geom vector or 3 vector components)
     #  @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
     #  @ingroup l2_modif_trsf
     def TranslateObjectMakeMesh(self, theObject, Vector, MakeGroups=False, NewMeshName=""):
-        if (isinstance(theObject, Mesh)):
+        if isinstance( theObject, Mesh ):
             theObject = theObject.GetMesh()
-        if (isinstance(Vector, geompyDC.GEOM._objref_GEOM_Object)):
+        if isinstance( Vector, geompyDC.GEOM._objref_GEOM_Object ):
             Vector = self.smeshpyD.GetDirStruct(Vector)
+        if isinstance( Vector, list ):
+            Vector = self.smeshpyD.MakeDirStruct(*Vector)
         self.mesh.SetParameters(Vector.PS.parameters)
         mesh = self.editor.TranslateObjectMakeMesh(theObject, Vector, MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
@@ -3547,6 +3755,10 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject, SMESH.ALL)
+        if ( isinstance( theScaleFact, float )):
+             theScaleFact = [theScaleFact]
+        if ( isinstance( theScaleFact, int )):
+             theScaleFact = [ float(theScaleFact)]
 
         self.mesh.SetParameters(thePoint.parameters)
 
@@ -3567,6 +3779,10 @@ class Mesh:
             theObject = theObject.GetMesh()
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject,SMESH.ALL)
+        if ( isinstance( theScaleFact, float )):
+             theScaleFact = [theScaleFact]
+        if ( isinstance( theScaleFact, int )):
+             theScaleFact = [ float(theScaleFact)]
 
         self.mesh.SetParameters(thePoint.parameters)
         mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact,
@@ -3844,12 +4060,20 @@ class Mesh:
     #  @param theAffectedElems - group of elements to which the replicated nodes
     #         should be associated to.
     #  @param theMakeGroup forces the generation of a group containing new elements.
-    #  @return TRUE or a created group if operation has been completed successfully,
+    #  @param theMakeNodeGroup forces the generation of a group containing new nodes.
+    #  @return TRUE or created groups (one or two) if operation has been completed successfully,
     #          FALSE or None otherwise
     #  @ingroup l2_modif_edit
-    def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems, theMakeGroup=False):
-        if theMakeGroup:
-            return self.editor.DoubleNodeElemGroupNew(theElems, theNodesNot, theAffectedElems)
+    def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems,
+                             theMakeGroup=False, theMakeNodeGroup=False):
+        if theMakeGroup or theMakeNodeGroup:
+            twoGroups = self.editor.DoubleNodeElemGroup2New(theElems, theNodesNot,
+                                                            theAffectedElems,
+                                                            theMakeGroup, theMakeNodeGroup)
+            if theMakeGroup and theMakeNodeGroup:
+                return twoGroups
+            else:
+                return twoGroups[ int(theMakeNodeGroup) ]
         return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems)
 
     ## Creates a hole in a mesh by doubling the nodes of some particular elements
@@ -3870,12 +4094,20 @@ class Mesh:
     #  @param theAffectedElems - group of elements to which the replicated nodes
     #         should be associated to.
     #  @param theMakeGroup forces the generation of a group containing new elements.
-    #  @return TRUE or a created group if operation has been completed successfully,
+    #  @param theMakeNodeGroup forces the generation of a group containing new nodes.
+    #  @return TRUE or created groups (one or two) if operation has been completed successfully,
     #          FALSE or None otherwise
     #  @ingroup l2_modif_edit
-    def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems, theMakeGroup=False):
-        if theMakeGroup:
-            return self.editor.DoubleNodeElemGroupsNew(theElems, theNodesNot, theAffectedElems)
+    def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems,
+                             theMakeGroup=False, theMakeNodeGroup=False):
+        if theMakeGroup or theMakeNodeGroup:
+            twoGroups = self.editor.DoubleNodeElemGroups2New(theElems, theNodesNot,
+                                                             theAffectedElems,
+                                                             theMakeGroup, theMakeNodeGroup)
+            if theMakeGroup and theMakeNodeGroup:
+                return twoGroups
+            else:
+                return twoGroups[ int(theMakeNodeGroup) ]
         return self.editor.DoubleNodeElemGroups(theElems, theNodesNot, theAffectedElems)
 
     ## Creates a hole in a mesh by doubling the nodes of some particular elements
@@ -3890,6 +4122,18 @@ class Mesh:
     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
 
+    ## Identify the elements that will be affected by node duplication (actual duplication is not performed.
+    #  This method is the first step of DoubleNodeElemGroupsInRegion.
+    #  @param theElems - list of groups of elements (edges or faces) to be replicated
+    #  @param theNodesNot - list of groups of nodes not to replicated
+    #  @param theShape - shape to detect affected elements (element which geometric center
+    #         located on or inside shape).
+    #         The replicated nodes should be associated to affected elements.
+    #  @return groups of affected elements
+    #  @ingroup l2_modif_edit
+    def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
+        return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)
+
     ## Double nodes on shared faces between groups of volumes and create flat elements on demand.
     # The list of groups must describe a partition of the mesh volumes.
     # The nodes of the internal faces at the boundaries of the groups are doubled.
@@ -3910,10 +4154,22 @@ class Mesh:
     # @return TRUE if operation has been completed successfully, FALSE otherwise
     def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
         return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
+    
+    ## identify all the elements around a geom shape, get the faces delimiting the hole
+    #
+    def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
+        return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
+
+    def _getFunctor(self, funcType ):
+        fn = self.functors[ funcType._v ]
+        if not fn:
+            fn = self.smeshpyD.GetFunctor(funcType)
+            fn.SetMesh(self.mesh)
+            self.functors[ funcType._v ] = fn
+        return fn
 
     def _valueFromFunctor(self, funcType, elemId):
-        fn = self.smeshpyD.GetFunctor(funcType)
-        fn.SetMesh(self.mesh)
+        fn = self._getFunctor( funcType )
         if fn.GetElementType() == self.GetElementType(elemId, True):
             val = fn.GetValue(elemId)
         else:
@@ -3991,287 +4247,10 @@ class Mesh:
     def GetSkew(self, elemId):
         return self._valueFromFunctor(SMESH.FT_Skew, elemId)
 
-## The mother class to define algorithm, it is not recommended to use it directly.
+    pass # end of Mesh class
+    
+## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
 #
-#  For each meshing algorithm, a python class inheriting from class Mesh_Algorithm
-#  should be defined. This descendant class sould have two attributes defining the way
-# it is created by class Mesh (see e.g. class StdMeshersDC_Segment in StdMeshersDC.py).
-# - meshMethod attribute defines name of method of class Mesh by calling which the
-#   python class of algorithm is created. E.g. if in class MyPlugin_Algorithm
-#   meshMethod = "MyAlgorithm", then an instance of MyPlugin_Algorithm is created
-#   by the following code: my_algo = mesh.MyAlgorithm()
-# - algoType defines name of algorithm type and is used mostly to discriminate
-#   algorithms that are created by the same method of class Mesh. E.g. if
-#   MyPlugin_Algorithm.algoType = "MyPLUGIN" then it's creation code can be:
-#   my_algo = mesh.MyAlgorithm(algo="MyPLUGIN")
-#  @ingroup l2_algorithms
-class Mesh_Algorithm:
-    #  @class Mesh_Algorithm
-    #  @brief Class Mesh_Algorithm
-
-    #def __init__(self,smesh):
-    #    self.smesh=smesh
-    def __init__(self):
-        self.mesh = None
-        self.geom = None
-        self.subm = None
-        self.algo = None
-
-    ## Finds a hypothesis in the study by its type name and parameters.
-    #  Finds only the hypotheses created in smeshpyD engine.
-    #  @return SMESH.SMESH_Hypothesis
-    def FindHypothesis (self, hypname, args, CompareMethod, smeshpyD):
-        study = smeshpyD.GetCurrentStudy()
-        #to do: find component by smeshpyD object, not by its data type
-        scomp = study.FindComponent(smeshpyD.ComponentDataType())
-        if scomp is not None:
-            res,hypRoot = scomp.FindSubObject(SMESH.Tag_HypothesisRoot)
-            # Check if the root label of the hypotheses exists
-            if res and hypRoot is not None:
-                iter = study.NewChildIterator(hypRoot)
-                # Check all published hypotheses
-                while iter.More():
-                    hypo_so_i = iter.Value()
-                    attr = hypo_so_i.FindAttribute("AttributeIOR")[1]
-                    if attr is not None:
-                        anIOR = attr.Value()
-                        hypo_o_i = salome.orb.string_to_object(anIOR)
-                        if hypo_o_i is not None:
-                            # Check if this is a hypothesis
-                            hypo_i = hypo_o_i._narrow(SMESH.SMESH_Hypothesis)
-                            if hypo_i is not None:
-                                # Check if the hypothesis belongs to current engine
-                                if smeshpyD.GetObjectId(hypo_i) > 0:
-                                    # Check if this is the required hypothesis
-                                    if hypo_i.GetName() == hypname:
-                                        # Check arguments
-                                        if CompareMethod(hypo_i, args):
-                                            # found!!!
-                                            return hypo_i
-                                        pass
-                                    pass
-                                pass
-                            pass
-                        pass
-                    iter.Next()
-                    pass
-                pass
-            pass
-        return None
-
-    ## Finds the algorithm in the study by its type name.
-    #  Finds only the algorithms, which have been created in smeshpyD engine.
-    #  @return SMESH.SMESH_Algo
-    def FindAlgorithm (self, algoname, smeshpyD):
-        study = smeshpyD.GetCurrentStudy()
-        #to do: find component by smeshpyD object, not by its data type
-        scomp = study.FindComponent(smeshpyD.ComponentDataType())
-        if scomp is not None:
-            res,hypRoot = scomp.FindSubObject(SMESH.Tag_AlgorithmsRoot)
-            # Check if the root label of the algorithms exists
-            if res and hypRoot is not None:
-                iter = study.NewChildIterator(hypRoot)
-                # Check all published algorithms
-                while iter.More():
-                    algo_so_i = iter.Value()
-                    attr = algo_so_i.FindAttribute("AttributeIOR")[1]
-                    if attr is not None:
-                        anIOR = attr.Value()
-                        algo_o_i = salome.orb.string_to_object(anIOR)
-                        if algo_o_i is not None:
-                            # Check if this is an algorithm
-                            algo_i = algo_o_i._narrow(SMESH.SMESH_Algo)
-                            if algo_i is not None:
-                                # Checks if the algorithm belongs to the current engine
-                                if smeshpyD.GetObjectId(algo_i) > 0:
-                                    # Check if this is the required algorithm
-                                    if algo_i.GetName() == algoname:
-                                        # found!!!
-                                        return algo_i
-                                    pass
-                                pass
-                            pass
-                        pass
-                    iter.Next()
-                    pass
-                pass
-            pass
-        return None
-
-    ## If the algorithm is global, returns 0; \n
-    #  else returns the submesh associated to this algorithm.
-    def GetSubMesh(self):
-        return self.subm
-
-    ## Returns the wrapped mesher.
-    def GetAlgorithm(self):
-        return self.algo
-
-    ## Gets the list of hypothesis that can be used with this algorithm
-    def GetCompatibleHypothesis(self):
-        mylist = []
-        if self.algo:
-            mylist = self.algo.GetCompatibleHypothesis()
-        return mylist
-
-    ## Gets the name of the algorithm
-    def GetName(self):
-        GetName(self.algo)
-
-    ## Sets the name to the algorithm
-    def SetName(self, name):
-        self.mesh.smeshpyD.SetName(self.algo, name)
-
-    ## Gets the id of the algorithm
-    def GetId(self):
-        return self.algo.GetId()
-
-    ## Private method.
-    def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
-        if geom is None:
-            raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
-        algo = self.FindAlgorithm(hypo, mesh.smeshpyD)
-        if algo is None:
-            algo = mesh.smeshpyD.CreateHypothesis(hypo, so)
-            pass
-        self.Assign(algo, mesh, geom)
-        return self.algo
-
-    ## Private method
-    def Assign(self, algo, mesh, geom):
-        if geom is None:
-            raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape"
-        self.mesh = mesh
-        name = ""
-        if not geom:
-            self.geom = mesh.geom
-        else:
-            self.geom = geom
-            AssureGeomPublished( mesh, geom )
-            try:
-                name = GetName(geom)
-                pass
-            except:
-                pass
-            self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName())
-        self.algo = algo
-        status = mesh.mesh.AddHypothesis(self.geom, self.algo)
-        TreatHypoStatus( status, algo.GetName(), name, True )
-        return
-
-    def CompareHyp (self, hyp, args):
-        print "CompareHyp is not implemented for ", self.__class__.__name__, ":", hyp.GetName()
-        return False
-
-    def CompareEqualHyp (self, hyp, args):
-        return True
-
-    ## Private method
-    def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
-                    UseExisting=0, CompareMethod=""):
-        hypo = None
-        if UseExisting:
-            if CompareMethod == "": CompareMethod = self.CompareHyp
-            hypo = self.FindHypothesis(hyp, args, CompareMethod, self.mesh.smeshpyD)
-            pass
-        if hypo is None:
-            hypo = self.mesh.smeshpyD.CreateHypothesis(hyp, so)
-            a = ""
-            s = "="
-            for arg in args:
-                argStr = str(arg)
-                if isinstance( arg, geompyDC.GEOM._objref_GEOM_Object ):
-                    argStr = arg.GetStudyEntry()
-                    if not argStr: argStr = "GEOM_Obj_%s", arg.GetEntry()
-                if len( argStr ) > 10:
-                    argStr = argStr[:7]+"..."
-                    if argStr[0] == '[': argStr += ']'
-                a = a + s + argStr
-                s = ","
-                pass
-            if len(a) > 50:
-                a = a[:47]+"..."
-            self.mesh.smeshpyD.SetName(hypo, hyp + a)
-            pass
-        geomName=""
-        if self.geom:
-            geomName = GetName(self.geom)
-        status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
-        TreatHypoStatus( status, GetName(hypo), geomName, 0 )
-        return hypo
-
-    ## Returns entry of the shape to mesh in the study
-    def MainShapeEntry(self):
-        entry = ""
-        if not self.mesh or not self.mesh.GetMesh(): return entry
-        if not self.mesh.GetMesh().HasShapeToMesh(): return entry
-        study = self.mesh.smeshpyD.GetCurrentStudy()
-        ior  = salome.orb.object_to_string( self.mesh.GetShape() )
-        sobj = study.FindObjectIOR(ior)
-        if sobj: entry = sobj.GetID()
-        if not entry: return ""
-        return entry
-
-    ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
-    #  near mesh boundary. This hypothesis can be used by several 3D algorithms:
-    #  NETGEN 3D, GHS3D, Hexahedron(i,j,k)
-    #  @param thickness total thickness of layers of prisms
-    #  @param numberOfLayers number of layers of prisms
-    #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
-    #  @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
-    #  @ingroup l3_hypos_additi
-    def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
-        if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
-            raise TypeError, "ViscousLayers are supported by 3D algorithms only"
-        if not "ViscousLayers" in self.GetCompatibleHypothesis():
-            raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
-        if ignoreFaces and isinstance( ignoreFaces[0], geompyDC.GEOM._objref_GEOM_Object ):
-            ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
-        hyp = self.Hypothesis("ViscousLayers",
-                              [thickness, numberOfLayers, stretchFactor, ignoreFaces])
-        hyp.SetTotalThickness(thickness)
-        hyp.SetNumberLayers(numberOfLayers)
-        hyp.SetStretchFactor(stretchFactor)
-        hyp.SetIgnoreFaces(ignoreFaces)
-        return hyp
-
-    ## Transform a list of ether edges or tuples (edge 1st_vertex_of_edge)
-    #  into a list acceptable to SetReversedEdges() of some 1D hypotheses
-    #  @ingroup l3_hypos_1dhyps
-    def ReversedEdgeIndices(self, reverseList):
-        resList = []
-        geompy = self.mesh.geompyD
-        for i in reverseList:
-            if isinstance( i, int ):
-                s = geompy.SubShapes(self.mesh.geom, [i])[0]
-                if s.GetShapeType() != geompyDC.GEOM.EDGE:
-                    raise TypeError, "Not EDGE index given"
-                resList.append( i )
-            elif isinstance( i, geompyDC.GEOM._objref_GEOM_Object ):
-                if i.GetShapeType() != geompyDC.GEOM.EDGE:
-                    raise TypeError, "Not an EDGE given"
-                resList.append( geompy.GetSubShapeID(self.mesh.geom, i ))
-            elif len( i ) > 1:
-                e = i[0]
-                v = i[1]
-                if not isinstance( e, geompyDC.GEOM._objref_GEOM_Object ) or \
-                   not isinstance( v, geompyDC.GEOM._objref_GEOM_Object ):
-                    raise TypeError, "A list item must be a tuple (edge 1st_vertex_of_edge)"
-                if v.GetShapeType() == geompyDC.GEOM.EDGE and \
-                   e.GetShapeType() == geompyDC.GEOM.VERTEX:
-                    v,e = e,v
-                if e.GetShapeType() != geompyDC.GEOM.EDGE or \
-                   v.GetShapeType() != geompyDC.GEOM.VERTEX:
-                    raise TypeError, "A list item must be a tuple (edge 1st_vertex_of_edge)"
-                vFirst = FirstVertexOnCurve( e )
-                tol    = geompy.Tolerance( vFirst )[-1]
-                if geompy.MinDistance( v, vFirst ) > 1.5*tol:
-                    resList.append( geompy.GetSubShapeID(self.mesh.geom, e ))
-            else:
-                raise TypeError, "Item must be either an edge or tuple (edge 1st_vertex_of_edge)"
-        return resList
-
-
 class Pattern(SMESH._objref_SMESH_Pattern):
 
     def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse):
@@ -4286,13 +4265,9 @@ class Pattern(SMESH._objref_SMESH_Pattern):
         theMesh.SetParameters(Parameters)
         return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index )
 
-#Registering the new proxy for Pattern
+# Registering the new proxy for Pattern
 omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
 
-
-
-
-
 ## Private class used to bind methods creating algorithms to the class Mesh
 #
 class algoCreator:
@@ -4336,6 +4311,7 @@ class algoCreator:
         return None
 
 # Private class used to substitute and store variable parameters of hypotheses.
+#
 class hypMethodWrapper:
     def __init__(self, hyp, method):
         self.hyp    = hyp