Salome HOME
PAL12037. Add protection against None shapes and empty geom groups
[modules/smesh.git] / src / SMESH_SWIG / smesh.py
index 2e96ee20fbd21c13c6d898cf72559ea38848ef12..5e37242dca44710a12be8e68e0fecd9c0d86a09c 100644 (file)
@@ -77,6 +77,7 @@ class Mesh_Algorithm:
     mesh = 0
     geom = 0
     subm = 0
     mesh = 0
     geom = 0
     subm = 0
+    algo = 0
 
     def GetSubMesh(self):
         """
 
     def GetSubMesh(self):
         """
@@ -85,10 +86,50 @@ class Mesh_Algorithm:
         """
         return self.subm
 
         """
         return self.subm
 
+    def GetAlgorithm(self):
+        """
+         Return the wrapped mesher
+        """
+        return self.algo
+
+    def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
+        """
+        Private method. Print error message if a hypothesis was not assigned
+        """
+        if isAlgo:
+            hypType = "algorithm"
+        else:
+            hypType = "hypothesis"
+        if status == SMESH.HYP_UNKNOWN_FATAL :
+            reason = "for unknown reason"
+        elif status == SMESH.HYP_INCOMPATIBLE :
+            reason = "this hypothesis mismatches algorithm"
+        elif status == SMESH.HYP_NOTCONFORM :
+            reason = "not conform mesh would be built"
+        elif status == SMESH.HYP_ALREADY_EXIST :
+            reason = hypType + " of the same dimension already assigned to this shape"
+        elif status == SMESH.HYP_BAD_DIM :
+            reason = hypType + " mismatches shape"
+        elif status == SMESH.HYP_CONCURENT :
+            reason = "there are concurrent hypotheses on sub-shapes"
+        elif status == SMESH.HYP_BAD_SUBSHAPE :
+            reason = "shape is neither the main one, nor its subshape, nor a valid group"
+        else:
+            return
+        hypName = '"' + hypName + '"'
+        geomName= '"' + geomName+ '"'
+        if status < SMESH.HYP_UNKNOWN_FATAL:
+            print hypName, "was assigned to",    geomName,"but", reason
+        else:
+            print hypName, "was not assigned to",geomName,":", reason
+        pass
+
     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
         """
          Private method
         """
     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
         """
          Private method
         """
+        if geom is None:
+            raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
         self.mesh = mesh
         piece = mesh.geom
         if geom==0:
         self.mesh = mesh
         piece = mesh.geom
         if geom==0:
@@ -102,9 +143,10 @@ class Mesh_Algorithm:
                 geompy.addToStudyInFather(piece, geom, name)
             self.subm = mesh.mesh.GetSubMesh(geom, hypo)
 
                 geompy.addToStudyInFather(piece, geom, name)
             self.subm = mesh.mesh.GetSubMesh(geom, hypo)
 
-        algo = smesh.CreateHypothesis(hypo, so)
-        SetName(algo, name + "/" + hypo)
-        mesh.mesh.AddHypothesis(self.geom, algo)
+        self.algo = smesh.CreateHypothesis(hypo, so)
+        SetName(self.algo, name + "/" + hypo)
+        status = mesh.mesh.AddHypothesis(self.geom, self.algo)
+        self.TreatHypoStatus( status, hypo, name, 1 )
 
     def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
         """
 
     def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
         """
@@ -119,8 +161,10 @@ class Mesh_Algorithm:
             a = a + s + str(args[i])
             s = ","
             i = i + 1
             a = a + s + str(args[i])
             s = ","
             i = i + 1
-        SetName(hypo, GetName(self.geom) + "/" + hyp + a)
-        self.mesh.mesh.AddHypothesis(self.geom, hypo)
+        name = GetName(self.geom)
+        SetName(hypo, name + "/" + hyp + a)
+        status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
+        self.TreatHypoStatus( status, hyp, name, 0 )
         return hypo
 
 # Public class: Mesh_Segment
         return hypo
 
 # Public class: Mesh_Segment
@@ -156,6 +200,7 @@ class Mesh_Segment(Mesh_Algorithm):
             hyp = self.Hypothesis("NumberOfSegments", [n])
         else:
             hyp = self.Hypothesis("NumberOfSegments", [n,s])
             hyp = self.Hypothesis("NumberOfSegments", [n])
         else:
             hyp = self.Hypothesis("NumberOfSegments", [n,s])
+            hyp.SetDistrType( 1 )
             hyp.SetScaleFactor(s)
         hyp.SetNumberOfSegments(n)
         return hyp
             hyp.SetScaleFactor(s)
         hyp.SetNumberOfSegments(n)
         return hyp
@@ -198,6 +243,27 @@ class Mesh_Segment(Mesh_Algorithm):
         """
         return self.Hypothesis("Propagation")
 
         """
         return self.Hypothesis("Propagation")
 
+    def AutomaticLength(self, fineness=0):
+        """
+         Define "AutomaticLength" hypothesis
+         \param fineness for the fineness [0-1]
+        """
+        hyp = self.Hypothesis("AutomaticLength")
+        hyp.SetFineness( fineness )
+        return hyp
+
+    def QuadraticMesh(self):
+        """
+         Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
+         If the 2D mesher sees that all boundary edges are quadratic ones,
+         it generates quadratic faces, else it generates linear faces using
+         medium nodes as if they were vertex ones.
+         The 3D mesher generates quadratic volumes only if all boundary faces
+         are quadratic ones, else it fails.
+        """
+        hyp = self.Hypothesis("QuadraticMesh")
+        return hyp
+
 # Public class: Mesh_Segment_Python
 # ---------------------------------
 
 # Public class: Mesh_Segment_Python
 # ---------------------------------
 
@@ -267,6 +333,15 @@ class Mesh_Quadrangle(Mesh_Algorithm):
         """
         self.Create(mesh, geom, "Quadrangle_2D")
 
         """
         self.Create(mesh, geom, "Quadrangle_2D")
 
+    def QuadranglePreference(self):
+        """
+         Define "QuadranglePreference" hypothesis, forcing construction
+         of quadrangles if the number of nodes on opposite edges is not the same
+         in the case where the global number of nodes on edges is even
+        """
+        hyp = self.Hypothesis("QuadranglePreference")
+        return hyp
+
 # Public class: Mesh_Tetrahedron
 # ------------------------------
 
 # Public class: Mesh_Tetrahedron
 # ------------------------------
 
@@ -347,6 +422,21 @@ class Mesh:
         """
         return self.geom
 
         """
         return self.geom
 
+    def MeshDimension(self):
+        """
+        Returns mesh dimension depending on shape one
+        """
+        shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
+        if len( shells ) > 0 :
+            return 3
+        elif geompy.NumberOfFaces( self.geom ) > 0 :
+            return 2
+        elif geompy.NumberOfEdges( self.geom ) > 0 :
+            return 1
+        else:
+            return 0;
+        pass
+
     def Segment(self, algo=REGULAR, geom=0):
         """
          Creates a segment discretization 1D algorithm.
     def Segment(self, algo=REGULAR, geom=0):
         """
          Creates a segment discretization 1D algorithm.
@@ -356,12 +446,16 @@ class Mesh:
          \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
          \param geom If defined, subshape to be meshed
         """
          \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
          \param geom If defined, subshape to be meshed
         """
+        ## if Segment(geom) is called by mistake
+        if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
+            algo, geom = geom, algo
+            pass
         if algo == REGULAR:
             return Mesh_Segment(self, geom)
         elif algo == PYTHON:
             return Mesh_Segment_Python(self, geom)
         else:
         if algo == REGULAR:
             return Mesh_Segment(self, geom)
         elif algo == PYTHON:
             return Mesh_Segment_Python(self, geom)
         else:
-            return Mesh_Segment(self, algo)
+            return Mesh_Segment(self, geom)
 
     def Triangle(self, geom=0):
         """
 
     def Triangle(self, geom=0):
         """
@@ -390,6 +484,10 @@ class Mesh:
          \param algo values are: smesh.NETGEN, smesh.GHS3D
          \param geom If defined, subshape to be meshed
         """
          \param algo values are: smesh.NETGEN, smesh.GHS3D
          \param geom If defined, subshape to be meshed
         """
+        ## if Tetrahedron(geom) is called by mistake
+        if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
+            algo, geom = geom, algo
+            pass
         return Mesh_Tetrahedron(self, algo, geom)
 
     def Hexahedron(self, geom=0):
         return Mesh_Tetrahedron(self, algo, geom)
 
     def Hexahedron(self, geom=0):
@@ -403,12 +501,88 @@ class Mesh:
 
     def Compute(self):
         """
 
     def Compute(self):
         """
-         Compute the mesh and return the status of the computation
-        """
-        b = smesh.Compute(self.mesh, self.geom)
+        Compute the mesh and return the status of the computation
+        """
+        ok = smesh.Compute(self.mesh, self.geom)
+        if not ok:
+            errors = smesh.GetAlgoState( self.mesh, self.geom )
+            allReasons = ""
+            for err in errors:
+                if err.isGlobalAlgo:
+                    glob = " global "
+                else:
+                    glob = " local "
+                    pass
+                dim = str(err.algoDim)
+                if err.name == SMESH.MISSING_ALGO:
+                    reason = glob + dim + "D algorithm is missing"
+                elif err.name == SMESH.MISSING_HYPO:
+                    name = '"' + err.algoName + '"'
+                    reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
+                else:
+                    reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
+                    pass
+                if allReasons != "":
+                    allReasons += "\n"
+                    pass
+                allReasons += reason
+                pass
+            if allReasons != "":
+                print '"' + GetName(self.mesh) + '"',"not computed:"
+                print allReasons
+                pass
+            pass
         if salome.sg.hasDesktop():
         if salome.sg.hasDesktop():
+            smeshgui = salome.ImportComponentGUI("SMESH")
+            smeshgui.Init(salome.myStudyId)
+            smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
             salome.sg.updateObjBrowser(1)
             salome.sg.updateObjBrowser(1)
-        return b
+            pass
+        return ok
+
+    def AutomaticTetrahedralization(self, fineness=0):
+        """
+        Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
+        The parameter \a fineness [0.-1.] defines mesh fineness
+        """
+        dim = self.MeshDimension()
+        # assign hypotheses
+        self.RemoveGlobalHypotheses()
+        self.Segment().AutomaticLength(fineness)
+        if dim > 1 :
+            self.Triangle().LengthFromEdges()
+            pass
+        if dim > 2 :
+            self.Tetrahedron(NETGEN)
+            pass
+        return self.Compute()
+
+    def AutomaticHexahedralization(self, fineness=0):
+        """
+        Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
+        The parameter \a fineness [0.-1.] defines mesh fineness
+        """
+        dim = self.MeshDimension()
+        # assign hypotheses
+        self.RemoveGlobalHypotheses()
+        self.Segment().AutomaticLength(fineness)
+        if dim > 1 :
+            self.Quadrangle()
+            pass
+        if dim > 2 :
+            self.Hexahedron()            
+            pass
+        return self.Compute()
+
+    def RemoveGlobalHypotheses(self):
+        """
+        Removes all global hypotheses
+        """
+        current_hyps = self.mesh.GetHypothesisList( self.geom )
+        for hyp in current_hyps:
+            self.mesh.RemoveHypothesis( self.geom, hyp )
+            pass
+        pass
 
     def Group(self, grp, name=""):
         """
 
     def Group(self, grp, name=""):
         """
@@ -434,6 +608,9 @@ class Mesh:
         elif tgeo == "SHELL":
             type = SMESH.VOLUME
         elif tgeo == "COMPOUND":
         elif tgeo == "SHELL":
             type = SMESH.VOLUME
         elif tgeo == "COMPOUND":
+            if len( geompy.GetObjectIDs( grp )) == 0:
+                print "Mesh.Group: empty geometric group", GetName( grp )
+                return 0
             tgeo = geompy.GetType(grp)
             if tgeo == geompy.ShapeType["VERTEX"]:
                 type = SMESH.NODE
             tgeo = geompy.GetType(grp)
             if tgeo == geompy.ShapeType["VERTEX"]:
                 type = SMESH.NODE
@@ -454,7 +631,7 @@ class Mesh:
         """
          Export the mesh in a file with the MED format and choice the \a version of MED format
          \param f is the file name
         """
          Export the mesh in a file with the MED format and choice the \a version of MED format
          \param f is the file name
-         \param version values are smesh.MED_V2_1, smesh.MED_V2_2
+         \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
         """
         self.mesh.ExportToMED(f, opt, version)
 
         """
         self.mesh.ExportToMED(f, opt, version)