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"):
135 name = GetName(piece)
140 name = geompy.SubShapeName(geom, piece)
141 geompy.addToStudyInFather(piece, geom, name)
142 self.subm = mesh.mesh.GetSubMesh(geom, hypo)
144 self.algo = smesh.CreateHypothesis(hypo, so)
145 SetName(self.algo, name + "/" + hypo)
146 status = mesh.mesh.AddHypothesis(self.geom, self.algo)
147 self.TreatHypoStatus( status, hypo, name, 1 )
149 def Hypothesis(self, hyp, args=[], so="libStdMeshersEngine.so"):
153 hypo = smesh.CreateHypothesis(hyp, so)
159 a = a + s + str(args[i])
162 name = GetName(self.geom)
163 SetName(hypo, name + "/" + hyp + a)
164 status = self.mesh.mesh.AddHypothesis(self.geom, hypo)
165 self.TreatHypoStatus( status, hyp, name, 0 )
168 # Public class: Mesh_Segment
169 # --------------------------
171 class Mesh_Segment(Mesh_Algorithm):
173 Class to define a segment 1D algorithm for discretization
176 def __init__(self, mesh, geom=0):
180 self.Create(mesh, geom, "Regular_1D")
182 def LocalLength(self, l):
184 Define "LocalLength" hypothesis to cut an edge in several segments with the same length
185 \param l for the length of segments that cut an edge
187 hyp = self.Hypothesis("LocalLength", [l])
191 def NumberOfSegments(self, n, s=[]):
193 Define "NumberOfSegments" hypothesis to cut an edge in several fixed number of segments
194 \param n for the number of segments that cut an edge
195 \param s for the scale factor (optional)
198 hyp = self.Hypothesis("NumberOfSegments", [n])
200 hyp = self.Hypothesis("NumberOfSegments", [n,s])
201 hyp.SetDistrType( 1 )
202 hyp.SetScaleFactor(s)
203 hyp.SetNumberOfSegments(n)
206 def Arithmetic1D(self, start, end):
208 Define "Arithmetic1D" hypothesis to cut an edge in several segments with arithmetic length increasing
209 \param start for the length of the first segment
210 \param end for the length of the last segment
212 hyp = self.Hypothesis("Arithmetic1D", [start, end])
213 hyp.SetLength(start, 1)
214 hyp.SetLength(end , 0)
217 def StartEndLength(self, start, end):
219 Define "StartEndLength" hypothesis to cut an edge in several segments with geometric length increasing
220 \param start for the length of the first segment
221 \param end for the length of the last segment
223 hyp = self.Hypothesis("StartEndLength", [start, end])
224 hyp.SetLength(start, 1)
225 hyp.SetLength(end , 0)
228 def Deflection1D(self, d):
230 Define "Deflection1D" hypothesis
231 \param d for the deflection
233 hyp = self.Hypothesis("Deflection1D", [d])
237 def Propagation(self):
239 Define "Propagation" hypothesis that propagate all other hypothesis on all others edges that are in
240 the opposite side in the case of quadrangular faces
242 return self.Hypothesis("Propagation")
244 def AutomaticLength(self, fineness=0):
246 Define "AutomaticLength" hypothesis
247 \param fineness for the fineness [0-1]
249 hyp = self.Hypothesis("AutomaticLength")
250 hyp.SetFineness( fineness )
253 def QuadraticMesh(self):
255 Define "QuadraticMesh" hypothesis, forcing construction of quadratic edges.
256 If the 2D mesher sees that all boundary edges are quadratic ones,
257 it generates quadratic faces, else it generates linear faces using
258 medium nodes as if they were vertex ones.
259 The 3D mesher generates quadratic volumes only if all boundary faces
260 are quadratic ones, else it fails.
262 hyp = self.Hypothesis("QuadraticMesh")
265 # Public class: Mesh_Segment_Python
266 # ---------------------------------
268 class Mesh_Segment_Python(Mesh_Segment):
270 Class to define a segment 1D algorithm for discretization with python function
273 def __init__(self, mesh, geom=0):
277 import Python1dPlugin
278 self.Create(mesh, geom, "Python_1D", "libPython1dEngine.so")
280 def PythonSplit1D(self, n, func):
282 Define "PythonSplit1D" hypothesis based on the Erwan Adam patch, awaiting equivalent SALOME functionality
283 \param n for the number of segments that cut an edge
284 \param func for the python function that calculate the length of all segments
286 hyp = self.Hypothesis("PythonSplit1D", [n], "libPython1dEngine.so")
287 hyp.SetNumberOfSegments(n)
288 hyp.SetPythonLog10RatioFunction(func)
291 # Public class: Mesh_Triangle
292 # ---------------------------
294 class Mesh_Triangle(Mesh_Algorithm):
296 Class to define a triangle 2D algorithm
299 def __init__(self, mesh, geom=0):
303 self.Create(mesh, geom, "MEFISTO_2D")
305 def MaxElementArea(self, area):
307 Define "MaxElementArea" hypothesis to give the maximun area of each triangles
308 \param area for the maximum area of each triangles
310 hyp = self.Hypothesis("MaxElementArea", [area])
311 hyp.SetMaxElementArea(area)
314 def LengthFromEdges(self):
316 Define "LengthFromEdges" hypothesis to build triangles based on the length of the edges taken from the wire
318 return self.Hypothesis("LengthFromEdges")
320 # Public class: Mesh_Quadrangle
321 # -----------------------------
323 class Mesh_Quadrangle(Mesh_Algorithm):
325 Class to define a quadrangle 2D algorithm
328 def __init__(self, mesh, geom=0):
332 self.Create(mesh, geom, "Quadrangle_2D")
334 def QuadranglePreference(self):
336 Define "QuadranglePreference" hypothesis, forcing construction
337 of quadrangles if the number of nodes on opposite edges is not the same
338 in the case where the global number of nodes on edges is even
340 hyp = self.Hypothesis("QuadranglePreference")
343 # Public class: Mesh_Tetrahedron
344 # ------------------------------
346 class Mesh_Tetrahedron(Mesh_Algorithm):
348 Class to define a tetrahedron 3D algorithm
351 def __init__(self, mesh, algo, geom=0):
356 self.Create(mesh, geom, "NETGEN_3D", "libNETGENEngine.so")
359 self.Create(mesh, geom, "GHS3D_3D" , "libGHS3DEngine.so")
361 def MaxElementVolume(self, vol):
363 Define "MaxElementVolume" hypothesis to give the maximun volume of each tetrahedral
364 \param vol for the maximum volume of each tetrahedral
366 hyp = self.Hypothesis("MaxElementVolume", [vol])
367 hyp.SetMaxElementVolume(vol)
370 # Public class: Mesh_Hexahedron
371 # ------------------------------
373 class Mesh_Hexahedron(Mesh_Algorithm):
375 Class to define a hexahedron 3D algorithm
378 def __init__(self, mesh, geom=0):
382 self.Create(mesh, geom, "Hexa_3D")
389 Class to define a mesh
395 def __init__(self, geom, name=0):
399 Creates mesh on the shape \a geom,
400 sets GUI name of this mesh to \a name.
401 \param geom Shape to be meshed
402 \param name Study name of the mesh
405 self.mesh = smesh.CreateMesh(geom)
407 SetName(self.mesh, GetName(geom))
409 SetName(self.mesh, name)
413 Method that returns the mesh
419 Method that returns the shape associated to the mesh
423 def MeshDimension(self):
425 Returns mesh dimension depending on shape one
427 shells = geompy.SubShapeAllIDs( self.geom, geompy.ShapeType["SHELL"] )
428 if len( shells ) > 0 :
430 elif geompy.NumberOfFaces( self.geom ) > 0 :
432 elif geompy.NumberOfEdges( self.geom ) > 0 :
438 def Segment(self, algo=REGULAR, geom=0):
440 Creates a segment discretization 1D algorithm.
441 If the optional \a algo parameter is not sets, this algorithm is REGULAR.
442 If the optional \a geom parameter is not sets, this algorithm is global.
443 Otherwise, this algorithm define a submesh based on \a geom subshape.
444 \param algo values are smesh.REGULAR or smesh.PYTHON for discretization via python function
445 \param geom If defined, subshape to be meshed
447 ## if Segment(geom) is called by mistake
448 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
449 algo, geom = geom, algo
452 return Mesh_Segment(self, geom)
454 return Mesh_Segment_Python(self, geom)
456 return Mesh_Segment(self, geom)
458 def Triangle(self, geom=0):
460 Creates a triangle 2D algorithm for faces.
461 If the optional \a geom parameter is not sets, this algorithm is global.
462 Otherwise, this algorithm define a submesh based on \a geom subshape.
463 \param geom If defined, subshape to be meshed
465 return Mesh_Triangle(self, geom)
467 def Quadrangle(self, geom=0):
469 Creates a quadrangle 2D algorithm for faces.
470 If the optional \a geom parameter is not sets, this algorithm is global.
471 Otherwise, this algorithm define a submesh based on \a geom subshape.
472 \param geom If defined, subshape to be meshed
474 return Mesh_Quadrangle(self, geom)
476 def Tetrahedron(self, algo, geom=0):
478 Creates a tetrahedron 3D algorithm for solids.
479 The parameter \a algo permits to choice the algorithm: NETGEN or GHS3D
480 If the optional \a geom parameter is not sets, this algorithm is global.
481 Otherwise, this algorithm define a submesh based on \a geom subshape.
482 \param algo values are: smesh.NETGEN, smesh.GHS3D
483 \param geom If defined, subshape to be meshed
485 ## if Tetrahedron(geom) is called by mistake
486 if ( isinstance( algo, geompy.GEOM._objref_GEOM_Object)):
487 algo, geom = geom, algo
489 return Mesh_Tetrahedron(self, algo, geom)
491 def Hexahedron(self, geom=0):
493 Creates a hexahedron 3D algorithm for solids.
494 If the optional \a geom parameter is not sets, this algorithm is global.
495 Otherwise, this algorithm define a submesh based on \a geom subshape.
496 \param geom If defined, subshape to be meshed
498 return Mesh_Hexahedron(self, geom)
502 Compute the mesh and return the status of the computation
504 ok = smesh.Compute(self.mesh, self.geom)
506 errors = smesh.GetAlgoState( self.mesh, self.geom )
514 dim = str(err.algoDim)
515 if err.name == SMESH.MISSING_ALGO:
516 reason = glob + dim + "D algorithm is missing"
517 elif err.name == SMESH.MISSING_HYPO:
518 name = '"' + err.algoName + '"'
519 reason = glob + dim + "D algorithm " + name + " misses " + dim + "D hypothesis"
521 reason = "Global \"Not Conform mesh allowed\" hypothesis is missing"
529 print '"' + GetName(self.mesh) + '"',"not computed:"
533 if salome.sg.hasDesktop():
534 smeshgui = salome.ImportComponentGUI("SMESH")
535 smeshgui.Init(salome.myStudyId)
536 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok )
537 salome.sg.updateObjBrowser(1)
541 def AutomaticTetrahedralization(self, fineness=0):
543 Compute tetrahedral mesh using AutomaticLength + MEFISTO + NETGEN
544 The parameter \a fineness [0.-1.] defines mesh fineness
546 dim = self.MeshDimension()
548 self.RemoveGlobalHypotheses()
549 self.Segment().AutomaticLength(fineness)
551 self.Triangle().LengthFromEdges()
554 self.Tetrahedron(NETGEN)
556 return self.Compute()
558 def AutomaticHexahedralization(self, fineness=0):
560 Compute hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
561 The parameter \a fineness [0.-1.] defines mesh fineness
563 dim = self.MeshDimension()
565 self.RemoveGlobalHypotheses()
566 self.Segment().AutomaticLength(fineness)
573 return self.Compute()
575 def RemoveGlobalHypotheses(self):
577 Removes all global hypotheses
579 current_hyps = self.mesh.GetHypothesisList( self.geom )
580 for hyp in current_hyps:
581 self.mesh.RemoveHypothesis( self.geom, hyp )
585 def Group(self, grp, name=""):
587 Create a mesh group based on geometric object \a grp
588 and give a \a name, if this parameter is not defined
589 the name is the same as the geometric group name
590 \param grp is a geometric group, a vertex, an edge, a face or a solid
591 \param name is the name of the mesh group
597 tgeo = str(grp.GetShapeType())
604 elif tgeo == "SOLID":
606 elif tgeo == "SHELL":
608 elif tgeo == "COMPOUND":
609 tgeo = geompy.GetType(grp)
610 if tgeo == geompy.ShapeType["VERTEX"]:
612 elif tgeo == geompy.ShapeType["EDGE"]:
614 elif tgeo == geompy.ShapeType["FACE"]:
616 elif tgeo == geompy.ShapeType["SOLID"]:
620 print "Mesh.Group: bad first argument: expected a group, a vertex, an edge, a face or a solid"
623 return self.mesh.CreateGroupFromGEOM(type, name, grp)
625 def ExportToMED(self, f, version, opt=0):
627 Export the mesh in a file with the MED format and choice the \a version of MED format
628 \param f is the file name
629 \param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
631 self.mesh.ExportToMED(f, opt, version)
633 def ExportMED(self, f, opt=0):
635 Export the mesh in a file with the MED format
636 \param f is the file name
638 self.mesh.ExportMED(f, opt)
640 def ExportDAT(self, f):
642 Export the mesh in a file with the DAT format
643 \param f is the file name
645 self.mesh.ExportDAT(f)
647 def ExportUNV(self, f):
649 Export the mesh in a file with the UNV format
650 \param f is the file name
652 self.mesh.ExportUNV(f)
654 def ExportSTL(self, f, ascii=1):
656 Export the mesh in a file with the STL format
657 \param f is the file name
658 \param ascii defined the kind of file contents
660 self.mesh.ExportSTL(f, ascii)