Salome HOME
22513: [CEA 1084] _objref_SMESH_Mesh instance has no attribute 'GetMEDMesh'
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index 736316f7f1e27e062fe3729a88dd89630571a42f..ce0a35594f1a35befb4d9109ad41333536073ffd 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
@@ -374,9 +384,12 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         #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.
+    ## 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
@@ -851,11 +864,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 +1064,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 +1076,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 +1088,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 +1157,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
@@ -1176,12 +1194,12 @@ class Mesh:
                     else:
                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
                     geompyD.addToStudy( self.geom, geo_name )
-                self.mesh = self.smeshpyD.CreateMesh(self.geom)
+                self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
 
             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
                 self.SetMesh(obj)
         else:
-            self.mesh = self.smeshpyD.CreateEmptyMesh()
+            self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
         if name:
             self.smeshpyD.SetName(self.mesh, name)
         elif objHasName:
@@ -1199,16 +1217,28 @@ class Mesh:
             if isinstance( attr, algoCreator ):
                 #print "algoCreator ", attrName
                 setattr( self, attrName, attr.copy( self ))
+                pass
+            pass
+        pass
 
+    ## Destructor. Clean-up resources
+    def __del__(self):
+        if self.mesh:
+            #self.mesh.UnRegister()
+            pass
+        pass
+        
     ## Initializes the Mesh object from an instance of SMESH_Mesh interface
     #  @param theMesh a SMESH_Mesh object
     #  @ingroup l2_construct
     def SetMesh(self, theMesh):
-        if self.mesh: self.mesh.UnRegister()
+        # do not call Register() as this prevents mesh servant deletion at closing study
+        #if self.mesh: self.mesh.UnRegister()
         self.mesh = theMesh
         if self.mesh:
-            self.mesh.Register()
+            #self.mesh.Register()
             self.geom = self.mesh.GetShapeToMesh()
+        pass
 
     ## Returns the mesh, that is an instance of SMESH_Mesh interface
     #  @return a SMESH_Mesh object
@@ -1536,13 +1566,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
 
@@ -1614,17 +1655,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)
 
@@ -1885,7 +1933,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):
@@ -2272,6 +2320,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()
@@ -2406,6 +2460,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):
@@ -3008,18 +3068,60 @@ class Mesh:
         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
 
     ## Splits volumic elements into tetrahedrons
-    #  @param elemIDs either list of elements or mesh or group or submesh
-    #  @param method  flags passing splitting method: Hex_5Tet, Hex_6Tet, Hex_24Tet
-    #         Hex_5Tet - split the hexahedron into 5 tetrahedrons, etc
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param method  flags passing splitting method:
+    #         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
+    #         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
     #  @ingroup l2_modif_cutquadr
-    def SplitVolumesIntoTetra(self, elemIDs, method=smeshBuilder.Hex_5Tet ):
+    def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
         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 )
+        self.editor.SplitVolumesIntoTetra(elems, method)
+
+    ## Splits hexahedra into prisms
+    #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
+    #  @param startHexPoint a point used to find a hexahedron for which @a facetNormal
+    #         gives a normal vector defining facets to split into triangles.
+    #         @a startHexPoint can be either a triple of coordinates or a vertex.
+    #  @param facetNormal a normal to a facet to split into triangles of a
+    #         hexahedron found by @a startHexPoint.
+    #         @a facetNormal can be either a triple of coordinates or an edge.
+    #  @param method  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
+    #         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
+    #  @param allDomains if @c False, only hexahedra adjacent to one closest
+    #         to @a startHexPoint are split, else @a startHexPoint
+    #         is used to find the facet to split in all domains present in @a elems.
+    #  @ingroup l2_modif_cutquadr
+    def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
+                                 method=smeshBuilder.Hex_2Prisms, allDomains=False ):
+        # IDSource
+        unRegister = genObjUnRegister()
+        if isinstance( elems, Mesh ):
+            elems = elems.GetMesh()
+        if ( isinstance( elems, list )):
+            elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
+            unRegister.set( elems )
+            pass
+        # axis
+        if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
+            startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
+        elif isinstance( startHexPoint, list ):
+            startHexPoint = SMESH.PointStruct( startHexPoint[0],
+                                               startHexPoint[1],
+                                               startHexPoint[2])
+        if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
+            facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
+        elif isinstance( facetNormal, list ):
+            facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
+                                                       facetNormal[1],
+                                                       facetNormal[2])
+        self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
+
+        self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
 
     ## Splits quadrangle faces near triangular facets of volumes
     #
@@ -3169,7 +3271,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,
@@ -3187,7 +3290,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,
@@ -3203,7 +3307,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,
@@ -3221,7 +3326,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,
@@ -4105,9 +4211,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)
@@ -4116,7 +4222,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()
@@ -4130,14 +4236,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 )):
@@ -4145,7 +4251,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)
@@ -4400,9 +4506,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.
@@ -4522,7 +4630,7 @@ class Mesh:
         return self._valueFromFunctor(SMESH.FT_Skew, elemId)
 
     pass # end of Mesh class
-    
+
 ## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
@@ -4643,7 +4751,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 )