Salome HOME
Fix Mirror*() to correctly work with a mirror given as a GEOM object
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index b82ba1ee5314c27e1d630b45e021985a19ee169c..767a5ef1494913132133776c59f6b145c60c6b63 100644 (file)
@@ -1,9 +1,9 @@
-# Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
-# version 2.1 of the License.
+# version 2.1 of the License, or (at your option) any later version.
 #
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -73,7 +73,7 @@
 ##   @defgroup l2_modif_invdiag  Diagonal inversion of elements
 ##   @defgroup l2_modif_unitetri Uniting triangles
 ##   @defgroup l2_modif_changori Changing orientation of elements
-##   @defgroup l2_modif_cutquadr Cutting quadrangles
+##   @defgroup l2_modif_cutquadr Cutting elements
 ##   @defgroup l2_modif_smooth   Smoothing
 ##   @defgroup l2_modif_extrurev Extrusion and Revolution
 ##   @defgroup l2_modif_patterns Pattern mapping
@@ -93,6 +93,16 @@ import SALOME
 import SALOMEDS
 import os
 
+class MeshMeta(type):
+    def __instancecheck__(cls, inst):
+        """Implement isinstance(inst, cls)."""
+        return any(cls.__subclasscheck__(c)
+                   for c in {type(inst), inst.__class__})
+
+    def __subclasscheck__(cls, sub):
+        """Implement issubclass(sub, cls)."""
+        return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
+
 ## @addtogroup l1_auxiliary
 ## @{
 
@@ -307,7 +317,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = range(4)
 
     # Methods of splitting a hexahedron into tetrahedra
-    Hex_5Tet, Hex_6Tet, Hex_24Tet = 1, 2, 3
+    Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
 
     def __new__(cls):
         global engine
@@ -373,10 +383,16 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     def init_smesh(self,theStudy,geompyD = None):
         #print "init_smesh"
         self.SetCurrentStudy(theStudy,geompyD)
-
-    ## Creates an empty Mesh. This mesh can have an underlying geometry.
-    #  @param obj the Geometrical object on which the mesh is built. If not defined,
-    #             the mesh will have no underlying geometry.
+        if theStudy:
+            global notebook
+            notebook.myStudy = theStudy
+
+    ## Creates a mesh. This can be either an empty mesh, possibly having an underlying geometry,
+    #  or a mesh wrapping a CORBA mesh given as a parameter.
+    #  @param obj either (1) a CORBA mesh (SMESH._objref_SMESH_Mesh) got e.g. by calling
+    #         salome.myStudy.FindObjectID("0:1:2:3").GetObject() or
+    #         (2) a Geometrical object for meshing or
+    #         (3) none.
     #  @param name the name for the new mesh.
     #  @return an instance of Mesh class.
     #  @ingroup l2_construct
@@ -440,7 +456,9 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @return SMESH.AxisStruct
     #  @ingroup l1_auxiliary
     def GetAxisStruct(self,theObj):
+        import GEOM
         edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
+        axis = None
         if len(edges) > 1:
             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
             vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
@@ -452,14 +470,18 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
             normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
-            return axis
+            axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
         elif len(edges) == 1:
             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
             p1 = self.geompyD.PointCoordinates( vertex1 )
             p2 = self.geompyD.PointCoordinates( vertex2 )
             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
-            return axis
-        return None
+            axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
+        elif theObj.GetShapeType() == GEOM.VERTEX:
+            x,y,z = self.geompyD.PointCoordinates( theObj )
+            axis = AxisStruct( x,y,z, 1,0,0,)
+            axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
+        return axis
 
     # From SMESH_Gen interface:
     # ------------------------
@@ -851,11 +873,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
     ## Creates a filter from criteria
     #  @param criteria a list of criteria
+    #  @param binOp binary operator used when binary operator of criteria is undefined
     #  @return SMESH_Filter
     #
     #  <a href="../tui_filters_page.html#tui_filters">Example of Filters usage</a>
     #  @ingroup l1_controls
-    def GetFilterFromCriteria(self,criteria):
+    def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
+        for i in range( len( criteria ) - 1 ):
+            if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
+                criteria[i].BinaryOp = self.EnumToLong( binOp )
         aFilterMgr = self.CreateFilterManager()
         aFilter = aFilterMgr.CreateFilter()
         aFilter.SetCriteria(criteria)
@@ -1047,7 +1073,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return result
 
     ## Get sum of lengths of all 1D elements in the mesh object.
-    #  @param elemId obj mesh, submesh or group
+    #  @param obj mesh, submesh or group
     #  @return sum of lengths of all 1D elements
     #  @ingroup l1_measurements
     def GetLength(self, obj):
@@ -1059,7 +1085,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return value
 
     ## Get sum of areas of all 2D elements in the mesh object.
-    #  @param elemId obj mesh, submesh or group
+    #  @param obj mesh, submesh or group
     #  @return sum of areas of all 2D elements
     #  @ingroup l1_measurements
     def GetArea(self, obj):
@@ -1071,7 +1097,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return value
 
     ## Get sum of volumes of all 3D elements in the mesh object.
-    #  @param elemId obj mesh, submesh or group
+    #  @param obj mesh, submesh or group
     #  @return sum of volumes of all 3D elements
     #  @ingroup l1_measurements
     def GetVolume(self, obj):
@@ -1140,6 +1166,7 @@ def New( study, instance=None):
 #  new nodes and elements and by changing the existing entities), to get information
 #  about a mesh and to export a mesh into different formats.
 class Mesh:
+    __metaclass__ = MeshMeta
 
     geom = 0
     mesh = 0
@@ -1499,7 +1526,7 @@ class Mesh:
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             salome.sg.updateObjBrowser(1)
 
-    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
+    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
@@ -1512,8 +1539,7 @@ class Mesh:
             self.Triangle().LengthFromEdges()
             pass
         if dim > 2 :
-            from salome.NETGENPlugin.NETGENPluginBuilder import NETGEN
-            self.Tetrahedron(NETGEN)
+            self.Tetrahedron()
             pass
         return self.Compute()
 
@@ -1548,13 +1574,24 @@ class Mesh:
             if not geom:
                 geom = self.mesh.GetShapeToMesh()
             pass
-        AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
-        status = self.mesh.AddHypothesis(geom, hyp)
-        isAlgo = hyp._narrow( SMESH_Algo )
+        isApplicable = True
+        if self.mesh.HasShapeToMesh():
+            hyp_type     = hyp.GetName()
+            lib_name     = hyp.GetLibName()
+            checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
+            if checkAll and geom:
+                checkAll = geom.GetType() == 37
+            isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
+        if isApplicable:
+            AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
+            status = self.mesh.AddHypothesis(geom, hyp)
+        else:
+            status = HYP_BAD_GEOMETRY
         hyp_name = GetName( hyp )
         geom_name = ""
         if geom:
-            geom_name = GetName( geom )
+            geom_name = geom.GetName()
+        isAlgo = hyp._narrow( SMESH_Algo )
         TreatHypoStatus( status, hyp_name, geom_name, isAlgo )
         return status
 
@@ -1626,17 +1663,24 @@ class Mesh:
     #         - 1D if all mesh nodes lie on OX coordinate axis, or
     #         - 2D if all mesh nodes lie on XOY coordinate plane, or
     #         - 3D in the rest cases.
-    #
     #         If @a autoDimension is @c False, the space dimension is always 3.
+    #  @param fields : list of GEOM fields defined on the shape to mesh.
+    #  @param geomAssocFields : each character of this string means a need to export a 
+    #         corresponding field; correspondence between fields and characters is following:
+    #         - 'v' stands for _vertices_ field;
+    #         - 'e' stands for _edges_ field;
+    #         - 'f' stands for _faces_ field;
+    #         - 's' stands for _solids_ field.
     #  @ingroup l2_impexp
     def ExportMED(self, f, auto_groups=0, version=MED_V2_2,
-                  overwrite=1, meshPart=None, autoDimension=True):
-        if meshPart:
+                  overwrite=1, meshPart=None, autoDimension=True, fields=[], geomAssocFields=''):
+        if meshPart or fields or geomAssocFields:
             unRegister = genObjUnRegister()
             if isinstance( meshPart, list ):
                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
                 unRegister.set( meshPart )
-            self.mesh.ExportPartToMED( meshPart, f, auto_groups, version, overwrite, autoDimension)
+            self.mesh.ExportPartToMED( meshPart, f, auto_groups, version, overwrite, autoDimension,
+                                       fields, geomAssocFields)
         else:
             self.mesh.ExportToMEDX(f, auto_groups, version, overwrite, autoDimension)
 
@@ -1897,7 +1941,7 @@ class Mesh:
     def RemoveGroupWithContents(self, group):
         self.mesh.RemoveGroupWithContents(group)
 
-    ## Gets the list of groups existing in the mesh
+    ## Gets the list of groups existing in the mesh in the order of creation (starting from the oldest one)
     #  @return a sequence of SMESH_GroupBase
     #  @ingroup l2_grps_create
     def GetGroups(self):
@@ -2284,6 +2328,12 @@ class Mesh:
     def GetElementGeomType(self, id):
         return self.mesh.GetElementGeomType(id)
 
+    ## Returns the shape type of mesh element
+    #  @return the value from SMESH::GeometryType enumeration
+    #  @ingroup l1_meshinfo
+    def GetElementShape(self, id):
+        return self.mesh.GetElementShape(id)
+
     ## Returns the list of submesh elements IDs
     #  @param Shape a geom object(sub-shape) IOR
     #         Shape must be the sub-shape of a ShapeToMesh()
@@ -2418,6 +2468,12 @@ class Mesh:
     def GetElemFaceNodes(self,elemId, faceIndex):
         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
 
+    ## Returns three components of normal of given mesh face
+    #  (or an empty array in KO case)
+    #  @ingroup l1_meshinfo
+    def GetFaceNormal(self, faceId, normalized=False):
+        return self.mesh.GetFaceNormal(faceId,normalized)
+
     ## Returns an element based on all given nodes.
     #  @ingroup l1_meshinfo
     def FindElementByNodes(self,nodes):
@@ -3020,18 +3076,60 @@ class Mesh:
         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
 
     ## Splits volumic elements into tetrahedrons
-    #  @param elemIDs either list of elements or mesh or group or submesh
-    #  @param method  flags passing splitting method: Hex_5Tet, Hex_6Tet, Hex_24Tet
-    #         Hex_5Tet - split the hexahedron into 5 tetrahedrons, etc
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param method  flags passing splitting method:
+    #         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
+    #         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
+    #  @ingroup l2_modif_cutquadr
+    def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
+        unRegister = genObjUnRegister()
+        if isinstance( elems, Mesh ):
+            elems = elems.GetMesh()
+        if ( isinstance( elems, list )):
+            elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
+            unRegister.set( elems )
+        self.editor.SplitVolumesIntoTetra(elems, method)
+
+    ## Splits hexahedra into prisms
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param startHexPoint a point used to find a hexahedron for which @a facetNormal
+    #         gives a normal vector defining facets to split into triangles.
+    #         @a startHexPoint can be either a triple of coordinates or a vertex.
+    #  @param facetNormal a normal to a facet to split into triangles of a
+    #         hexahedron found by @a startHexPoint.
+    #         @a facetNormal can be either a triple of coordinates or an edge.
+    #  @param method  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
+    #         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
+    #  @param allDomains if @c False, only hexahedra adjacent to one closest
+    #         to @a startHexPoint are split, else @a startHexPoint
+    #         is used to find the facet to split in all domains present in @a elems.
     #  @ingroup l2_modif_cutquadr
-    def SplitVolumesIntoTetra(self, elemIDs, method=smeshBuilder.Hex_5Tet ):
+    def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
+                                 method=smeshBuilder.Hex_2Prisms, allDomains=False ):
+        # IDSource
         unRegister = genObjUnRegister()
-        if isinstance( elemIDs, Mesh ):
-            elemIDs = elemIDs.GetMesh()
-        if ( isinstance( elemIDs, list )):
-            elemIDs = self.editor.MakeIDSource(elemIDs, SMESH.VOLUME)
-            unRegister.set( elemIDs )
-        self.editor.SplitVolumesIntoTetra(elemIDs, method)
+        if isinstance( elems, Mesh ):
+            elems = elems.GetMesh()
+        if ( isinstance( elems, list )):
+            elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
+            unRegister.set( elems )
+            pass
+        # axis
+        if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
+            startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
+        elif isinstance( startHexPoint, list ):
+            startHexPoint = SMESH.PointStruct( startHexPoint[0],
+                                               startHexPoint[1],
+                                               startHexPoint[2])
+        if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
+            facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
+        elif isinstance( facetNormal, list ):
+            facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
+                                                       facetNormal[1],
+                                                       facetNormal[2])
+        self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
+
+        self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
 
     ## Splits quadrangle faces near triangular facets of volumes
     #
@@ -3181,7 +3279,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
@@ -3199,7 +3298,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothObject(self, theObject, IDsOfFixedNodes,
@@ -3215,7 +3315,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method is Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
@@ -3233,7 +3334,8 @@ class Mesh:
     #  Note that nodes built on edges and boundary nodes are always fixed.
     #  @param MaxNbOfIterations the maximum number of iterations
     #  @param MaxAspectRatio varies in range [1.0, inf]
-    #  @param Method Laplacian(LAPLACIAN_SMOOTH) or Centroidal(CENTROIDAL_SMOOTH)
+    #  @param Method is either Laplacian (smesh.LAPLACIAN_SMOOTH)
+    #         or Centroidal (smesh.CENTROIDAL_SMOOTH)
     #  @return TRUE in case of success, FALSE otherwise.
     #  @ingroup l2_modif_smooth
     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
@@ -3834,12 +3936,14 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_trsf
-    def Mirror(self, IDsOfElements, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
@@ -3854,12 +3958,14 @@ class Mesh:
     #  @param NewMeshName a name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType, MakeGroups=0, NewMeshName=""):
+    def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
         if IDsOfElements == []:
             IDsOfElements = self.GetElementsId()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
                                           MakeGroups, NewMeshName)
         return Mesh(self.smeshpyD,self.geompyD,mesh)
@@ -3873,12 +3979,14 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_trsf
-    def MirrorObject (self, theObject, Mirror, theMirrorType, Copy=0, MakeGroups=False):
+    def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         if Copy and MakeGroups:
             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
@@ -3893,12 +4001,14 @@ class Mesh:
     #  @param NewMeshName the name of the new mesh to create
     #  @return instance of Mesh class
     #  @ingroup l2_modif_trsf
-    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType,MakeGroups=0, NewMeshName=""):
+    def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
         if ( isinstance( theObject, Mesh )):
             theObject = theObject.GetMesh()
-        if (isinstance(Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
-            Mirror = self.smeshpyD.GetAxisStruct(Mirror)
-        self.mesh.SetParameters(Mirror.parameters)
+        if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
+            Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
+            theMirrorType = Mirror._mirrorType
+        else:
+            self.mesh.SetParameters(Mirror.parameters)
         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
                                                 MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD,self.geompyD,mesh )
@@ -4117,9 +4227,9 @@ class Mesh:
         self.mesh.SetParameters(Parameters)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
 
-    ## Finds groups of ajacent nodes within Tolerance.
+    ## Finds groups of adjacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
-    #  @return the list of groups of nodes
+    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindCoincidentNodes (self, Tolerance):
         return self.editor.FindCoincidentNodes(Tolerance)
@@ -4128,7 +4238,7 @@ class Mesh:
     #  @param Tolerance the value of tolerance
     #  @param SubMeshOrGroup SubMesh or Group
     #  @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
-    #  @return the list of groups of nodes
+    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]):
         unRegister = genObjUnRegister()
@@ -4142,14 +4252,14 @@ class Mesh:
         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes)
 
     ## Merges nodes
-    #  @param GroupsOfNodes the list of groups of nodes
+    #  @param GroupsOfNodes a list of pairs of nodes IDs for merging (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def MergeNodes (self, GroupsOfNodes):
         self.editor.MergeNodes(GroupsOfNodes)
 
     ## Finds the elements built on the same nodes.
     #  @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
-    #  @return a list of groups of equal elements
+    #  @return the list of pairs of equal elements IDs (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def FindEqualElements (self, MeshOrSubMeshOrGroup):
         if ( isinstance( MeshOrSubMeshOrGroup, Mesh )):
@@ -4157,7 +4267,7 @@ class Mesh:
         return self.editor.FindEqualElements(MeshOrSubMeshOrGroup)
 
     ## Merges elements in each given group.
-    #  @param GroupsOfElementsID groups of elements for merging
+    #  @param GroupsOfElementsID a list of pairs of elements IDs for merging (e.g. [[1,12],[25,4]])
     #  @ingroup l2_modif_trsf
     def MergeElements(self, GroupsOfElementsID):
         self.editor.MergeElements(GroupsOfElementsID)
@@ -4412,9 +4522,11 @@ class Mesh:
     # Triangles are transformed in prisms, and quadrangles in hexahedrons.
     # @param theDomains - list of groups of volumes
     # @param createJointElems - if TRUE, create the elements
+    # @param onAllBoundaries - if TRUE, the nodes and elements are also created on
+    #        the boundary between \a theDomains and the rest mesh
     # @return TRUE if operation has been completed successfully, FALSE otherwise
-    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
-       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
+    def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
+       return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
 
     ## Double nodes on some external faces and create flat elements.
     # Flat elements are mainly used by some types of mechanic calculations.
@@ -4533,8 +4645,31 @@ class Mesh:
     def GetSkew(self, elemId):
         return self._valueFromFunctor(SMESH.FT_Skew, elemId)
 
+    ## Return minimal and maximal value of a given functor.
+    #  @param funType a functor type, an item of SMESH.FunctorType enum
+    #         (one of SMESH.FunctorType._items)
+    #  @param meshPart a part of mesh (group, sub-mesh) to treat
+    #  @return tuple (min,max)
+    #  @ingroup l1_measurements
+    def GetMinMax(self, funType, meshPart=None):
+        unRegister = genObjUnRegister()
+        if isinstance( meshPart, list ):
+            meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+            unRegister.set( meshPart )
+        if isinstance( meshPart, Mesh ):
+            meshPart = meshPart.mesh
+        fun = self._getFunctor( funType )
+        if fun:
+            if meshPart:
+                hist = fun.GetLocalHistogram( 1, False, meshPart )
+            else:
+                hist = fun.GetHistogram( 1, False )
+            if hist:
+                return hist[0].min, hist[0].max
+        return None
+
     pass # end of Mesh class
-    
+
 ## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
@@ -4655,7 +4790,8 @@ for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
     try:
         exec( "from salome.%s.%s import *" % (pluginName, pluginBuilderName))
     except Exception, e:
-        print "Exception while loading %s: %s" % ( pluginBuilderName, e )
+       from salome_utils import verbose
+       if verbose(): print "Exception while loading %s: %s" % ( pluginBuilderName, e )
         continue
     exec( "from salome.%s import %s" % (pluginName, pluginBuilderName))
     plugin = eval( pluginBuilderName )