Salome HOME
23179: EDF 11603 - Problem with extrusion when path is not well oriented
[modules/smesh.git] / src / SMESH_SWIG / smesh_algorithm.py
index e72a81f8e8f14dad711cd502b2cfadf7bd0a8d58..a57b034633f9e65d9c1a8e809aece3bd0405a79f 100644 (file)
@@ -1,9 +1,9 @@
-# Copyright (C) 2007-2013  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
 # 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
@@ -23,7 +23,7 @@
 
 import salome
 from salome.geom import geomBuilder
-import SMESH
+import SMESH, StdMeshers
 
 ## The base class to define meshing algorithms
 #
@@ -40,7 +40,7 @@ import SMESH
 #    @code
 #    meshMethod = "MyAlgorithm"
 #    @endcode
-#    then an instance of @c MyPlugin_Algorithm can be created by the direct invokation of the function
+#    then an instance of @c MyPlugin_Algorithm can be created by the direct invocation of the function
 #    of smesh.Mesh class:
 #    @code
 #    my_algo = mesh.MyAlgorithm()
@@ -85,6 +85,7 @@ class Mesh_Algorithm:
                     attr = hypo_so_i.FindAttribute("AttributeIOR")[1]
                     if attr is not None:
                         anIOR = attr.Value()
+                        if not anIOR: continue # prevent exception in orb.string_to_object()
                         hypo_o_i = salome.orb.string_to_object(anIOR)
                         if hypo_o_i is not None:
                             # Check if this is a hypothesis
@@ -128,6 +129,7 @@ class Mesh_Algorithm:
                     attr = algo_so_i.FindAttribute("AttributeIOR")[1]
                     if attr is not None:
                         anIOR = attr.Value()
+                        if not anIOR: continue # prevent exception in orb.string_to_object()
                         algo_o_i = salome.orb.string_to_object(anIOR)
                         if algo_o_i is not None:
                             # Check if this is an algorithm
@@ -180,7 +182,7 @@ class Mesh_Algorithm:
 
     ## Private method.
     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
-        if geom is None:
+        if geom is None and mesh.mesh.HasShapeToMesh():
             raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
         algo = self.FindAlgorithm(hypo, mesh.smeshpyD)
         if algo is None:
@@ -192,24 +194,17 @@ class Mesh_Algorithm:
     ## Private method
     def Assign(self, algo, mesh, geom):
         from salome.smesh.smeshBuilder import AssureGeomPublished, TreatHypoStatus, GetName
-        if geom is None:
+        if geom is None and mesh.mesh.HasShapeToMesh():
             raise RuntimeError, "Attemp to create " + algo + " algoritm on None shape"
         self.mesh = mesh
-        name = ""
         if not geom or geom.IsSame( mesh.geom ):
             self.geom = mesh.geom
         else:
             self.geom = geom
             AssureGeomPublished( mesh, geom )
-            try:
-                name = GetName(geom)
-                pass
-            except:
-                pass
             self.subm = mesh.mesh.GetSubMesh(geom, algo.GetName())
         self.algo = algo
-        status = mesh.mesh.AddHypothesis(self.geom, self.algo)
-        TreatHypoStatus( status, algo.GetName(), name, True )
+        status = mesh.AddHypothesis(self.algo, self.geom)
         return
 
     def CompareHyp (self, hyp, args):
@@ -221,7 +216,7 @@ class Mesh_Algorithm:
 
     ## Private method
     def Hypothesis (self, hyp, args=[], so="libStdMeshersEngine.so",
-                    UseExisting=0, CompareMethod=""):
+                    UseExisting=0, CompareMethod="", toAdd=True):
         from salome.smesh.smeshBuilder import TreatHypoStatus, GetName
         hypo = None
         if UseExisting:
@@ -250,8 +245,9 @@ class Mesh_Algorithm:
         geomName=""
         if self.geom:
             geomName = GetName(self.geom)
-        status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
-        TreatHypoStatus( status, GetName(hypo), geomName, 0 )
+        if toAdd:
+            status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
+            TreatHypoStatus( status, GetName(hypo), geomName, 0, self.mesh )
         return hypo
 
     ## Returns entry of the shape to mesh in the study
@@ -263,51 +259,89 @@ class Mesh_Algorithm:
 
     ## Defines "ViscousLayers" hypothesis to give parameters of layers of prisms to build
     #  near mesh boundary. This hypothesis can be used by several 3D algorithms:
-    #  NETGEN 3D, GHS3D, Hexahedron(i,j,k)
+    #  NETGEN 3D, MG-Tetra, Hexahedron(i,j,k)
     #  @param thickness total thickness of layers of prisms
     #  @param numberOfLayers number of layers of prisms
     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
-    #  @param ignoreFaces list of geometrical faces (or their ids) not to generate layers on
+    #  @param faces list of geometrical faces (or their ids).
+    #         Viscous layers are either generated on these faces or not, depending on
+    #         the value of \a isFacesToIgnore parameter.
+    #  @param isFacesToIgnore if \c True, the Viscous layers are not generated on the
+    #         faces specified by the previous parameter (\a faces).
+    #  @param extrMethod extrusion method defines how position of new nodes are found during
+    #         prism construction and how creation of distorted and intersecting prisms is
+    #         prevented. Possible values are:
+    #       - StdMeshers.SURF_OFFSET_SMOOTH (default) method extrudes nodes along normal
+    #         to underlying geometrical surface. Smoothing of internal surface of
+    #         element layers can be used to avoid creation of invalid prisms.
+    #       - StdMeshers.FACE_OFFSET method extrudes nodes along average normal of
+    #         surrounding mesh faces till intersection with a neighbor mesh face
+    #         translated along its own normal by the layers thickness. Thickness
+    #         of layers can be limited to avoid creation of invalid prisms.
+    #       - StdMeshers.NODE_OFFSET method extrudes nodes along average normal of
+    #         surrounding mesh faces by the layers thickness. Thickness of
+    #         layers can be limited to avoid creation of invalid prisms.
     #  @ingroup l3_hypos_additi
-    def ViscousLayers(self, thickness, numberOfLayers, stretchFactor, ignoreFaces=[]):
+    def ViscousLayers(self, thickness, numberOfLayers, stretchFactor,
+                      faces=[], isFacesToIgnore=True, extrMethod=StdMeshers.SURF_OFFSET_SMOOTH ):
         if not isinstance(self.algo, SMESH._objref_SMESH_3D_Algo):
             raise TypeError, "ViscousLayers are supported by 3D algorithms only"
         if not "ViscousLayers" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
-        if ignoreFaces and isinstance( ignoreFaces[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            ignoreFaces = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreFaces ]
+        if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
+            faceIDs = []
+            for shape in faces:
+                ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] )
+                for f in ff:
+                    faceIDs.append( self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f))
+            faces = faceIDs
         hyp = self.Hypothesis("ViscousLayers",
-                              [thickness, numberOfLayers, stretchFactor, ignoreFaces])
-        hyp.SetTotalThickness(thickness)
-        hyp.SetNumberLayers(numberOfLayers)
-        hyp.SetStretchFactor(stretchFactor)
-        hyp.SetIgnoreFaces(ignoreFaces)
+                              [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
+                              toAdd=False)
+        hyp.SetTotalThickness( thickness )
+        hyp.SetNumberLayers( numberOfLayers )
+        hyp.SetStretchFactor( stretchFactor )
+        hyp.SetFaces( faces, isFacesToIgnore )
+        hyp.SetMethod( extrMethod )
+        self.mesh.AddHypothesis( hyp, self.geom )
         return hyp
 
     ## Defines "ViscousLayers2D" hypothesis to give parameters of layers of quadrilateral
     #  elements to build near mesh boundary. This hypothesis can be used by several 2D algorithms:
-    #  NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, BLSURF
+    #  NETGEN 2D, NETGEN 1D-2D, Quadrangle (mapping), MEFISTO, MG-CADSurf
     #  @param thickness total thickness of layers of quadrilaterals
     #  @param numberOfLayers number of layers
     #  @param stretchFactor factor (>1.0) of growth of layer thickness towards inside of mesh
-    #  @param ignoreEdges list of geometrical edge (or their ids) not to generate layers on
+    #  @param edges list of geometrical edges (or their ids).
+    #         Viscous layers are either generated on these edges or not, depending on
+    #         the value of \a isEdgesToIgnore parameter.
+    #  @param isEdgesToIgnore if \c True, the Viscous layers are not generated on the
+    #         edges specified by the previous parameter (\a edges).
     #  @ingroup l3_hypos_additi
-    def ViscousLayers2D(self, thickness, numberOfLayers, stretchFactor, ignoreEdges=[]):
+    def ViscousLayers2D(self, thickness, numberOfLayers, stretchFactor,
+                        edges=[], isEdgesToIgnore=True ):
         if not isinstance(self.algo, SMESH._objref_SMESH_2D_Algo):
             raise TypeError, "ViscousLayers2D are supported by 2D algorithms only"
         if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
-        if ignoreEdges and isinstance( ignoreEdges[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            ignoreEdges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in ignoreEdges ]
+        if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
+            edgeIDs = []
+            for shape in edges:
+                ee = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["EDGE"])
+                for e in ee:
+                    edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e ))
+            edges = edgeIDs
         hyp = self.Hypothesis("ViscousLayers2D",
-                              [thickness, numberOfLayers, stretchFactor, ignoreEdges])
+                              [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
+                              toAdd=False)
         hyp.SetTotalThickness(thickness)
         hyp.SetNumberLayers(numberOfLayers)
         hyp.SetStretchFactor(stretchFactor)
-        hyp.SetIgnoreEdges(ignoreEdges)
+        hyp.SetEdges(edges, isEdgesToIgnore)
+        self.mesh.AddHypothesis( hyp, self.geom )
         return hyp
 
-    ## Transform a list of ether edges or tuples (edge, 1st_vertex_of_edge)
+    ## Transform a list of either edges or tuples (edge, 1st_vertex_of_edge)
     #  into a list acceptable to SetReversedEdges() of some 1D hypotheses
     #  @ingroup l3_hypos_1dhyps
     def ReversedEdgeIndices(self, reverseList):
@@ -336,7 +370,7 @@ class Mesh_Algorithm:
                 if e.GetShapeType() != geomBuilder.GEOM.EDGE or \
                    v.GetShapeType() != geomBuilder.GEOM.VERTEX:
                     raise TypeError, "A list item must be a tuple (edge, 1st_vertex_of_edge)"
-                vFirst = FirstVertexOnCurve( e )
+                vFirst = FirstVertexOnCurve( self.mesh, e )
                 tol    = geompy.Tolerance( vFirst )[-1]
                 if geompy.MinDistance( v, vFirst ) > 1.5*tol:
                     resList.append( geompy.GetSubShapeID(self.mesh.geom, e ))