Salome HOME
22874: [CEA 1425] Performance SMESH Module
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index 767a5ef1494913132133776c59f6b145c60c6b63..b4f79d7356e2ed27ff664744de29fc9be4ef4236 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2015  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
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -207,12 +207,15 @@ def GetName(obj):
     raise RuntimeError, "Null or invalid object"
 
 ## Prints error message if a hypothesis was not assigned.
     raise RuntimeError, "Null or invalid object"
 
 ## Prints error message if a hypothesis was not assigned.
-def TreatHypoStatus(status, hypName, geomName, isAlgo):
+def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
     if isAlgo:
         hypType = "algorithm"
     else:
         hypType = "hypothesis"
         pass
     if isAlgo:
         hypType = "algorithm"
     else:
         hypType = "hypothesis"
         pass
+    reason = ""
+    if hasattr( status, "__getitem__" ):
+        status,reason = status[0],status[1]
     if status == HYP_UNKNOWN_FATAL :
         reason = "for unknown reason"
     elif status == HYP_INCOMPATIBLE :
     if status == HYP_UNKNOWN_FATAL :
         reason = "for unknown reason"
     elif status == HYP_INCOMPATIBLE :
@@ -235,17 +238,24 @@ def TreatHypoStatus(status, hypName, geomName, isAlgo):
     elif status == HYP_HIDING_ALGO:
         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
     elif status == HYP_NEED_SHAPE:
     elif status == HYP_HIDING_ALGO:
         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
     elif status == HYP_NEED_SHAPE:
-        reason = "Algorithm can't work without shape"
+        reason = "algorithm can't work without shape"
+    elif status == HYP_INCOMPAT_HYPS:
+        pass
     else:
         return
     else:
         return
-    hypName = '"' + hypName + '"'
-    geomName= '"' + geomName+ '"'
-    if status < HYP_UNKNOWN_FATAL and not geomName =='""':
-        print hypName, "was assigned to",    geomName,"but", reason
-    elif not geomName == '""':
-        print hypName, "was not assigned to",geomName,":", reason
+    where = geomName
+    if where:
+        where = '"%s"' % geomName
+        if mesh:
+            meshName = GetName( mesh )
+            if meshName and meshName != NO_NAME:
+                where = '"%s" in "%s"' % ( geomName, meshName )
+    if status < HYP_UNKNOWN_FATAL and where:
+        print '"%s" was assigned to %s but %s' %( hypName, where, reason )
+    elif where:
+        print '"%s" was not assigned to %s : %s' %( hypName, where, reason )
     else:
     else:
-        print hypName, "was not assigned:", reason
+        print '"%s" was not assigned : %s' %( hypName, reason )
         pass
 
 ## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
         pass
 
 ## Private method. Add geom (sub-shape of the main shape) into the study if not yet there
@@ -510,7 +520,8 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         #return self.IsEmbeddedMode()
         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
 
         #return self.IsEmbeddedMode()
         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
 
-    ## Sets the current study
+    ## Sets the current study. Calling SetCurrentStudy( None ) allows to
+    #  switch OFF automatic pubilishing in the Study of mesh objects.
     #  @ingroup l1_auxiliary
     def SetCurrentStudy( self, theStudy, geompyD = None ):
         #self.SetCurrentStudy(theStudy)
     #  @ingroup l1_auxiliary
     def SetCurrentStudy( self, theStudy, geompyD = None ):
         #self.SetCurrentStudy(theStudy)
@@ -526,6 +537,12 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             notebook = salome_notebook.NoteBook( theStudy )
         else:
             notebook = salome_notebook.NoteBook( salome_notebook.PseudoStudyForNoteBook() )
             notebook = salome_notebook.NoteBook( theStudy )
         else:
             notebook = salome_notebook.NoteBook( salome_notebook.PseudoStudyForNoteBook() )
+        if theStudy:
+            sb = theStudy.NewBuilder()
+            sc = theStudy.FindComponent("SMESH")
+            if sc: sb.LoadWith(sc, self)
+            pass
+        pass
 
     ## Gets the current study
     #  @ingroup l1_auxiliary
 
     ## Gets the current study
     #  @ingroup l1_auxiliary
@@ -585,14 +602,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         if error.comment: print "*** CreateMeshesFromGMF() errors:\n", error.comment
         return Mesh(self, self.geompyD, aSmeshMesh), error
 
         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
+    ## Concatenate the given meshes into one mesh. All groups of input meshes will be
+    #  present in the new mesh.
     #  @param meshes the meshes to combine into one mesh
     #  @param uniteIdenticalGroups if true, groups with same names are united, else they are renamed
     #  @param meshes the meshes to combine into one mesh
     #  @param uniteIdenticalGroups if true, groups with same names are united, else they are renamed
-    #  @param mergeNodesAndElements if true, equal nodes and elements aremerged
+    #  @param mergeNodesAndElements if true, equal nodes and elements are merged
     #  @param mergeTolerance tolerance for merging nodes
     #  @param mergeTolerance tolerance for merging nodes
-    #  @param allGroups forces creation of groups of all elements
+    #  @param allGroups forces creation of groups corresponding to every input mesh
     #  @param name name of a new mesh
     #  @param name name of a new mesh
+    #  @return an instance of Mesh class
     def Concatenate( self, meshes, uniteIdenticalGroups,
                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
                      name = ""):
     def Concatenate( self, meshes, uniteIdenticalGroups,
                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
                      name = ""):
@@ -617,7 +635,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #                  pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart
     #  @param meshName a name of the new mesh
     #  @param toCopyGroups to create in the new mesh groups the copied elements belongs to
     #                  pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart
     #  @param meshName a name of the new mesh
     #  @param toCopyGroups to create in the new mesh groups the copied elements belongs to
-    #  @param toKeepIDs to preserve IDs of the copied elements or not
+    #  @param toKeepIDs to preserve order of the copied elements or not
     #  @return an instance of Mesh class
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
         if (isinstance( meshPart, Mesh )):
     #  @return an instance of Mesh class
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
         if (isinstance( meshPart, Mesh )):
@@ -1359,9 +1377,10 @@ class Mesh:
     #  @param discardModifs if True and the mesh has been edited since
     #         a last total re-compute and that may prevent successful partial re-compute,
     #         then the mesh is cleaned before Compute()
     #  @param discardModifs if True and the mesh has been edited since
     #         a last total re-compute and that may prevent successful partial re-compute,
     #         then the mesh is cleaned before Compute()
+    #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
     #  @return True or False
     #  @ingroup l2_construct
     #  @return True or False
     #  @ingroup l2_construct
-    def Compute(self, geom=0, discardModifs=False):
+    def Compute(self, geom=0, discardModifs=False, refresh=False):
         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
             if self.geom == 0:
                 geom = self.mesh.GetShapeToMesh()
         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
             if self.geom == 0:
                 geom = self.mesh.GetShapeToMesh()
@@ -1489,7 +1508,7 @@ class Mesh:
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
-            salome.sg.updateObjBrowser(1)
+            if refresh: salome.sg.updateObjBrowser(1)
             pass
         return ok
 
             pass
         return ok
 
@@ -1506,25 +1525,28 @@ class Mesh:
         return self.mesh.SetMeshOrder(submeshes)
 
     ## Removes all nodes and elements
         return self.mesh.SetMeshOrder(submeshes)
 
     ## Removes all nodes and elements
+    #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
     #  @ingroup l2_construct
     #  @ingroup l2_construct
-    def Clear(self):
+    def Clear(self, refresh=False):
         self.mesh.Clear()
         if ( salome.sg.hasDesktop() and 
         self.mesh.Clear()
         if ( salome.sg.hasDesktop() and 
-             salome.myStudyManager.GetStudyByID( self.mesh.GetStudyId() )):
+             salome.myStudyManager.GetStudyByID( self.mesh.GetStudyId() ) ):
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
-            salome.sg.updateObjBrowser(1)
+            if refresh: salome.sg.updateObjBrowser(1)
 
     ## Removes all nodes and elements of indicated shape
 
     ## Removes all nodes and elements of indicated shape
+    #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
+    #  @param geomId the ID of a sub-shape to remove elements on
     #  @ingroup l2_construct
     #  @ingroup l2_construct
-    def ClearSubMesh(self, geomId):
+    def ClearSubMesh(self, geomId, refresh=False):
         self.mesh.ClearSubMesh(geomId)
         if salome.sg.hasDesktop():
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
         self.mesh.ClearSubMesh(geomId)
         if salome.sg.hasDesktop():
             smeshgui = salome.ImportComponentGUI("SMESH")
             smeshgui.Init(self.mesh.GetStudyId())
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
-            salome.sg.updateObjBrowser(1)
+            if refresh: salome.sg.updateObjBrowser(1)
 
     ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
 
     ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
@@ -1586,13 +1608,13 @@ class Mesh:
             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
             status = self.mesh.AddHypothesis(geom, hyp)
         else:
             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
             status = self.mesh.AddHypothesis(geom, hyp)
         else:
-            status = HYP_BAD_GEOMETRY
+            status = HYP_BAD_GEOMETRY,""
         hyp_name = GetName( hyp )
         geom_name = ""
         if geom:
             geom_name = geom.GetName()
         isAlgo = hyp._narrow( SMESH_Algo )
         hyp_name = GetName( hyp )
         geom_name = ""
         if geom:
             geom_name = geom.GetName()
         isAlgo = hyp._narrow( SMESH_Algo )
-        TreatHypoStatus( status, hyp_name, geom_name, isAlgo )
+        TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
         return status
 
     ## Return True if an algorithm of hypothesis is assigned to a given shape
         return status
 
     ## Return True if an algorithm of hypothesis is assigned to a given shape
@@ -1866,7 +1888,12 @@ class Mesh:
     #  @ingroup l2_grps_create
     def MakeGroupByIds(self, groupName, elementType, elemIDs):
         group = self.mesh.CreateGroup(elementType, groupName)
     #  @ingroup l2_grps_create
     def MakeGroupByIds(self, groupName, elementType, elemIDs):
         group = self.mesh.CreateGroup(elementType, groupName)
-        group.Add(elemIDs)
+        if hasattr( elemIDs, "GetIDs" ):
+            if hasattr( elemIDs, "SetMesh" ):
+                elemIDs.SetMesh( self.GetMesh() )
+            group.AddFrom( elemIDs )
+        else:
+            group.Add(elemIDs)
         return group
 
     ## Creates a mesh group by the given conditions
         return group
 
     ## Creates a mesh group by the given conditions
@@ -1878,7 +1905,7 @@ class Mesh:
     #  @param UnaryOp FT_LogicalNOT or FT_Undefined
     #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
     #         FT_LyingOnGeom, FT_CoplanarFaces criteria
     #  @param UnaryOp FT_LogicalNOT or FT_Undefined
     #  @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface,
     #         FT_LyingOnGeom, FT_CoplanarFaces criteria
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroup(self,
                   groupName,
     #  @ingroup l2_grps_create
     def MakeGroup(self,
                   groupName,
@@ -1895,40 +1922,32 @@ class Mesh:
     ## Creates a mesh group by the given criterion
     #  @param groupName the name of the mesh group
     #  @param Criterion the instance of Criterion class
     ## Creates a mesh group by the given criterion
     #  @param groupName the name of the mesh group
     #  @param Criterion the instance of Criterion class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByCriterion(self, groupName, Criterion):
     #  @ingroup l2_grps_create
     def MakeGroupByCriterion(self, groupName, Criterion):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aCriteria = []
-        aCriteria.append(Criterion)
-        aFilter.SetCriteria(aCriteria)
-        group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
-        return group
+        return self.MakeGroupByCriteria( groupName, [Criterion] )
 
     ## Creates a mesh group by the given criteria (list of criteria)
     #  @param groupName the name of the mesh group
     #  @param theCriteria the list of criteria
 
     ## Creates a mesh group by the given criteria (list of criteria)
     #  @param groupName the name of the mesh group
     #  @param theCriteria the list of criteria
-    #  @return SMESH_Group
+    #  @param binOp binary operator used when binary operator of criteria is undefined
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     #  @ingroup l2_grps_create
-    def MakeGroupByCriteria(self, groupName, theCriteria):
-        aFilterMgr = self.smeshpyD.CreateFilterManager()
-        aFilter = aFilterMgr.CreateFilter()
-        aFilter.SetCriteria(theCriteria)
+    def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
+        aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
         group = self.MakeGroupByFilter(groupName, aFilter)
         group = self.MakeGroupByFilter(groupName, aFilter)
-        aFilterMgr.UnRegister()
         return group
 
     ## Creates a mesh group by the given filter
     #  @param groupName the name of the mesh group
     #  @param theFilter the instance of Filter class
         return group
 
     ## Creates a mesh group by the given filter
     #  @param groupName the name of the mesh group
     #  @param theFilter the instance of Filter class
-    #  @return SMESH_Group
+    #  @return SMESH_GroupOnFilter
     #  @ingroup l2_grps_create
     def MakeGroupByFilter(self, groupName, theFilter):
     #  @ingroup l2_grps_create
     def MakeGroupByFilter(self, groupName, theFilter):
-        group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
-        theFilter.SetMesh( self.mesh )
-        group.AddFrom( theFilter )
+        #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
+        #theFilter.SetMesh( self.mesh )
+        #group.AddFrom( theFilter )
+        group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
         return group
 
     ## Removes a group
         return group
 
     ## Removes a group
@@ -2578,7 +2597,7 @@ class Mesh:
 
     ## Get measure structure specifying bounding box data of the specified object(s)
     #  @param IDs single source object or list of source objects or list of nodes/elements IDs
 
     ## Get measure structure specifying bounding box data of the specified object(s)
     #  @param IDs single source object or list of source objects or list of nodes/elements IDs
-    #  @param isElem if @a objects is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
+    #  @param isElem if @a IDs is a list of IDs, @c True value in this parameters specifies that @a objects are elements,
     #  @c False specifies that @a objects are nodes
     #  @return Measure structure
     #  @sa BoundingBox()
     #  @c False specifies that @a objects are nodes
     #  @return Measure structure
     #  @sa BoundingBox()
@@ -2964,6 +2983,37 @@ class Mesh:
             theFace = -1
         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
 
             theFace = -1
         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
 
+    ## Reorient faces according to adjacent volumes.
+    #  @param the2DObject is a mesh, sub-mesh, group or list of
+    #         either IDs of faces or face groups.
+    #  @param the3DObject is a mesh, sub-mesh, group or list of IDs of volumes.
+    #  @param theOutsideNormal to orient faces to have their normals
+    #         pointing either \a outside or \a inside the adjacent volumes.
+    #  @return number of reoriented faces.
+    #  @ingroup l2_modif_changori
+    def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
+        unRegister = genObjUnRegister()
+        # check the2DObject
+        if not isinstance( the2DObject, list ):
+            the2DObject = [ the2DObject ]
+        elif the2DObject and isinstance( the2DObject[0], int ):
+            the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
+            unRegister.set( the2DObject )
+            the2DObject = [ the2DObject ]
+        for i,obj2D in enumerate( the2DObject ):
+            if isinstance( obj2D, Mesh ):
+                the2DObject[i] = obj2D.GetMesh()
+            if isinstance( obj2D, list ):
+                the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
+                unRegister.set( the2DObject[i] )
+        # check the3DObject
+        if isinstance( the3DObject, Mesh ):
+            the3DObject = the3DObject.GetMesh()
+        if isinstance( the3DObject, list ):
+            the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
+            unRegister.set( the3DObject )
+        return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
+
     ## Fuses the neighbouring triangles into quadrangles.
     #  @param IDsOfElements The triangles to be fused,
     #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
     ## Fuses the neighbouring triangles into quadrangles.
     #  @param IDsOfElements The triangles to be fused,
     #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
@@ -3349,11 +3399,11 @@ class Mesh:
     #  them with quadratic with the same id.
     #  @param theForce3d new node creation method:
     #         0 - the medium node lies at the geometrical entity from which the mesh element is built
     #  them with quadratic with the same id.
     #  @param theForce3d new node creation method:
     #         0 - the medium node lies at the geometrical entity from which the mesh element is built
-    #         1 - the medium node lies at the middle of the line segments connecting start and end node of a mesh element
+    #         1 - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
     #  @ingroup l2_modif_tofromqu
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
     #  @ingroup l2_modif_tofromqu
-    def ConvertToQuadratic(self, theForce3d, theSubMesh=None, theToBiQuad=False):
+    def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
         if isinstance( theSubMesh, Mesh ):
             theSubMesh = theSubMesh.mesh
         if theToBiQuad:
         if isinstance( theSubMesh, Mesh ):
             theSubMesh = theSubMesh.mesh
         if theToBiQuad:
@@ -3418,7 +3468,7 @@ class Mesh:
 
     ##
     # @brief Creates missing boundary elements around either the whole mesh or 
 
     ##
     # @brief Creates missing boundary elements around either the whole mesh or 
-    #    groups of 2D elements
+    #    groups of elements
     #  @param dimension - defines type of boundary elements to create
     #  @param groupName - a name of group to store all boundary elements in,
     #    "" means not to create the group
     #  @param dimension - defines type of boundary elements to create
     #  @param groupName - a name of group to store all boundary elements in,
     #    "" means not to create the group
@@ -3426,7 +3476,7 @@ class Mesh:
     #    mesh + created boundary elements; "" means not to create the new mesh
     #  @param toCopyAll - if true, the whole initial mesh will be copied into
     #    the new mesh else only boundary elements will be copied into the new mesh
     #    mesh + created boundary elements; "" means not to create the new mesh
     #  @param toCopyAll - if true, the whole initial mesh will be copied into
     #    the new mesh else only boundary elements will be copied into the new mesh
-    #  @param groups - groups of 2D elements to make boundary around
+    #  @param groups - groups of elements to make boundary around
     #  @retval tuple( long, mesh, groups )
     #                 long - number of added boundary elements
     #                 mesh - the mesh where elements were added to
     #  @retval tuple( long, mesh, groups )
     #                 long - number of added boundary elements
     #                 mesh - the mesh where elements were added to
@@ -3439,12 +3489,12 @@ class Mesh:
         if mesh: mesh = self.smeshpyD.Mesh(mesh)
         return nb, mesh, group
 
         if mesh: mesh = self.smeshpyD.Mesh(mesh)
         return nb, mesh, group
 
-    ## Renumber mesh nodes
+    ## Renumber mesh nodes (Obsolete, does nothing)
     #  @ingroup l2_modif_renumber
     def RenumberNodes(self):
         self.editor.RenumberNodes()
 
     #  @ingroup l2_modif_renumber
     def RenumberNodes(self):
         self.editor.RenumberNodes()
 
-    ## Renumber mesh elements
+    ## Renumber mesh elements (Obsole, does nothing)
     #  @ingroup l2_modif_renumber
     def RenumberElements(self):
         self.editor.RenumberElements()
     #  @ingroup l2_modif_renumber
     def RenumberElements(self):
         self.editor.RenumberElements()
@@ -3624,6 +3674,44 @@ class Mesh:
                                       ExtrFlags, SewTolerance)
         return []
 
                                       ExtrFlags, SewTolerance)
         return []
 
+    ## Generates new elements by extrusion along the normal to a discretized surface or wire
+    #  @param Elements container of elements to extrude;
+    #         it can be Mesh, Group, Sub-mesh, Filter or list of IDs;
+    #         Only faces can be extruded so far. Sub-mesh sould be a sub-mesh on geom faces.
+    #  @param StepSize length of one extrusion step (the total extrusion
+    #         length will be \a NbOfSteps * \a StepSize ).
+    #  @param NbOfSteps number of extrusion steps.
+    #  @param ByAverageNormal if True each node is translated by \a StepSize
+    #         along the average of the normal vectors to the faces sharing the node;
+    #         else each node is translated along the same average normal till
+    #         intersection with the plane got by translation of the face sharing
+    #         the node along its own normal by \a StepSize.
+    #  @param UseInputElemsOnly to use only \a Elements when computing extrusion direction
+    #         for every node of \a Elements.
+    #  @param MakeGroups forces generation of new groups from existing ones.
+    #  @param Dim dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
+    #         is not yet implemented. This parameter is used if \a Elements contains
+    #         both faces and edges, i.e. \a Elements is a Mesh.
+    #  @return the list of created groups (SMESH_GroupBase) if \a MakeGroups=True,
+    #          empty list otherwise.
+    #  @ingroup l2_modif_extrurev
+    def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
+                          ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
+        unRegister = genObjUnRegister()
+        if isinstance( Elements, Mesh ):
+            Elements = Elements.GetMesh()
+        if isinstance( Elements, list ):
+            if not Elements:
+                raise RuntimeError, "List of element IDs is empty!"
+            if not isinstance( Elements[0], int ):
+                raise RuntimeError, "List must contain element IDs and not %s"% Elements[0]
+            Elements = self.GetIDSource( Elements, SMESH.ALL )
+            unRegister.set( Elements )
+        StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
+        self.mesh.SetParameters(Parameters)
+        return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
+                                             UseInputElemsOnly, ByAverageNormal, MakeGroups, Dim)
+
     ## Generates new elements by extrusion of the elements which belong to the object
     #  @param theObject the object which elements should be processed.
     #                   It can be a mesh, a sub mesh or a group.
     ## 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.
@@ -4093,7 +4181,7 @@ class Mesh:
 
     ## Scales the object
     #  @param theObject - the object to translate (mesh, submesh, or group)
 
     ## Scales the object
     #  @param theObject - the object to translate (mesh, submesh, or group)
-    #  @param thePoint - base point for scale
+    #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param Copy - allows copying the translated elements
     #  @param MakeGroups - forces the generation of new groups from existing
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param Copy - allows copying the translated elements
     #  @param MakeGroups - forces the generation of new groups from existing
@@ -4107,6 +4195,8 @@ class Mesh:
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject, SMESH.ALL)
             unRegister.set( theObject )
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject, SMESH.ALL)
             unRegister.set( theObject )
+        if ( isinstance( thePoint, list )):
+            thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
@@ -4121,7 +4211,7 @@ class Mesh:
 
     ## Creates a new mesh from the translated object
     #  @param theObject - the object to translate (mesh, submesh, or group)
 
     ## Creates a new mesh from the translated object
     #  @param theObject - the object to translate (mesh, submesh, or group)
-    #  @param thePoint - base point for scale
+    #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param MakeGroups - forces the generation of new groups from existing ones
     #  @param NewMeshName - the name of the newly created mesh
     #  @param theScaleFact - list of 1-3 scale factors for axises
     #  @param MakeGroups - forces the generation of new groups from existing ones
     #  @param NewMeshName - the name of the newly created mesh
@@ -4133,6 +4223,8 @@ class Mesh:
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject,SMESH.ALL)
             unRegister.set( theObject )
         if ( isinstance( theObject, list )):
             theObject = self.GetIDSource(theObject,SMESH.ALL)
             unRegister.set( theObject )
+        if ( isinstance( thePoint, list )):
+            thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):
         if ( isinstance( theScaleFact, float )):
              theScaleFact = [theScaleFact]
         if ( isinstance( theScaleFact, int )):