1 # Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 # See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 # Author : Francis KLOSS, OCC
43 smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH")
44 smesh.SetCurrentStudy(salome.myStudy)
52 ior = salome.orb.object_to_string(obj)
53 sobj = salome.myStudy.FindObjectIOR(ior)
57 attr = sobj.FindAttribute("AttributeName")[1]
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]
66 # Algorithms and hypothesis
67 # =========================
69 # Private class: Mesh_Algorithm
70 # -----------------------------
74 Mother class to define algorithm, recommended to don't use directly
84 If the algorithm is global, return 0
85 else return the submesh associated to this algorithm
89 def GetAlgorithm(self):
91 Return the wrapped mesher
95 def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
97 Private method. Print error message if a hypothesis was not assigned
100 hypType = "algorithm"
102 hypType = "hypothesis"
103 if status == SMESH.HYP_UNKNOWN_FATAL :
104 reason = "for unknown reason"
105 elif status == SMESH.HYP_INCOMPATIBLE :
106 reason = "this hypothesis mismatches algorithm"
107 elif status == SMESH.HYP_NOTCONFORM :
108 reason = "not conform mesh would be built"
109 elif status == SMESH.HYP_ALREADY_EXIST :
110 reason = hypType + " of the same dimension already assigned to this shape"
111 elif status == SMESH.HYP_BAD_DIM :
112 reason = hypType + " mismatches shape"
113 elif status == SMESH.HYP_CONCURENT :
114 reason = "there are concurrent hypotheses on sub-shapes"
115 elif status == SMESH.HYP_BAD_SUBSHAPE :
116 reason = "shape is neither the main one, nor its subshape, nor a valid group"
119 hypName = '"' + hypName + '"'
120 geomName= '"' + geomName+ '"'
121 if status < SMESH.HYP_UNKNOWN_FATAL:
122 print hypName, "was assigned to", geomName,"but", reason
124 print hypName, "was not assigned to",geomName,":", reason
127 def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
132 raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
137 name = GetName(piece)
142 name = geompy.SubShapeName(geom, piece)
143 geompy.addToStudyInFather(piece, geom, name)
144 self.subm = mesh.mesh.GetSubMesh(geom, hypo)
146 self.algo = smesh.CreateHypothesis(hypo, so)
147 SetName(self.algo, name + "/" + hypo)
148 status = mesh.mesh.AddHypothesis(self.geom, self.algo)
149 self.TreatHypoStatus( status, hypo, name, 1 )
151 def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
155 hypo = smesh.CreateHypothesis(hyp, so)
161 a = a + s + str(args[i])
164 name = GetName(self.geom)
165 SetName(hypo, name + "/" + hyp + a)
166 status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
167 self.TreatHypoStatus( status, hyp, name, 0 )
170 # Public class: Mesh_Segment
171 # --------------------------
173 class Mesh_Segment(Mesh_Algorithm):
175 Class to define a segment 1D algorithm for discretization
178 def __init__(self, mesh, geom=0):
182 self.Create(mesh, geom, "Regular_1D")
184 def LocalLength(self, l):
186 Define "LocalLength" hypothesis to cut an edge in several segments with the same length
187 \param l for the length of segments that cut an edge
189 hyp = self.Hypothesis("LocalLength", [l])
193 def NumberOfSegments(self, n, s=[]):
195 Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
196 \param n for the number of segments that cut an edge
197 \param s for the scale factor (optional)
200 hyp = self.Hypothesis("NumberOfSegments", [n])
202 hyp = self.Hypothesis("NumberOfSegments", [n,s])
203 hyp.SetDistrType( 1 )
204 hyp.SetScaleFactor(s)
205 hyp.SetNumberOfSegments(n)
208 def Arithmetic1D(self, start, end):
210 Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
211 \param start for the length of the first segment
212 \param end for the length of the last segment
214 hyp = self.Hypothesis("Arithmetic1D", [start, end])
215 hyp.SetLength(start, 1)
216 hyp.SetLength(end , 0)
219 def StartEndLength(self, start, end):
221 Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
222 \param start for the length of the first segment
223 \param end for the length of the last segment
225 hyp = self.Hypothesis("StartEndLength", [start, end])
226 hyp.SetLength(start, 1)
227 hyp.SetLength(end , 0)
230 def Deflection1D(self, d):
232 Define "Deflection1D" hypothesis
233 \param d for the deflection
235 hyp = self.Hypothesis("Deflection1D", [d])
239 def Propagation(self):
241 Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
242 the opposite side in the case of quadrangular faces
244 return self.Hypothesis("Propagation")
246 def AutomaticLength(self, fineness=0):
248 Define "AutomaticLength" hypothesis
249 \param fineness for the fineness [0-1]
251 hyp = self.Hypothesis("AutomaticLength")
252 hyp.SetFineness( fineness )
255 def QuadraticMesh(self):
257 Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
258 If the 2D mesher sees that all boundary edges are quadratic ones,
259 it generates quadratic faces, else it generates linear faces using
260 medium nodes as if they were vertex ones.
261 The 3D mesher generates quadratic volumes only if all boundary faces
262 are quadratic ones, else it fails.
264 hyp = self.Hypothesis("QuadraticMesh")
267 # Public class: Mesh_Segment_Python
268 # ---------------------------------
270 class Mesh_Segment_Python(Mesh_Segment):
272 Class to define a segment 1D algorithm for discretization with python function
275 def __init__(self, mesh, geom=0):
279 import Python1dPlugin
280 self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
282 def PythonSplit1D(self, n, func):
284 Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
285 \param n for the number of segments that cut an edge
286 \param func for the python function that calculate the length of all segments
288 hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
289 hyp.SetNumberOfSegments(n)
290 hyp.SetPythonLog10RatioFunction(func)
293 # Public class: Mesh_Triangle
294 # ---------------------------
296 class Mesh_Triangle(Mesh_Algorithm):
298 Class to define a triangle 2D algorithm
301 def __init__(self, mesh, geom=0):
305 self.Create(mesh, geom, "MEFISTO_2D")
307 def MaxElementArea(self, area):
309 Define "MaxElementArea" hypothesis to give the maximun area of each triangles
310 \param area for the maximum area of each triangles
312 hyp = self.Hypothesis("MaxElementArea", [area])
313 hyp.SetMaxElementArea(area)
316 def LengthFromEdges(self):
318 Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
320 return self.Hypothesis("LengthFromEdges")
322 # Public class: Mesh_Quadrangle
323 # -----------------------------
325 class Mesh_Quadrangle(Mesh_Algorithm):
327 Class to define a quadrangle 2D algorithm
330 def __init__(self, mesh, geom=0):
334 self.Create(mesh, geom, "Quadrangle_2D")
336 def QuadranglePreference(self):
338 Define "QuadranglePreference" hypothesis, forcing construction
339 of quadrangles if the number of nodes on opposite edges is not the same
340 in the case where the global number of nodes on edges is even
342 hyp = self.Hypothesis("QuadranglePreference")
345 # Public class: Mesh_Tetrahedron
346 # ------------------------------
348 class Mesh_Tetrahedron(Mesh_Algorithm):
350 Class to define a tetrahedron 3D algorithm
353 def __init__(self, mesh, algo, geom=0):
358 self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
361 self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
363 def MaxElementVolume(self, vol):
365 Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
366 \param vol for the maximum volume of each tetrahedral
368 hyp = self.Hypothesis("MaxElementVolume", [vol])
369 hyp.SetMaxElementVolume(vol)
372 # Public class: Mesh_Hexahedron
373 # ------------------------------
375 class Mesh_Hexahedron(Mesh_Algorithm):
377 Class to define a hexahedron 3D algorithm
380 def __init__(self, mesh, geom=0):
384 self.Create(mesh, geom, "Hexa_3D")
391 Class to define a mesh
397 def __init__(self, geom, name=0):
401 Creates mesh on the shape \a geom,
402 sets GUI name of this mesh to \a name.
403 \param geom Shape to be meshed
404 \param name Study name of the mesh
407 self.mesh = smesh.CreateMesh(geom)
409 SetName(self.mesh, GetName(geom))
411 SetName(self.mesh, name)
415 Method that returns the mesh
421 Method that returns the shape associated to the mesh
425 def MeshDimension(self):
427 Returns mesh dimension depending on shape one
429 shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
430 if len( shells ) > 0 :
432 elif geompy.NumberOfFaces( self.geom ) > 0 :
434 elif geompy.NumberOfEdges( self.geom ) > 0 :
440 def Segment(self, algo=REGULAR, geom=0):
442 Creates a segment discretization 1D algorithm.
443 If the optional \a algo parameter is not sets, this algorithm is REGULAR.
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 algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
447 \param geom If defined, subshape to be meshed
449 ## if Segment(geom) is called by mistake
450 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
451 algo, geom = geom, algo
454 return Mesh_Segment(self, geom)
456 return Mesh_Segment_Python(self, geom)
458 return Mesh_Segment(self, geom)
460 def Triangle(self, geom=0):
462 Creates a triangle 2D algorithm for faces.
463 If the optional \a geom parameter is not sets, this algorithm is global.
464 Otherwise, this algorithm define a submesh based on \a geom subshape.
465 \param geom If defined, subshape to be meshed
467 return Mesh_Triangle(self, geom)
469 def Quadrangle(self, geom=0):
471 Creates a quadrangle 2D algorithm for faces.
472 If the optional \a geom parameter is not sets, this algorithm is global.
473 Otherwise, this algorithm define a submesh based on \a geom subshape.
474 \param geom If defined, subshape to be meshed
476 return Mesh_Quadrangle(self, geom)
478 def Tetrahedron(self, algo, geom=0):
480 Creates a tetrahedron 3D algorithm for solids.
481 The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
482 If the optional \a geom parameter is not sets, this algorithm is global.
483 Otherwise, this algorithm define a submesh based on \a geom subshape.
484 \param algo values are: smesh.NETGEN, smesh.GHS3D
485 \param geom If defined, subshape to be meshed
487 ## if Tetrahedron(geom) is called by mistake
488 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
489 algo, geom = geom, algo
491 return Mesh_Tetrahedron(self, algo, geom)
493 def Hexahedron(self, geom=0):
495 Creates a hexahedron 3D algorithm for solids.
496 If the optional \a geom parameter is not sets, this algorithm is global.
497 Otherwise, this algorithm define a submesh based on \a geom subshape.
498 \param geom If defined, subshape to be meshed
500 return Mesh_Hexahedron(self, geom)
504 Compute the mesh and return the status of the computation
506 ok = smesh.Compute(self.mesh, self.geom)
508 errors = smesh.GetAlgoState( self.mesh, self.geom )
516 dim = str(err.algoDim)
517 if err.name == SMESH.MISSING_ALGO:
518 reason = glob + dim + "D algorithm is missing"
519 elif err.name == SMESH.MISSING_HYPO:
520 name = '"' + err.algoName + '"'
521 reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
523 reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
531 print '"' + GetName(self.mesh) + '"',"not computed:"
535 if salome.sg.hasDesktop():
536 smeshgui = salome.ImportComponentGUI("SMESH")
537 smeshgui.Init(salome.myStudyId)
538 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
539 salome.sg.updateObjBrowser(1)
543 def AutomaticTetrahedralization(self, fineness=0):
545 Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
546 The parameter \a fineness [0.-1.] defines mesh fineness
548 dim = self.MeshDimension()
550 self.RemoveGlobalHypotheses()
551 self.Segment().AutomaticLength(fineness)
553 self.Triangle().LengthFromEdges()
556 self.Tetrahedron(NETGEN)
558 return self.Compute()
560 def AutomaticHexahedralization(self, fineness=0):
562 Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
563 The parameter \a fineness [0.-1.] defines mesh fineness
565 dim = self.MeshDimension()
567 self.RemoveGlobalHypotheses()
568 self.Segment().AutomaticLength(fineness)
575 return self.Compute()
577 def RemoveGlobalHypotheses(self):
579 Removes all global hypotheses
581 current_hyps = self.mesh.GetHypothesisList( self.geom )
582 for hyp in current_hyps:
583 self.mesh.RemoveHypothesis( self.geom, hyp )
587 def Group(self, grp, name=""):
589 Create a mesh group based on geometric object \a grp
590 and give a \a name, if this parameter is not defined
591 the name is the same as the geometric group name
592 \param grp is a geometric group, a vertex, an edge, a face or a solid
593 \param name is the name of the mesh group
599 tgeo = str(grp.GetShapeType())
606 elif tgeo == "SOLID":
608 elif tgeo == "SHELL":
610 elif tgeo == "COMPOUND":
611 if len( geompy.GetObjectIDs( grp )) == 0:
612 print "Mesh.Group: empty geometric group", GetName( grp )
614 tgeo = geompy.GetType(grp)
615 if tgeo == geompy.ShapeType["VERTEX"]:
617 elif tgeo == geompy.ShapeType["EDGE"]:
619 elif tgeo == geompy.ShapeType["FACE"]:
621 elif tgeo == geompy.ShapeType["SOLID"]:
625 print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
628 return self.mesh.CreateGroupFromGEOM(type, name, grp)
630 def ExportToMED(self, f, version, opt=0):
632 Export the mesh in a file with the MED format and choice the \a version of MED format
633 \param f is the file name
634 \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
636 self.mesh.ExportToMED(f, opt, version)
638 def ExportMED(self, f, opt=0):
640 Export the mesh in a file with the MED format
641 \param f is the file name
643 self.mesh.ExportMED(f, opt)
645 def ExportDAT(self, f):
647 Export the mesh in a file with the DAT format
648 \param f is the file name
650 self.mesh.ExportDAT(f)
652 def ExportUNV(self, f):
654 Export the mesh in a file with the UNV format
655 \param f is the file name
657 self.mesh.ExportUNV(f)
659 def ExportSTL(self, f, ascii=1):
661 Export the mesh in a file with the STL format
662 \param f is the file name
663 \param ascii defined the kind of file contents
665 self.mesh.ExportSTL(f, ascii)