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
41 smesh = salome.lcc.FindOrLoadComponent("FactoryServer", "SMESH")
42 smesh.SetCurrentStudy(salome.myStudy)
48 ior = salome.orb.object_to_string(obj)
49 sobj = salome.myStudy.FindObjectIOR(ior)
53 attr = sobj.FindAttribute("AttributeName")[1]
56 def SetName(obj, name):
57 ior = salome.orb.object_to_string(obj)
58 sobj = salome.myStudy.FindObjectIOR(ior)
60 attr = sobj.FindAttribute("AttributeName")[1]
63 ## Mother class to define algorithm, recommended to don't use directly.
67 # @class Mesh_Algorithm
68 # @brief Class Mesh_Algorithm
75 ## If the algorithm is global, return 0
76 # \fn else return the submesh associated to this algorithm.
82 ## Return the wrapped mesher.
83 def GetAlgorithm(self):
86 ## Private method. Print error message if a hypothesis was not assigned.
87 def TreatHypoStatus(self, status, hypName, geomName, isAlgo):
91 hypType = "hypothesis"
92 if status == SMESH.HYP_UNKNOWN_FATAL :
93 reason = "for unknown reason"
94 elif status == SMESH.HYP_INCOMPATIBLE :
95 reason = "this hypothesis mismatches algorithm"
96 elif status == SMESH.HYP_NOTCONFORM :
97 reason = "not conform mesh would be built"
98 elif status == SMESH.HYP_ALREADY_EXIST :
99 reason = hypType + " of the same dimension already assigned to this shape"
100 elif status == SMESH.HYP_BAD_DIM :
101 reason = hypType + " mismatches shape"
102 elif status == SMESH.HYP_CONCURENT :
103 reason = "there are concurrent hypotheses on sub-shapes"
104 elif status == SMESH.HYP_BAD_SUBSHAPE :
105 reason = "shape is neither the main one, nor its subshape, nor a valid group"
108 hypName = '"' + hypName + '"'
109 geomName= '"' + geomName+ '"'
110 if status < SMESH.HYP_UNKNOWN_FATAL:
111 print hypName, "was assigned to", geomName,"but", reason
113 print hypName, "was not assigned to",geomName,":", reason
117 def Create(self, mesh, geom, hypo, so="libStdMeshersEngine.so"):
119 raise RuntimeError, "Attemp to create " + hypo + " algoritm on None shape"
124 name = GetName(piece)
129 name = geompy.SubShapeName(geom, piece)
130 geompy.addToStudyInFather(piece, geom, name)
131 self.subm = mesh.mesh.GetSubMesh(geom, hypo)
133 self.algo = smesh.CreateHypothesis(hypo, so)
134 SetName(self.algo, name + "/" + hypo)
135 status = mesh.mesh.AddHypothesis(self.geom, self.algo)
136 self.TreatHypoStatus( status, hypo, name, 1 )
139 def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
140 hypo = smesh.CreateHypothesis(hyp, so)
146 a = a + s + str(args[i])
149 name = GetName(self.geom)
150 SetName(hypo, name + "/" + hyp + a)
151 status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
152 self.TreatHypoStatus( status, hyp, name, 0 )
155 # Public class: Mesh_Segment
156 # --------------------------
158 ## Class to define a segment 1D algorithm for discretization
161 class Mesh_Segment(Mesh_Algorithm):
163 ## Private constructor.
164 def __init__(self, mesh, geom=0):
165 self.Create(mesh, geom, "Regular_1D")
167 ## Define "LocalLength" hypothesis to cut an edge in several segments with the same length
168 # @param l for the length of segments that cut an edge
169 def LocalLength(self, l):
170 hyp = self.Hypothesis("LocalLength", [l])
174 ## Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
175 # @param n for the number of segments that cut an edge
176 # @param s for the scale factor (optional)
177 def NumberOfSegments(self, n, s=[]):
179 hyp = self.Hypothesis("NumberOfSegments", [n])
181 hyp = self.Hypothesis("NumberOfSegments", [n,s])
182 hyp.SetDistrType( 1 )
183 hyp.SetScaleFactor(s)
184 hyp.SetNumberOfSegments(n)
187 ## Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
188 # @param start for the length of the first segment
189 # @param end for the length of the last segment
190 def Arithmetic1D(self, start, end):
191 hyp = self.Hypothesis("Arithmetic1D", [start, end])
192 hyp.SetLength(start, 1)
193 hyp.SetLength(end , 0)
196 ## Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
197 # @param start for the length of the first segment
198 # @param end for the length of the last segment
199 def StartEndLength(self, start, end):
200 hyp = self.Hypothesis("StartEndLength", [start, end])
201 hyp.SetLength(start, 1)
202 hyp.SetLength(end , 0)
205 ## Define "Deflection1D" hypothesis
206 # @param d for the deflection
207 def Deflection1D(self, d):
208 hyp = self.Hypothesis("Deflection1D", [d])
212 ## Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
213 # the opposite side in the case of quadrangular faces
214 def Propagation(self):
215 return self.Hypothesis("Propagation")
217 ## Define "AutomaticLength" hypothesis
218 # @param fineness for the fineness [0-1]
219 def AutomaticLength(self, fineness=0):
220 hyp = self.Hypothesis("AutomaticLength")
221 hyp.SetFineness( fineness )
224 ## Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
225 # If the 2D mesher sees that all boundary edges are quadratic ones,
226 # it generates quadratic faces, else it generates linear faces using
227 # medium nodes as if they were vertex ones.
228 # The 3D mesher generates quadratic volumes only if all boundary faces
229 # are quadratic ones, else it fails.
230 def QuadraticMesh(self):
231 hyp = self.Hypothesis("QuadraticMesh")
234 # Public class: Mesh_Segment_Python
235 # ---------------------------------
237 ## Class to define a segment 1D algorithm for discretization with python function
240 class Mesh_Segment_Python(Mesh_Segment):
242 ## Private constructor.
243 def __init__(self, mesh, geom=0):
244 import Python1dPlugin
245 self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
247 ## Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
248 # @param n for the number of segments that cut an edge
249 # @param func for the python function that calculate the length of all segments
250 def PythonSplit1D(self, n, func):
251 hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
252 hyp.SetNumberOfSegments(n)
253 hyp.SetPythonLog10RatioFunction(func)
256 # Public class: Mesh_Triangle
257 # ---------------------------
259 ## Class to define a triangle 2D algorithm
262 class Mesh_Triangle(Mesh_Algorithm):
264 ## Private constructor.
265 def __init__(self, mesh, geom=0):
266 self.Create(mesh, geom, "MEFISTO_2D")
268 ## Define "MaxElementArea" hypothesis to give the maximun area of each triangles
269 # @param area for the maximum area of each triangles
270 def MaxElementArea(self, area):
271 hyp = self.Hypothesis("MaxElementArea", [area])
272 hyp.SetMaxElementArea(area)
275 ## Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
276 def LengthFromEdges(self):
277 return self.Hypothesis("LengthFromEdges")
279 # Public class: Mesh_Quadrangle
280 # -----------------------------
282 ## Class to define a quadrangle 2D algorithm
285 class Mesh_Quadrangle(Mesh_Algorithm):
287 ## Private constructor.
288 def __init__(self, mesh, geom=0):
289 self.Create(mesh, geom, "Quadrangle_2D")
291 ## Define "QuadranglePreference" hypothesis, forcing construction
292 # of quadrangles if the number of nodes on opposite edges is not the same
293 # in the case where the global number of nodes on edges is even
294 def QuadranglePreference(self):
295 hyp = self.Hypothesis("QuadranglePreference")
298 # Public class: Mesh_Tetrahedron
299 # ------------------------------
301 ## Class to define a tetrahedron 3D algorithm
304 class Mesh_Tetrahedron(Mesh_Algorithm):
306 ## Private constructor.
307 def __init__(self, mesh, algo, geom=0):
309 self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
312 self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
314 ## Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
315 # @param vol for the maximum volume of each tetrahedral
316 def MaxElementVolume(self, vol):
317 hyp = self.Hypothesis("MaxElementVolume", [vol])
318 hyp.SetMaxElementVolume(vol)
321 # Public class: Mesh_Hexahedron
322 # ------------------------------
324 ## Class to define a hexahedron 3D algorithm
327 class Mesh_Hexahedron(Mesh_Algorithm):
329 ## Private constructor.
330 def __init__(self, mesh, geom=0):
331 self.Create(mesh, geom, "Hexa_3D")
333 # Public class: Mesh_Netgen
334 # ------------------------------
336 ## Class to define a NETGEN-based 2D or 3D algorithm
337 # that need no discrete boundary (i.e. independent)
340 class Mesh_Netgen(Mesh_Algorithm):
344 ## Private constructor.
345 def __init__(self, mesh, is3D, geom=0):
348 self.Create(mesh, geom, "NETGEN_2D3D", "libNETGENEngine.so")
350 self.Create(mesh, geom, "NETGEN_2D", "libNETGENEngine.so")
352 ## Define hypothesis containing parameters of the algorithm
353 def Parameters(self):
355 hyp = self.Hypothesis("NETGEN_Parameters", [], "libNETGENEngine.so")
357 hyp = self.Hypothesis("NETGEN_Parameters_2D", [], "libNETGENEngine.so")
363 ## Class to define a mesh
373 # Creates mesh on the shape \a geom,
374 # sets GUI name of this mesh to \a name.
375 # @param geom Shape to be meshed
376 # @param name Study name of the mesh
377 def __init__(self, geom, name=0):
379 self.mesh = smesh.CreateMesh(geom)
381 SetName(self.mesh, GetName(geom))
383 SetName(self.mesh, name)
385 ## Method that returns the mesh
389 ## Method that returns the shape associated to the mesh
393 ## Returns mesh dimension depending on shape one
394 def MeshDimension(self):
395 shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
396 if len( shells ) > 0 :
398 elif geompy.NumberOfFaces( self.geom ) > 0 :
400 elif geompy.NumberOfEdges( self.geom ) > 0 :
406 ## Creates a segment discretization 1D algorithm.
407 # If the optional \a algo parameter is not sets, this algorithm is REGULAR.
408 # If the optional \a geom parameter is not sets, this algorithm is global.
409 # Otherwise, this algorithm define a submesh based on \a geom subshape.
410 # @param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
411 # @param geom If defined, subshape to be meshed
412 def Segment(self, algo=REGULAR, geom=0):
413 ## if Segment(geom) is called by mistake
414 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
415 algo, geom = geom, algo
418 return Mesh_Segment(self, geom)
420 return Mesh_Segment_Python(self, geom)
422 return Mesh_Segment(self, geom)
424 ## Creates a triangle 2D algorithm for faces.
425 # If the optional \a geom parameter is not sets, this algorithm is global.
426 # Otherwise, this algorithm define a submesh based on \a geom subshape.
427 # @param geom If defined, subshape to be meshed
428 def Triangle(self, geom=0):
429 return Mesh_Triangle(self, geom)
431 ## Creates a quadrangle 2D algorithm for faces.
432 # If the optional \a geom parameter is not sets, this algorithm is global.
433 # Otherwise, this algorithm define a submesh based on \a geom subshape.
434 # @param geom If defined, subshape to be meshed
435 def Quadrangle(self, geom=0):
436 return Mesh_Quadrangle(self, geom)
438 ## Creates a tetrahedron 3D algorithm for solids.
439 # The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
440 # If the optional \a geom parameter is not sets, this algorithm is global.
441 # Otherwise, this algorithm define a submesh based on \a geom subshape.
442 # @param algo values are: smesh.NETGEN, smesh.GHS3D
443 # @param geom If defined, subshape to be meshed
444 def Tetrahedron(self, algo, geom=0):
445 ## if Tetrahedron(geom) is called by mistake
446 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
447 algo, geom = geom, algo
449 return Mesh_Tetrahedron(self, algo, geom)
451 ## Creates a hexahedron 3D algorithm for solids.
452 # If the optional \a geom parameter is not sets, this algorithm is global.
453 # Otherwise, this algorithm define a submesh based on \a geom subshape.
454 # @param geom If defined, subshape to be meshed
455 def Hexahedron(self, geom=0):
456 return Mesh_Hexahedron(self, geom)
458 ## Creates a NETGEN-based 2D or 3D independent algorithm (i.e. needs no
459 # discrete boundary).
460 # If the optional \a geom parameter is not sets, this algorithm is global.
461 # Otherwise, this algorithm defines a submesh based on \a geom subshape.
462 # @param is3D If 0 then algorithm is 2D, otherwise 3D
463 # @param geom If defined, subshape to be meshed
464 def Netgen(self, is3D, geom=0):
465 return Mesh_Netgen(self, is3D, geom)
467 ## Compute the mesh and return the status of the computation
469 ok = smesh.Compute(self.mesh, self.geom)
471 errors = smesh.GetAlgoState( self.mesh, self.geom )
479 dim = str(err.algoDim)
480 if err.name == SMESH.MISSING_ALGO:
481 reason = glob + dim + "D algorithm is missing"
482 elif err.name == SMESH.MISSING_HYPO:
483 name = '"' + err.algoName + '"'
484 reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
486 reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
494 print '"' + GetName(self.mesh) + '"',"not computed:"
498 if salome.sg.hasDesktop():
499 smeshgui = salome.ImportComponentGUI("SMESH")
500 smeshgui.Init(salome.myStudyId)
501 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
502 salome.sg.updateObjBrowser(1)
506 ## Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
507 # The parameter \a fineness [0.-1.] defines mesh fineness
508 def AutomaticTetrahedralization(self, fineness=0):
509 dim = self.MeshDimension()
511 self.RemoveGlobalHypotheses()
512 self.Segment().AutomaticLength(fineness)
514 self.Triangle().LengthFromEdges()
517 self.Tetrahedron(NETGEN)
519 return self.Compute()
521 ## Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
522 # The parameter \a fineness [0.-1.] defines mesh fineness
523 def AutomaticHexahedralization(self, fineness=0):
524 dim = self.MeshDimension()
526 self.RemoveGlobalHypotheses()
527 self.Segment().AutomaticLength(fineness)
534 return self.Compute()
536 ## Removes all global hypotheses
537 def RemoveGlobalHypotheses(self):
538 current_hyps = self.mesh.GetHypothesisList( self.geom )
539 for hyp in current_hyps:
540 self.mesh.RemoveHypothesis( self.geom, hyp )
544 ## Create a mesh group based on geometric object \a grp
545 # and give a \a name, if this parameter is not defined
546 # the name is the same as the geometric group name
547 # @param grp is a geometric group, a vertex, an edge, a face or a solid
548 # @param name is the name of the mesh group
549 def Group(self, grp, name=""):
554 tgeo = str(grp.GetShapeType())
561 elif tgeo == "SOLID":
563 elif tgeo == "SHELL":
565 elif tgeo == "COMPOUND":
566 if len( geompy.GetObjectIDs( grp )) == 0:
567 print "Mesh.Group: empty geometric group", GetName( grp )
569 tgeo = geompy.GetType(grp)
570 if tgeo == geompy.ShapeType["VERTEX"]:
572 elif tgeo == geompy.ShapeType["EDGE"]:
574 elif tgeo == geompy.ShapeType["FACE"]:
576 elif tgeo == geompy.ShapeType["SOLID"]:
580 print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
583 return self.mesh.CreateGroupFromGEOM(type, name, grp)
585 ## Export the mesh in a file with the MED format and choice the \a version of MED format
586 # @param f is the file name
587 # @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
588 def ExportToMED(self, f, version, opt=0):
589 self.mesh.ExportToMED(f, opt, version)
591 ## Export the mesh in a file with the MED format
592 # @param f is the file name
593 def ExportMED(self, f, opt=0):
594 self.mesh.ExportMED(f, opt)
596 ## Export the mesh in a file with the DAT format
597 # @param f is the file name
598 def ExportDAT(self, f):
599 self.mesh.ExportDAT(f)
601 ## Export the mesh in a file with the UNV format
602 # @param f is the file name
603 def ExportUNV(self, f):
604 self.mesh.ExportUNV(f)
606 ## Export the mesh in a file with the STL format
607 # @param f is the file name
608 # @param ascii defined the kind of file contents
609 def ExportSTL(self, f, ascii=1):
610 self.mesh.ExportSTL(f, ascii)