Salome HOME
PAL10467. Add "Quadrangle Preference" hypothesis for "Quadrangle(Mapping)" algo
[modules/smesh.git] / src / SMESH_SWIG / smesh.py
1 #  Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 #
4 #  This library is free software; you can redistribute it and/or
5 #  modify it under the terms of the GNU Lesser General Public
6 #  License as published by the Free Software Foundation; either
7 #  version 2.1 of the License.
8 #
9 #  This library is distributed in the hope that it will be useful,
10 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 #  Lesser General Public License for more details.
13 #
14 #  You should have received a copy of the GNU Lesser General Public
15 #  License along with this library; if not, write to the Free Software
16 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 #  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19 #
20 #  File   : smesh.py
21 #  Author : Francis KLOSS, OCC
22 #  Module : SMESH
23
24 """
25  \namespace smesh
26  \brief Module smesh
27 """
28
29 import salome
30 import geompy
31 import StdMeshers
32 import SMESH
33
34 # Public variables
35 # ----------------
36
37 REGULAR = 1
38 PYTHON  = 2
39
40 NETGEN  = 3
41 GHS3D   = 4
42
43 smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH")
44 smesh.SetCurrentStudy(salome.myStudy)
45
46 # Private functions
47 # -----------------
48
49 NO_NAME = "NoName"
50
51 def GetName(obj):
52     ior  = salome.orb.object_to_string(obj)
53     sobj = salome.myStudy.FindObjectIOR(ior)
54     if sobj is None:
55         return NO_NAME
56     else:
57         attr = sobj.FindAttribute("AttributeName")[1]
58         return attr.Value()
59
60 def SetName(obj, name):
61     ior  = salome.orb.object_to_string(obj)
62     sobj = salome.myStudy.FindObjectIOR(ior)
63     attr = sobj.FindAttribute("AttributeName")[1]
64     attr.SetValue(name)
65
66 # Algorithms and hypothesis
67 # =========================
68
69 # Private class: Mesh_Algorithm
70 # -----------------------------
71
72 class Mesh_Algorithm:
73     """
74     Mother class to define algorithm, recommended to don't use directly
75     """
76
77     mesh = 0
78     geom = 0
79     subm = 0
80     algo = 0
81
82     def GetSubMesh(self):
83         """
84          If the algorithm is global, return 0
85          else return the submesh associated to this algorithm
86         """
87         return self.subm
88
89     def GetAlgorithm(self):
90         """
91          Return the wrapped mesher
92         """
93         return self.algo
94
95     def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
96         """
97          Private method
98         """
99         self.mesh = mesh
100         piece = mesh.geom
101         if geom==0:
102             self.geom = piece
103             name = GetName(piece)
104         else:
105             self.geom = geom
106             name = GetName(geom)
107             if name==NO_NAME:
108                 name = geompy.SubShapeName(geom, piece)
109                 geompy.addToStudyInFather(piece, geom, name)
110             self.subm = mesh.mesh.GetSubMesh(geom, hypo)
111
112         self.algo = smesh.CreateHypothesis(hypo, so)
113         SetName(self.algo, name + "/" + hypo)
114         mesh.mesh.AddHypothesis(self.geom, self.algo)
115
116     def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
117         """
118          Private method
119         """
120         hypo = smesh.CreateHypothesis(hyp, so)
121         a = ""
122         s = "="
123         i = 0
124         n = len(args)
125         while i<n:
126             a = a + s + str(args[i])
127             s = ","
128             i = i + 1
129         SetName(hypo, GetName(self.geom) + "/" + hyp + a)
130         self.mesh.mesh.AddHypothesis(self.geom, hypo)
131         return hypo
132
133 # Public class: Mesh_Segment
134 # --------------------------
135
136 class Mesh_Segment(Mesh_Algorithm):
137     """
138     Class to define a segment 1D algorithm for discretization
139     """
140
141     def __init__(self, mesh, geom=0):
142         """
143          Private constructor
144         """
145         self.Create(mesh, geom, "Regular_1D")
146
147     def LocalLength(self, l):
148         """
149          Define "LocalLength" hypothesis to cut an edge in several segments with the same length
150          \param l for the length of segments that cut an edge
151         """
152         hyp = self.Hypothesis("LocalLength", [l])
153         hyp.SetLength(l)
154         return hyp
155
156     def NumberOfSegments(self, n, s=[]):
157         """
158          Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
159          \param n for the number of segments that cut an edge
160          \param s for the scale factor (optional)
161         """
162         if s == []:
163             hyp = self.Hypothesis("NumberOfSegments", [n])
164         else:
165             hyp = self.Hypothesis("NumberOfSegments", [n,s])
166             hyp.SetDistrType( 1 )
167             hyp.SetScaleFactor(s)
168         hyp.SetNumberOfSegments(n)
169         return hyp
170
171     def Arithmetic1D(self, start, end):
172         """
173          Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
174          \param start for the length of the first segment
175          \param end   for the length of the last  segment
176         """
177         hyp = self.Hypothesis("Arithmetic1D", [start, end])
178         hyp.SetLength(start, 1)
179         hyp.SetLength(end  , 0)
180         return hyp
181
182     def StartEndLength(self, start, end):
183         """
184          Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
185          \param start for the length of the first segment
186          \param end   for the length of the last  segment
187         """
188         hyp = self.Hypothesis("StartEndLength", [start, end])
189         hyp.SetLength(start, 1)
190         hyp.SetLength(end  , 0)
191         return hyp
192
193     def Deflection1D(self, d):
194         """
195          Define "Deflection1D" hypothesis
196          \param d for the deflection
197         """
198         hyp = self.Hypothesis("Deflection1D", [d])
199         hyp.SetDeflection(d)
200         return hyp
201
202     def Propagation(self):
203         """
204          Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
205          the opposite side in the case of quadrangular faces
206         """
207         return self.Hypothesis("Propagation")
208
209     def AutomaticLength(self):
210         """
211          Define "AutomaticLength" hypothesis
212         """
213         return self.Hypothesis("AutomaticLength")
214
215 # Public class: Mesh_Segment_Python
216 # ---------------------------------
217
218 class Mesh_Segment_Python(Mesh_Segment):
219     """
220     Class to define a segment 1D algorithm for discretization with python function
221     """
222
223     def __init__(self, mesh, geom=0):
224         """
225          Private constructor
226         """
227         import Python1dPlugin
228         self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
229
230     def PythonSplit1D(self, n, func):
231         """
232          Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
233          \param n for the number of segments that cut an edge
234          \param func for the python function that calculate the length of all segments
235         """
236         hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
237         hyp.SetNumberOfSegments(n)
238         hyp.SetPythonLog10RatioFunction(func)
239         return hyp
240
241 # Public class: Mesh_Triangle
242 # ---------------------------
243
244 class Mesh_Triangle(Mesh_Algorithm):
245     """
246     Class to define a triangle 2D algorithm
247     """
248
249     def __init__(self, mesh, geom=0):
250         """
251          Private constructor
252         """
253         self.Create(mesh, geom, "MEFISTO_2D")
254
255     def MaxElementArea(self, area):
256         """
257          Define "MaxElementArea" hypothesis to give the maximun area of each triangles
258          \param area for the maximum area of each triangles
259         """
260         hyp = self.Hypothesis("MaxElementArea", [area])
261         hyp.SetMaxElementArea(area)
262         return hyp
263
264     def LengthFromEdges(self):
265         """
266          Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
267         """
268         return self.Hypothesis("LengthFromEdges")
269
270 # Public class: Mesh_Quadrangle
271 # -----------------------------
272
273 class Mesh_Quadrangle(Mesh_Algorithm):
274     """
275     Class to define a quadrangle 2D algorithm
276     """
277
278     def __init__(self, mesh, geom=0):
279         """
280          Private constructor
281         """
282         self.Create(mesh, geom, "Quadrangle_2D")
283
284     def QuadranglePreference(self):
285         """
286          Define "QuadranglePreference" hypothesis, forcing construction
287          of quadrangles if the number of nodes on opposite edges is not the same
288          in the case where the global number of nodes on edges is even
289         """
290         hyp = self.Hypothesis("QuadranglePreference")
291         return hyp
292
293 # Public class: Mesh_Tetrahedron
294 # ------------------------------
295
296 class Mesh_Tetrahedron(Mesh_Algorithm):
297     """
298     Class to define a tetrahedron 3D algorithm
299     """
300
301     def __init__(self, mesh, algo, geom=0):
302         """
303          Private constructor
304         """
305         if algo == NETGEN:
306             self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
307         elif algo == GHS3D:
308             import GHS3DPlugin
309             self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
310
311     def MaxElementVolume(self, vol):
312         """
313          Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
314          \param vol for the maximum volume of each tetrahedral
315         """
316         hyp = self.Hypothesis("MaxElementVolume", [vol])
317         hyp.SetMaxElementVolume(vol)
318         return hyp
319
320 # Public class: Mesh_Hexahedron
321 # ------------------------------
322
323 class Mesh_Hexahedron(Mesh_Algorithm):
324     """
325     Class to define a hexahedron 3D algorithm
326     """
327
328     def __init__(self, mesh, geom=0):
329         """
330          Private constructor
331         """
332         self.Create(mesh, geom, "Hexa_3D")
333
334 # Public class: Mesh
335 # ==================
336
337 class Mesh:
338     """
339     Class to define a mesh
340     """
341
342     geom = 0
343     mesh = 0
344
345     def __init__(self, geom, name=0):
346         """
347          Constructor
348
349          Creates mesh on the shape \a geom,
350          sets GUI name of this mesh to \a name.
351          \param geom Shape to be meshed
352          \param name Study name of the mesh
353         """
354         self.geom = geom
355         self.mesh = smesh.CreateMesh(geom)
356         if name == 0:
357             SetName(self.mesh, GetName(geom))
358         else:
359             SetName(self.mesh, name)
360
361     def GetMesh(self):
362         """
363          Method that returns the mesh
364         """
365         return self.mesh
366
367     def GetShape(self):
368         """
369          Method that returns the shape associated to the mesh
370         """
371         return self.geom
372
373     def MeshDimension(self):
374         """
375         Returns mesh dimension depending on shape one
376         """
377         shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
378         if len( shells ) > 0 :
379             return 3
380         elif geompy.NumberOfFaces( self.geom ) > 0 :
381             return 2
382         elif geompy.NumberOfEdges( self.geom ) > 0 :
383             return 1
384         else:
385             return 0;
386         pass
387
388     def Segment(self, algo=REGULAR, geom=0):
389         """
390          Creates a segment discretization 1D algorithm.
391          If the optional \a algo parameter is not sets, this algorithm is REGULAR.
392          If the optional \a geom parameter is not sets, this algorithm is global.
393          Otherwise, this algorithm define a submesh based on \a geom subshape.
394          \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
395          \param geom If defined, subshape to be meshed
396         """
397         ## if Segment(geom) is called by mistake
398         if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
399             algo, geom = geom, algo
400             pass
401         if algo == REGULAR:
402             return Mesh_Segment(self, geom)
403         elif algo == PYTHON:
404             return Mesh_Segment_Python(self, geom)
405         else:
406             return Mesh_Segment(self, geom)
407
408     def Triangle(self, geom=0):
409         """
410          Creates a triangle 2D algorithm for faces.
411          If the optional \a geom parameter is not sets, this algorithm is global.
412          Otherwise, this algorithm define a submesh based on \a geom subshape.
413          \param geom If defined, subshape to be meshed
414         """
415         return Mesh_Triangle(self, geom)
416
417     def Quadrangle(self, geom=0):
418         """
419          Creates a quadrangle 2D algorithm for faces.
420          If the optional \a geom parameter is not sets, this algorithm is global.
421          Otherwise, this algorithm define a submesh based on \a geom subshape.
422          \param geom If defined, subshape to be meshed
423         """
424         return Mesh_Quadrangle(self, geom)
425
426     def Tetrahedron(self, algo, geom=0):
427         """
428          Creates a tetrahedron 3D algorithm for solids.
429          The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
430          If the optional \a geom parameter is not sets, this algorithm is global.
431          Otherwise, this algorithm define a submesh based on \a geom subshape.
432          \param algo values are: smesh.NETGEN, smesh.GHS3D
433          \param geom If defined, subshape to be meshed
434         """
435         ## if Tetrahedron(geom) is called by mistake
436         if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
437             algo, geom = geom, algo
438             pass
439         return Mesh_Tetrahedron(self, algo, geom)
440
441     def Hexahedron(self, geom=0):
442         """
443          Creates a hexahedron 3D algorithm for solids.
444          If the optional \a geom parameter is not sets, this algorithm is global.
445          Otherwise, this algorithm define a submesh based on \a geom subshape.
446          \param geom If defined, subshape to be meshed
447         """
448         return Mesh_Hexahedron(self, geom)
449
450     def Compute(self):
451         """
452          Compute the mesh and return the status of the computation
453         """
454         b = smesh.Compute(self.mesh, self.geom)
455         if salome.sg.hasDesktop():
456             smeshgui = salome.ImportComponentGUI("SMESH")
457             smeshgui.Init(salome.myStudyId)
458             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), b )
459             salome.sg.updateObjBrowser(1)
460         return b
461
462     def AutomaticTetrahedralization(self):
463         """
464         Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
465         """
466         dim = self.MeshDimension()
467         # assign hypotheses
468         self.RemoveGlobalHypotheses()
469         self.Segment().AutomaticLength()
470         if dim > 1 :
471             self.Triangle().LengthFromEdges()
472             pass
473         if dim > 2 :
474             self.Tetrahedron(NETGEN)
475             pass
476         return self.Compute()
477
478     def AutomaticHexahedralization(self):
479         """
480         Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
481         """
482         dim = self.MeshDimension()
483         # assign hypotheses
484         self.RemoveGlobalHypotheses()
485         self.Segment().AutomaticLength()
486         if dim > 1 :
487             self.Quadrangle()
488             pass
489         if dim > 2 :
490             self.Hexahedron()            
491             pass
492         return self.Compute()
493
494     def RemoveGlobalHypotheses(self):
495         """
496         Removes all global hypotheses
497         """
498         current_hyps = self.mesh.GetHypothesisList( self.geom )
499         for hyp in current_hyps:
500             self.mesh.RemoveHypothesis( self.geom, hyp )
501             pass
502         pass
503
504     def Group(self, grp, name=""):
505         """
506          Create a mesh group based on geometric object \a grp
507          and give a \a name, if this parameter is not defined
508          the name is the same as the geometric group name
509          \param grp  is a geometric group, a vertex, an edge, a face or a solid
510          \param name is the name of the mesh group
511         """
512         if name == "":
513             name = grp.GetName()
514
515         type = []
516         tgeo = str(grp.GetShapeType())
517         if tgeo == "VERTEX":
518             type = SMESH.NODE
519         elif tgeo == "EDGE":
520             type = SMESH.EDGE
521         elif tgeo == "FACE":
522             type = SMESH.FACE
523         elif tgeo == "SOLID":
524             type = SMESH.VOLUME
525         elif tgeo == "SHELL":
526             type = SMESH.VOLUME
527         elif tgeo == "COMPOUND":
528             tgeo = geompy.GetType(grp)
529             if tgeo == geompy.ShapeType["VERTEX"]:
530                 type = SMESH.NODE
531             elif tgeo == geompy.ShapeType["EDGE"]:
532                 type = SMESH.EDGE
533             elif tgeo == geompy.ShapeType["FACE"]:
534                 type = SMESH.FACE
535             elif tgeo == geompy.ShapeType["SOLID"]:
536                 type = SMESH.VOLUME
537
538         if type == []:
539             print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
540             return 0
541         else:
542             return self.mesh.CreateGroupFromGEOM(type, name, grp)
543
544     def ExportToMED(self, f, version, opt=0):
545         """
546          Export the mesh in a file with the MED format and choice the \a version of MED format
547          \param f is the file name
548          \param version values are smesh.MED_V2_1, smesh.MED_V2_2
549         """
550         self.mesh.ExportToMED(f, opt, version)
551
552     def ExportMED(self, f, opt=0):
553         """
554          Export the mesh in a file with the MED format
555          \param f is the file name
556         """
557         self.mesh.ExportMED(f, opt)
558
559     def ExportDAT(self, f):
560         """
561          Export the mesh in a file with the DAT format
562          \param f is the file name
563         """
564         self.mesh.ExportDAT(f)
565
566     def ExportUNV(self, f):
567         """
568          Export the mesh in a file with the UNV format
569          \param f is the file name
570         """
571         self.mesh.ExportUNV(f)
572
573     def ExportSTL(self, f, ascii=1):
574         """
575          Export the mesh in a file with the STL format
576          \param f is the file name
577          \param ascii defined the kind of file contents
578         """
579         self.mesh.ExportSTL(f, ascii)