1 # Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 # File : smeshBuilder.py
20 # Author : Francis KLOSS, OCC
24 from salome.geom import geomBuilder
26 import SMESH # This is necessary for back compatibility
27 import omniORB # back compatibility
28 SMESH.MED_V2_1 = 11 #omniORB.EnumItem("MED_V2_1", 11) # back compatibility: use number > MED minor version
29 SMESH.MED_V2_2 = 12 #omniORB.EnumItem("MED_V2_2", 12) # back compatibility: latest minor will be used
30 SMESH.MED_MINOR_0 = 20 # back compatibility
31 SMESH.MED_MINOR_1 = 21 # back compatibility
32 SMESH.MED_MINOR_2 = 22 # back compatibility
33 SMESH.MED_MINOR_3 = 23 # back compatibility
34 SMESH.MED_MINOR_4 = 24 # back compatibility
35 SMESH.MED_MINOR_5 = 25 # back compatibility
36 SMESH.MED_MINOR_6 = 26 # back compatibility
37 SMESH.MED_MINOR_7 = 27 # back compatibility
38 SMESH.MED_MINOR_8 = 28 # back compatibility
39 SMESH.MED_MINOR_9 = 29 # back compatibility
42 from salome.smesh.smesh_algorithm import Mesh_Algorithm
49 # In case the omniORBpy EnumItem class does not fully support Python 3
50 # (for instance in version 4.2.1-2), the comparison ordering methods must be
54 SMESH.Entity_Triangle < SMESH.Entity_Quadrangle
56 def enumitem_eq(self, other):
58 if isinstance(other, omniORB.EnumItem):
59 if other._parent_id == self._parent_id:
60 return self._v == other._v
62 return self._parent_id == other._parent_id
64 return id(self) == id(other)
66 return id(self) == id(other)
68 def enumitem_lt(self, other):
70 if isinstance(other, omniORB.EnumItem):
71 if other._parent_id == self._parent_id:
72 return self._v < other._v
74 return self._parent_id < other._parent_id
76 return id(self) < id(other)
78 return id(self) < id(other)
80 def enumitem_le(self, other):
82 if isinstance(other, omniORB.EnumItem):
83 if other._parent_id == self._parent_id:
84 return self._v <= other._v
86 return self._parent_id <= other._parent_id
88 return id(self) <= id(other)
90 return id(self) <= id(other)
92 def enumitem_gt(self, other):
94 if isinstance(other, omniORB.EnumItem):
95 if other._parent_id == self._parent_id:
96 return self._v > other._v
98 return self._parent_id > other._parent_id
100 return id(self) > id(other)
102 return id(self) > id(other)
104 def enumitem_ge(self, other):
106 if isinstance(other, omniORB.EnumItem):
107 if other._parent_id == self._parent_id:
108 return self._v >= other._v
110 return self._parent_id >= other._parent_id
112 return id(self) >= id(other)
114 return id(self) >= id(other)
116 omniORB.EnumItem.__eq__ = enumitem_eq
117 omniORB.EnumItem.__lt__ = enumitem_lt
118 omniORB.EnumItem.__le__ = enumitem_le
119 omniORB.EnumItem.__gt__ = enumitem_gt
120 omniORB.EnumItem.__ge__ = enumitem_ge
123 class MeshMeta(type):
124 """Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
126 def __instancecheck__(cls, inst):
127 """Implement isinstance(inst, cls)."""
128 return any(cls.__subclasscheck__(c)
129 for c in {type(inst), inst.__class__})
131 def __subclasscheck__(cls, sub):
132 """Implement issubclass(sub, cls)."""
133 return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
135 def DegreesToRadians(AngleInDegrees):
136 """Convert an angle from degrees to radians
139 return AngleInDegrees * pi / 180.0
141 import salome_notebook
142 notebook = salome_notebook.notebook
143 # Salome notebook variable separator
146 def ParseParameters(*args):
148 Return list of variable values from salome notebook.
149 The last argument, if is callable, is used to modify values got from notebook
155 if args and callable(args[-1]):
156 args, varModifFun = args[:-1], args[-1]
157 for parameter in args:
159 Parameters += str(parameter) + var_separator
161 if isinstance(parameter,str):
162 # check if there is an inexistent variable name
163 if not notebook.isVariable(parameter):
164 raise ValueError("Variable with name '" + parameter + "' doesn't exist!!!")
165 parameter = notebook.get(parameter)
168 parameter = varModifFun(parameter)
171 Result.append(parameter)
174 Parameters = Parameters[:-1]
175 Result.append( Parameters )
176 Result.append( hasVariables )
179 def ParseAngles(*args):
181 Parse parameters while converting variables to radians
183 return ParseParameters( *( args + (DegreesToRadians, )))
185 def __initPointStruct(point,*args):
187 Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
188 Parameters are stored in PointStruct.parameters attribute
190 point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
192 SMESH.PointStruct.__init__ = __initPointStruct
194 def __initAxisStruct(ax,*args):
196 Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
197 Parameters are stored in AxisStruct.parameters attribute
200 raise RuntimeError("Bad nb args (%s) passed in SMESH.AxisStruct(x,y,z,dx,dy,dz)"%(len( args )))
201 ax.x, ax.y, ax.z, ax.vx, ax.vy, ax.vz, ax.parameters,hasVars = ParseParameters(*args)
203 SMESH.AxisStruct.__init__ = __initAxisStruct
205 smeshPrecisionConfusion = 1.e-07
206 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
207 """Compare real values using smeshPrecisionConfusion as tolerance
209 if abs(val1 - val2) < tol:
217 Return a name of an object
224 if isinstance(obj, SALOMEDS._objref_SObject):
228 ior = salome.orb.object_to_string(obj)
232 sobj = salome.myStudy.FindObjectIOR(ior)
234 return sobj.GetName()
235 if hasattr(obj, "GetName"):
236 # unknown CORBA object, having GetName() method
239 # unknown CORBA object, no GetName() method
242 if hasattr(obj, "GetName"):
243 # unknown non-CORBA object, having GetName() method
246 raise RuntimeError("Null or invalid object")
248 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
250 Print error message if a hypothesis was not assigned.
253 hypType = "algorithm"
255 hypType = "hypothesis"
258 if hasattr( status, "__getitem__" ):
259 status, reason = status[0], status[1]
260 if status == HYP_UNKNOWN_FATAL:
261 reason = "for unknown reason"
262 elif status == HYP_INCOMPATIBLE:
263 reason = "this hypothesis mismatches the algorithm"
264 elif status == HYP_NOTCONFORM:
265 reason = "a non-conform mesh would be built"
266 elif status == HYP_ALREADY_EXIST:
267 if isAlgo: return # it does not influence anything
268 reason = hypType + " of the same dimension is already assigned to this shape"
269 elif status == HYP_BAD_DIM:
270 reason = hypType + " mismatches the shape"
271 elif status == HYP_CONCURRENT :
272 reason = "there are concurrent hypotheses on sub-shapes"
273 elif status == HYP_BAD_SUBSHAPE:
274 reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
275 elif status == HYP_BAD_GEOMETRY:
276 reason = "the algorithm is not applicable to this geometry"
277 elif status == HYP_HIDDEN_ALGO:
278 reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
279 elif status == HYP_HIDING_ALGO:
280 reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
281 elif status == HYP_NEED_SHAPE:
282 reason = "algorithm can't work without shape"
283 elif status == HYP_INCOMPAT_HYPS:
289 where = '"%s"' % geomName
291 meshName = GetName( mesh )
292 if meshName and meshName != NO_NAME:
293 where = '"%s" shape in "%s" mesh ' % ( geomName, meshName )
294 if status < HYP_UNKNOWN_FATAL and where:
295 print('"%s" was assigned to %s but %s' %( hypName, where, reason ))
297 print('"%s" was not assigned to %s : %s' %( hypName, where, reason ))
299 print('"%s" was not assigned : %s' %( hypName, reason ))
302 def AssureGeomPublished(mesh, geom, name=''):
304 Private method. Add geom (sub-shape of the main shape) into the study if not yet there
306 if not mesh.smeshpyD.IsEnablePublish():
308 if not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
310 if not geom.GetStudyEntry():
312 if not name and geom.GetShapeType() != geomBuilder.GEOM.COMPOUND:
313 # for all groups SubShapeName() return "Compound_-1"
314 name = mesh.geompyD.SubShapeName(geom, mesh.geom)
316 name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
318 mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
321 def FirstVertexOnCurve(mesh, edge):
324 the first vertex of a geometrical edge by ignoring orientation
326 vv = mesh.geompyD.SubShapeAll( edge, geomBuilder.geomBuilder.ShapeType["VERTEX"])
328 raise TypeError("Given object has no vertices")
329 if len( vv ) == 1: return vv[0]
330 v0 = mesh.geompyD.MakeVertexOnCurve(edge,0.)
331 xyz = mesh.geompyD.PointCoordinates( v0 ) # coords of the first vertex
332 xyz1 = mesh.geompyD.PointCoordinates( vv[0] )
333 xyz2 = mesh.geompyD.PointCoordinates( vv[1] )
336 dist1 += abs( xyz[i] - xyz1[i] )
337 dist2 += abs( xyz[i] - xyz2[i] )
346 smeshInst is a singleton
352 class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
354 This class allows to create, load or manipulate meshes.
355 It has a set of methods to create, load or copy meshes, to combine several meshes, etc.
356 It also has methods to get infos and measure meshes.
359 # MirrorType enumeration
360 POINT = SMESH_MeshEditor.POINT
361 AXIS = SMESH_MeshEditor.AXIS
362 PLANE = SMESH_MeshEditor.PLANE
364 # Smooth_Method enumeration
365 LAPLACIAN_SMOOTH = SMESH_MeshEditor.LAPLACIAN_SMOOTH
366 CENTROIDAL_SMOOTH = SMESH_MeshEditor.CENTROIDAL_SMOOTH
368 PrecisionConfusion = smeshPrecisionConfusion
370 # TopAbs_State enumeration
371 [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = list(range(4))
373 # Methods of splitting a hexahedron into tetrahedra
374 Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
376 def __new__(cls, *args):
380 #print("==== __new__", engine, smeshInst, doLcc)
382 if smeshInst is None:
383 # smesh engine is either retrieved from engine, or created
385 # Following test avoids a recursive loop
387 if smeshInst is not None:
388 # smesh engine not created: existing engine found
392 # FindOrLoadComponent called:
393 # 1. CORBA resolution of server
394 # 2. the __new__ method is called again
395 #print("==== smeshInst = lcc.FindOrLoadComponent ", engine, smeshInst, doLcc)
396 smeshInst = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" )
398 # FindOrLoadComponent not called
399 if smeshInst is None:
400 # smeshBuilder instance is created from lcc.FindOrLoadComponent
401 #print("==== smeshInst = super(smeshBuilder,cls).__new__(cls) ", engine, smeshInst, doLcc)
402 smeshInst = super(smeshBuilder,cls).__new__(cls)
404 # smesh engine not created: existing engine found
405 #print("==== existing ", engine, smeshInst, doLcc)
407 #print("====1 ", smeshInst)
410 #print("====2 ", smeshInst)
413 def __init__(self, *args):
415 #print("--------------- smeshbuilder __init__ ---", created)
418 SMESH._objref_SMESH_Gen.__init__(self, *args)
421 def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
423 Dump component to the Python script.
424 This method overrides IDL function to allow default values for the parameters.
427 return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
429 def SetDumpPythonHistorical(self, isHistorical):
431 Set mode of DumpPython(), *historical* or *snapshot*.
432 In the *historical* mode, the Python Dump script includes all commands
433 performed by SMESH engine. In the *snapshot* mode, commands
434 relating to objects removed from the Study are excluded from the script
435 as well as commands not influencing the current state of meshes
438 if isHistorical: val = "true"
440 SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
442 def init_smesh(self,geompyD = None):
444 Set Geometry component
447 self.UpdateStudy(geompyD)
448 notebook.myStudy = salome.myStudy
450 def Mesh(self, obj=0, name=0):
452 Create a mesh. This mesh can be either
454 * an empty mesh not bound to geometry, if *obj* == 0
455 * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
456 * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
461 1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
464 salome.myStudy.FindObjectID("0:1:2:3").GetObject()
466 2. a geometrical object for meshing
468 name: the name for the new mesh.
471 an instance of class :class:`Mesh`.
474 if isinstance(obj,str):
476 return Mesh(self, self.geompyD, obj, name)
478 def EnumToLong(self,theItem):
480 Return a long value from enumeration
485 def ColorToString(self,c):
487 Convert SALOMEDS.Color to string.
488 To be used with filters.
491 c: color value (SALOMEDS.Color)
494 a string representation of the color.
498 if isinstance(c, SALOMEDS.Color):
499 val = "%s;%s;%s" % (c.R, c.G, c.B)
500 elif isinstance(c, str):
503 raise ValueError("Color value should be of string or SALOMEDS.Color type")
506 def GetPointStruct(self,theVertex):
508 Get :class:`SMESH.PointStruct` from vertex
511 theVertex (GEOM.GEOM_Object): vertex
514 :class:`SMESH.PointStruct`
517 [x, y, z] = self.geompyD.PointCoordinates(theVertex)
518 return PointStruct(x,y,z)
520 def GetDirStruct(self,theVector):
522 Get :class:`SMESH.DirStruct` from vector
525 theVector (GEOM.GEOM_Object): vector
528 :class:`SMESH.DirStruct`
531 vertices = self.geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
532 if(len(vertices) != 2):
533 print("Error: vector object is incorrect.")
535 p1 = self.geompyD.PointCoordinates(vertices[0])
536 p2 = self.geompyD.PointCoordinates(vertices[1])
537 pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
538 dirst = DirStruct(pnt)
541 def MakeDirStruct(self,x,y,z):
543 Make :class:`SMESH.DirStruct` from a triplet of floats
546 x,y,z (float): vector components
549 :class:`SMESH.DirStruct`
552 pnt = PointStruct(x,y,z)
553 return DirStruct(pnt)
555 def GetAxisStruct(self,theObj):
557 Get :class:`SMESH.AxisStruct` from a geometrical object
560 theObj (GEOM.GEOM_Object): line or plane
563 :class:`SMESH.AxisStruct`
566 edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
569 vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
570 vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
571 vertex1 = self.geompyD.PointCoordinates(vertex1)
572 vertex2 = self.geompyD.PointCoordinates(vertex2)
573 vertex3 = self.geompyD.PointCoordinates(vertex3)
574 vertex4 = self.geompyD.PointCoordinates(vertex4)
575 v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
576 v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
577 normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
578 axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
579 axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
580 elif len(edges) == 1:
581 vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
582 p1 = self.geompyD.PointCoordinates( vertex1 )
583 p2 = self.geompyD.PointCoordinates( vertex2 )
584 axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
585 axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
586 elif theObj.GetShapeType() == GEOM.VERTEX:
587 x,y,z = self.geompyD.PointCoordinates( theObj )
588 axis = AxisStruct( x,y,z, 1,0,0,)
589 axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
592 # From SMESH_Gen interface:
593 # ------------------------
595 def SetName(self, obj, name):
597 Set the given name to an object
600 obj: the object to rename
601 name: a new object name
604 if isinstance( obj, Mesh ):
606 elif isinstance( obj, Mesh_Algorithm ):
607 obj = obj.GetAlgorithm()
608 ior = salome.orb.object_to_string(obj)
609 SMESH._objref_SMESH_Gen.SetName(self, ior, name)
611 def SetEmbeddedMode( self,theMode ):
616 SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
618 def IsEmbeddedMode(self):
623 return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
625 def UpdateStudy( self, geompyD = None ):
627 Update the current study. Calling UpdateStudy() allows to
628 update meshes at switching GEOM->SMESH
632 from salome.geom import geomBuilder
633 geompyD = geomBuilder.geom
635 geompyD = geomBuilder.New()
638 self.SetGeomEngine(geompyD)
639 SMESH._objref_SMESH_Gen.UpdateStudy(self)
640 sb = salome.myStudy.NewBuilder()
641 sc = salome.myStudy.FindComponent("SMESH")
643 sb.LoadWith(sc, self)
646 def SetEnablePublish( self, theIsEnablePublish ):
648 Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
649 switch **off** publishing in the Study of mesh objects.
651 #self.SetEnablePublish(theIsEnablePublish)
652 SMESH._objref_SMESH_Gen.SetEnablePublish(self,theIsEnablePublish)
654 notebook = salome_notebook.NoteBook( theIsEnablePublish )
657 def CreateMeshesFromUNV( self,theFileName ):
659 Create a Mesh object importing data from the given UNV file
662 an instance of class :class:`Mesh`
665 aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromUNV(self,theFileName)
666 aMesh = Mesh(self, self.geompyD, aSmeshMesh)
669 def CreateMeshesFromMED( self,theFileName ):
671 Create a Mesh object(s) importing data from the given MED file
674 a tuple ( list of class :class:`Mesh` instances,
675 :class:`SMESH.DriverMED_ReadStatus` )
678 aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
679 aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
680 return aMeshes, aStatus
682 def CreateMeshesFromSAUV( self,theFileName ):
684 Create a Mesh object(s) importing data from the given SAUV file
687 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
690 aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
691 aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
692 return aMeshes, aStatus
694 def CreateMeshesFromSTL( self, theFileName ):
696 Create a Mesh object importing data from the given STL file
699 an instance of class :class:`Mesh`
702 aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromSTL(self,theFileName)
703 aMesh = Mesh(self, self.geompyD, aSmeshMesh)
706 def CreateMeshesFromCGNS( self, theFileName ):
708 Create Mesh objects importing data from the given CGNS file
711 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
714 aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
715 aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
716 return aMeshes, aStatus
718 def CreateMeshesFromGMF( self, theFileName ):
720 Create a Mesh object importing data from the given GMF file.
721 GMF files must have .mesh extension for the ASCII format and .meshb for
725 ( an instance of class :class:`Mesh`, :class:`SMESH.ComputeError` )
728 aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
731 if error.comment: print("*** CreateMeshesFromGMF() errors:\n", error.comment)
732 return Mesh(self, self.geompyD, aSmeshMesh), error
734 def Concatenate( self, meshes, uniteIdenticalGroups,
735 mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
736 name = "", meshToAppendTo = None):
738 Concatenate the given meshes into one mesh, optionally to meshToAppendTo.
739 All groups of input meshes will be present in the new mesh.
742 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
743 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
744 mergeNodesAndElements: if True, equal nodes and elements are merged
745 mergeTolerance: tolerance for merging nodes
746 allGroups: forces creation of groups corresponding to every input mesh
747 name: name of a new mesh
748 meshToAppendTo a mesh to append all given meshes
751 an instance of class :class:`Mesh`
754 if not meshes: return None
755 for i,m in enumerate(meshes):
756 if isinstance(m, Mesh):
757 meshes[i] = m.GetMesh()
758 mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
759 if hasattr(meshes[0], "SetParameters"):
760 meshes[0].SetParameters(Parameters)
762 meshes[0].GetMesh().SetParameters(Parameters)
763 if isinstance( meshToAppendTo, Mesh ):
764 meshToAppendTo = meshToAppendTo.GetMesh()
766 aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
767 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
768 mergeTolerance,meshToAppendTo)
770 aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
771 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
772 mergeTolerance,meshToAppendTo)
774 aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
777 def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
779 Create a mesh by copying a part of another mesh.
782 meshPart: a part of mesh to copy, either
783 :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
784 To copy nodes or elements not forming any mesh object,
785 pass result of :meth:`Mesh.GetIDSource` as *meshPart*
786 meshName: a name of the new mesh
787 toCopyGroups: to create in the new mesh groups the copied elements belongs to
788 toKeepIDs: to preserve order of the copied elements or not
791 an instance of class :class:`Mesh`
794 if isinstance( meshPart, Mesh ):
795 meshPart = meshPart.GetMesh()
796 mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
797 return Mesh(self, self.geompyD, mesh)
799 def CopyMeshWithGeom( self, sourceMesh, newGeom, meshName="", toCopyGroups=True,
800 toReuseHypotheses=True, toCopyElements=True):
802 Create a mesh by copying a mesh definition (hypotheses and groups) to a new geometry.
803 It is supposed that the new geometry is a modified geometry of *sourceMesh*.
804 To facilitate and speed up the operation, consider using
805 "Set presentation parameters and sub-shapes from arguments" option in
806 a dialog of geometrical operation used to create the new geometry.
809 sourceMesh: the mesh to copy definition of.
810 newGeom: the new geomtry.
811 meshName: an optional name of the new mesh. If omitted, the mesh name is kept.
812 toCopyGroups: to create groups in the new mesh.
813 toReuseHypotheses: to reuse hypotheses of the *sourceMesh*.
814 toCopyElements: to copy mesh elements present on non-modified sub-shapes of
817 tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries )
818 *invalidEntries* are study entries of objects whose
819 counterparts are not found in the *newGeom*, followed by entries
820 of mesh sub-objects that are invalid because they depend on a not found
823 if isinstance( sourceMesh, Mesh ):
824 sourceMesh = sourceMesh.GetMesh()
826 ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries = \
827 SMESH._objref_SMESH_Gen.CopyMeshWithGeom( self, sourceMesh, newGeom, meshName,
831 return ( ok, Mesh(self, self.geompyD, newMesh),
832 newGroups, newSubMeshes, newHypotheses, invalidEntries )
834 def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
836 Return IDs of sub-shapes
839 theMainObject (GEOM.GEOM_Object): a shape
840 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
842 the list of integer values
845 return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
847 def GetPattern(self):
849 Create a pattern mapper.
852 an instance of :class:`SMESH.SMESH_Pattern`
854 :ref:`Example of Patterns usage <tui_pattern_mapping>`
857 return SMESH._objref_SMESH_Gen.GetPattern(self)
859 def SetBoundaryBoxSegmentation(self, nbSegments):
861 Set number of segments per diagonal of boundary box of geometry, by which
862 default segment length of appropriate 1D hypotheses is defined in GUI.
866 SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
868 # Filtering. Auxiliary functions:
869 # ------------------------------
871 def GetEmptyCriterion(self):
873 Create an empty criterion
876 :class:`SMESH.Filter.Criterion`
879 Type = self.EnumToLong(FT_Undefined)
880 Compare = self.EnumToLong(FT_Undefined)
884 UnaryOp = self.EnumToLong(FT_Undefined)
885 BinaryOp = self.EnumToLong(FT_Undefined)
888 Precision = -1 ##@1e-07
889 return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
890 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
892 def GetCriterion(self,elementType,
894 Compare = FT_EqualTo,
896 UnaryOp=FT_Undefined,
897 BinaryOp=FT_Undefined,
900 Create a criterion by the given parameters
901 Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
904 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
905 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
906 Note that the items starting from FT_LessThan are not suitable for *CritType*.
907 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
908 Threshold: the threshold value (range of ids as string, shape, numeric)
909 UnaryOp: SMESH.FT_LogicalNOT or SMESH.FT_Undefined
910 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
912 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
913 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
916 :class:`SMESH.Filter.Criterion`
918 Example: :ref:`combining_filters`
921 if not CritType in SMESH.FunctorType._items:
922 raise TypeError("CritType should be of SMESH.FunctorType")
923 aCriterion = self.GetEmptyCriterion()
924 aCriterion.TypeOfElement = elementType
925 aCriterion.Type = self.EnumToLong(CritType)
926 aCriterion.Tolerance = Tolerance
928 aThreshold = Threshold
930 if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
931 aCriterion.Compare = self.EnumToLong(Compare)
932 elif Compare == "=" or Compare == "==":
933 aCriterion.Compare = self.EnumToLong(FT_EqualTo)
935 aCriterion.Compare = self.EnumToLong(FT_LessThan)
937 aCriterion.Compare = self.EnumToLong(FT_MoreThan)
938 elif Compare != FT_Undefined:
939 aCriterion.Compare = self.EnumToLong(FT_EqualTo)
942 if CritType in [FT_BelongToGeom, FT_BelongToPlane, FT_BelongToGenSurface,
943 FT_BelongToCylinder, FT_LyingOnGeom]:
944 # Check that Threshold is GEOM object
945 if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
946 aCriterion.ThresholdStr = GetName(aThreshold)
947 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
948 if not aCriterion.ThresholdID:
949 name = aCriterion.ThresholdStr
951 name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
952 aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
953 # or a name of GEOM object
954 elif isinstance( aThreshold, str ):
955 aCriterion.ThresholdStr = aThreshold
957 raise TypeError("The Threshold should be a shape.")
958 if isinstance(UnaryOp,float):
959 aCriterion.Tolerance = UnaryOp
960 UnaryOp = FT_Undefined
962 elif CritType == FT_BelongToMeshGroup:
963 # Check that Threshold is a group
964 if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
965 if aThreshold.GetType() != elementType:
966 raise ValueError("Group type mismatches Element type")
967 aCriterion.ThresholdStr = aThreshold.GetName()
968 aCriterion.ThresholdID = salome.orb.object_to_string( aThreshold )
969 study = salome.myStudy
971 so = study.FindObjectIOR( aCriterion.ThresholdID )
975 aCriterion.ThresholdID = entry
977 raise TypeError("The Threshold should be a Mesh Group")
978 elif CritType == FT_RangeOfIds:
979 # Check that Threshold is string
980 if isinstance(aThreshold, str):
981 aCriterion.ThresholdStr = aThreshold
983 raise TypeError("The Threshold should be a string.")
984 elif CritType == FT_CoplanarFaces:
985 # Check the Threshold
986 if isinstance(aThreshold, int):
987 aCriterion.ThresholdID = str(aThreshold)
988 elif isinstance(aThreshold, str):
991 raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
992 aCriterion.ThresholdID = aThreshold
994 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
995 elif CritType == FT_ConnectedElements:
996 # Check the Threshold
997 if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
998 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
999 if not aCriterion.ThresholdID:
1000 name = aThreshold.GetName()
1002 name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
1003 aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
1004 elif isinstance(aThreshold, int): # node id
1005 aCriterion.Threshold = aThreshold
1006 elif isinstance(aThreshold, list): # 3 point coordinates
1007 if len( aThreshold ) < 3:
1008 raise ValueError("too few point coordinates, must be 3")
1009 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
1010 elif isinstance(aThreshold, str):
1011 if aThreshold.isdigit():
1012 aCriterion.Threshold = aThreshold # node id
1014 aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
1016 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
1017 "or a list of point coordinates and not '%s'"%aThreshold)
1018 elif CritType == FT_ElemGeomType:
1019 # Check the Threshold
1021 aCriterion.Threshold = self.EnumToLong(aThreshold)
1022 assert( aThreshold in SMESH.GeometryType._items )
1024 if isinstance(aThreshold, int):
1025 aCriterion.Threshold = aThreshold
1027 raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
1030 elif CritType == FT_EntityType:
1031 # Check the Threshold
1033 aCriterion.Threshold = self.EnumToLong(aThreshold)
1034 assert( aThreshold in SMESH.EntityType._items )
1036 if isinstance(aThreshold, int):
1037 aCriterion.Threshold = aThreshold
1039 raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
1043 elif CritType == FT_GroupColor:
1044 # Check the Threshold
1046 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
1048 raise TypeError("The threshold value should be of SALOMEDS.Color type")
1050 elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
1051 FT_LinearOrQuadratic, FT_BadOrientedVolume,
1052 FT_BareBorderFace, FT_BareBorderVolume,
1053 FT_OverConstrainedFace, FT_OverConstrainedVolume,
1054 FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
1055 # At this point the Threshold is unnecessary
1056 if aThreshold == FT_LogicalNOT:
1057 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1058 elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1059 aCriterion.BinaryOp = aThreshold
1063 aThreshold = float(aThreshold)
1064 aCriterion.Threshold = aThreshold
1066 raise TypeError("The Threshold should be a number.")
1069 if Threshold == FT_LogicalNOT or UnaryOp == FT_LogicalNOT:
1070 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1072 if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1073 aCriterion.BinaryOp = self.EnumToLong(Threshold)
1075 if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1076 aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1078 if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1079 aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1083 def GetFilter(self,elementType,
1084 CritType=FT_Undefined,
1087 UnaryOp=FT_Undefined,
1091 Create a filter with the given parameters
1094 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1095 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1096 Note that the items starting from FT_LessThan are not suitable for CritType.
1097 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1098 Threshold: the threshold value (range of ids as string, shape, numeric)
1099 UnaryOp: SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1100 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1101 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1102 mesh: the mesh to initialize the filter with
1105 :class:`SMESH.Filter`
1108 See :doc:`Filters usage examples <tui_filters>`
1111 aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1112 aFilterMgr = self.CreateFilterManager()
1113 aFilter = aFilterMgr.CreateFilter()
1115 aCriteria.append(aCriterion)
1116 aFilter.SetCriteria(aCriteria)
1118 if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1119 else : aFilter.SetMesh( mesh )
1120 aFilterMgr.UnRegister()
1123 def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1125 Create a filter from criteria
1128 criteria: a list of :class:`SMESH.Filter.Criterion`
1129 binOp: binary operator used when binary operator of criteria is undefined
1132 :class:`SMESH.Filter`
1135 See :doc:`Filters usage examples <tui_filters>`
1138 for i in range( len( criteria ) - 1 ):
1139 if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1140 criteria[i].BinaryOp = self.EnumToLong( binOp )
1141 aFilterMgr = self.CreateFilterManager()
1142 aFilter = aFilterMgr.CreateFilter()
1143 aFilter.SetCriteria(criteria)
1144 aFilterMgr.UnRegister()
1147 def GetFunctor(self,theCriterion):
1149 Create a numerical functor by its type
1152 theCriterion (SMESH.FunctorType): functor type.
1153 Note that not all items correspond to numerical functors.
1156 :class:`SMESH.NumericalFunctor`
1159 if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1161 aFilterMgr = self.CreateFilterManager()
1163 if theCriterion == FT_AspectRatio:
1164 functor = aFilterMgr.CreateAspectRatio()
1165 elif theCriterion == FT_AspectRatio3D:
1166 functor = aFilterMgr.CreateAspectRatio3D()
1167 elif theCriterion == FT_Warping:
1168 functor = aFilterMgr.CreateWarping()
1169 elif theCriterion == FT_MinimumAngle:
1170 functor = aFilterMgr.CreateMinimumAngle()
1171 elif theCriterion == FT_Taper:
1172 functor = aFilterMgr.CreateTaper()
1173 elif theCriterion == FT_Skew:
1174 functor = aFilterMgr.CreateSkew()
1175 elif theCriterion == FT_Area:
1176 functor = aFilterMgr.CreateArea()
1177 elif theCriterion == FT_Volume3D:
1178 functor = aFilterMgr.CreateVolume3D()
1179 elif theCriterion == FT_MaxElementLength2D:
1180 functor = aFilterMgr.CreateMaxElementLength2D()
1181 elif theCriterion == FT_MaxElementLength3D:
1182 functor = aFilterMgr.CreateMaxElementLength3D()
1183 elif theCriterion == FT_MultiConnection:
1184 functor = aFilterMgr.CreateMultiConnection()
1185 elif theCriterion == FT_MultiConnection2D:
1186 functor = aFilterMgr.CreateMultiConnection2D()
1187 elif theCriterion == FT_Length:
1188 functor = aFilterMgr.CreateLength()
1189 elif theCriterion == FT_Length2D:
1190 functor = aFilterMgr.CreateLength2D()
1191 elif theCriterion == FT_Deflection2D:
1192 functor = aFilterMgr.CreateDeflection2D()
1193 elif theCriterion == FT_NodeConnectivityNumber:
1194 functor = aFilterMgr.CreateNodeConnectivityNumber()
1195 elif theCriterion == FT_BallDiameter:
1196 functor = aFilterMgr.CreateBallDiameter()
1198 print("Error: given parameter is not numerical functor type.")
1199 aFilterMgr.UnRegister()
1202 def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1207 theHType (string): mesh hypothesis type
1208 theLibName (string): mesh plug-in library name
1211 created hypothesis instance
1213 hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1215 if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1218 # wrap hypothesis methods
1219 for meth_name in dir( hyp.__class__ ):
1220 if not meth_name.startswith("Get") and \
1221 not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1222 method = getattr ( hyp.__class__, meth_name )
1223 if callable(method):
1224 setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1228 def GetMeshInfo(self, obj):
1230 Get the mesh statistic.
1231 Use :meth:`smeshBuilder.EnumToLong` to get an integer from
1232 an item of :class:`SMESH.EntityType`.
1235 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1238 if isinstance( obj, Mesh ):
1241 if hasattr(obj, "GetMeshInfo"):
1242 values = obj.GetMeshInfo()
1243 for i in range(SMESH.Entity_Last._v):
1244 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1248 def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1250 Get minimum distance between two objects
1252 * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1253 * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1256 src1 (SMESH.SMESH_IDSource): first source object
1257 src2 (SMESH.SMESH_IDSource): second source object
1258 id1 (int): node/element id from the first source
1259 id2 (int): node/element id from the second (or first) source
1260 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1261 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1264 minimum distance value
1267 :meth:`GetMinDistance`
1270 result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1274 result = result.value
1277 def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1279 Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1281 * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1282 * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1285 src1 (SMESH.SMESH_IDSource): first source object
1286 src2 (SMESH.SMESH_IDSource): second source object
1287 id1 (int): node/element id from the first source
1288 id2 (int): node/element id from the second (or first) source
1289 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1290 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1293 :class:`SMESH.Measure` structure or None if input data is invalid
1298 if isinstance(src1, Mesh): src1 = src1.mesh
1299 if isinstance(src2, Mesh): src2 = src2.mesh
1300 if src2 is None and id2 != 0: src2 = src1
1301 if not hasattr(src1, "_narrow"): return None
1302 src1 = src1._narrow(SMESH.SMESH_IDSource)
1303 if not src1: return None
1304 unRegister = genObjUnRegister()
1307 e = m.GetMeshEditor()
1309 src1 = e.MakeIDSource([id1], SMESH.FACE)
1311 src1 = e.MakeIDSource([id1], SMESH.NODE)
1312 unRegister.set( src1 )
1314 if hasattr(src2, "_narrow"):
1315 src2 = src2._narrow(SMESH.SMESH_IDSource)
1316 if src2 and id2 != 0:
1318 e = m.GetMeshEditor()
1320 src2 = e.MakeIDSource([id2], SMESH.FACE)
1322 src2 = e.MakeIDSource([id2], SMESH.NODE)
1323 unRegister.set( src2 )
1326 aMeasurements = self.CreateMeasurements()
1327 unRegister.set( aMeasurements )
1328 result = aMeasurements.MinDistance(src1, src2)
1331 def BoundingBox(self, objects):
1333 Get bounding box of the specified object(s)
1336 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1339 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1342 :meth:`GetBoundingBox`
1345 result = self.GetBoundingBox(objects)
1349 result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1352 def GetBoundingBox(self, objects):
1354 Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1357 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1360 :class:`SMESH.Measure` structure
1366 if isinstance(objects, tuple):
1367 objects = list(objects)
1368 if not isinstance(objects, list):
1372 if isinstance(o, Mesh):
1373 srclist.append(o.mesh)
1374 elif hasattr(o, "_narrow"):
1375 src = o._narrow(SMESH.SMESH_IDSource)
1376 if src: srclist.append(src)
1379 aMeasurements = self.CreateMeasurements()
1380 result = aMeasurements.BoundingBox(srclist)
1381 aMeasurements.UnRegister()
1384 def GetLength(self, obj):
1386 Get sum of lengths of all 1D elements in the mesh object.
1389 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1392 sum of lengths of all 1D elements
1395 if isinstance(obj, Mesh): obj = obj.mesh
1396 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1397 aMeasurements = self.CreateMeasurements()
1398 value = aMeasurements.Length(obj)
1399 aMeasurements.UnRegister()
1402 def GetArea(self, obj):
1404 Get sum of areas of all 2D elements in the mesh object.
1407 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1410 sum of areas of all 2D elements
1413 if isinstance(obj, Mesh): obj = obj.mesh
1414 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1415 aMeasurements = self.CreateMeasurements()
1416 value = aMeasurements.Area(obj)
1417 aMeasurements.UnRegister()
1420 def GetVolume(self, obj):
1422 Get sum of volumes of all 3D elements in the mesh object.
1425 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1428 sum of volumes of all 3D elements
1431 if isinstance(obj, Mesh): obj = obj.mesh
1432 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1433 aMeasurements = self.CreateMeasurements()
1434 value = aMeasurements.Volume(obj)
1435 aMeasurements.UnRegister()
1438 def GetGravityCenter(self, obj):
1440 Get gravity center of all nodes of a mesh object.
1443 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1446 Three components of the gravity center (x,y,z)
1449 :meth:`Mesh.BaryCenter`
1451 if isinstance(obj, Mesh): obj = obj.mesh
1452 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1453 aMeasurements = self.CreateMeasurements()
1454 pointStruct = aMeasurements.GravityCenter(obj)
1455 aMeasurements.UnRegister()
1456 return pointStruct.x, pointStruct.y, pointStruct.z
1458 def GetAngle(self, p1, p2, p3 ):
1460 Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3)
1463 p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct
1469 if isinstance( p1, list ): p1 = PointStruct(*p1)
1470 if isinstance( p2, list ): p2 = PointStruct(*p2)
1471 if isinstance( p3, list ): p3 = PointStruct(*p3)
1473 aMeasurements = self.CreateMeasurements()
1474 angle = aMeasurements.Angle(p1,p2,p3)
1475 aMeasurements.UnRegister()
1480 pass # end of class smeshBuilder
1483 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1484 """Registering the new proxy for SMESH.SMESH_Gen"""
1487 def New( instance=None, instanceGeom=None):
1489 Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1490 interface to create or load meshes.
1495 salome.salome_init()
1496 from salome.smesh import smeshBuilder
1497 smesh = smeshBuilder.New()
1500 instance: CORBA proxy of SMESH Engine. If None, the default Engine is used.
1501 instanceGeom: CORBA proxy of GEOM Engine. If None, the default Engine is used.
1503 :class:`smeshBuilder` instance
1508 if instance and isinstance( instance, SALOMEDS._objref_Study ):
1510 sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1515 smeshInst = smeshBuilder()
1516 assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1517 smeshInst.init_smesh(instanceGeom)
1521 # Public class: Mesh
1522 # ==================
1525 class Mesh(metaclass = MeshMeta):
1527 This class allows defining and managing a mesh.
1528 It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1529 It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1530 new nodes and elements and by changing the existing entities), to get information
1531 about a mesh and to export a mesh in different formats.
1538 def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1543 Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1544 sets the GUI name of this mesh to *name*.
1547 smeshpyD: an instance of smeshBuilder class
1548 geompyD: an instance of geomBuilder class
1549 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1550 name: Study name of the mesh
1553 self.smeshpyD = smeshpyD
1554 self.geompyD = geompyD
1559 if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1562 # publish geom of mesh (issue 0021122)
1563 if not self.geom.GetStudyEntry():
1567 geo_name = name + " shape"
1569 geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1570 geompyD.addToStudy( self.geom, geo_name )
1571 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1573 elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1576 self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1578 self.smeshpyD.SetName(self.mesh, name)
1580 self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1583 self.geom = self.mesh.GetShapeToMesh()
1585 self.editor = self.mesh.GetMeshEditor()
1586 self.functors = [None] * SMESH.FT_Undefined._v
1588 # set self to algoCreator's
1589 for attrName in dir(self):
1590 attr = getattr( self, attrName )
1591 if isinstance( attr, algoCreator ):
1592 setattr( self, attrName, attr.copy( self ))
1599 Destructor. Clean-up resources
1602 #self.mesh.UnRegister()
1606 def SetMesh(self, theMesh):
1608 Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1611 theMesh: a :class:`SMESH.SMESH_Mesh` object
1615 # do not call Register() as this prevents mesh servant deletion at closing study
1616 #if self.mesh: self.mesh.UnRegister()
1619 #self.mesh.Register()
1620 self.geom = self.mesh.GetShapeToMesh()
1625 Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1628 a :class:`SMESH.SMESH_Mesh` object
1633 def GetEngine(self):
1635 Return a smeshBuilder instance created this mesh
1637 return self.smeshpyD
1639 def GetGeomEngine(self):
1641 Return a geomBuilder instance
1647 Get the name of the mesh
1650 the name of the mesh as a string
1653 name = GetName(self.GetMesh())
1656 def SetName(self, name):
1658 Set a name to the mesh
1661 name: a new name of the mesh
1664 self.smeshpyD.SetName(self.GetMesh(), name)
1666 def GetSubMesh(self, geom, name):
1668 Get a sub-mesh object associated to a *geom* geometrical object.
1671 geom: a geometrical object (shape)
1672 name: a name for the sub-mesh in the Object Browser
1675 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1676 which lies on the given shape
1679 A sub-mesh is implicitly created when a sub-shape is specified at
1680 creating an algorithm, for example::
1682 algo1D = mesh.Segment(geom=Edge_1)
1684 create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1685 The created sub-mesh can be retrieved from the algorithm::
1687 submesh = algo1D.GetSubMesh()
1690 AssureGeomPublished( self, geom, name )
1691 submesh = self.mesh.GetSubMesh( geom, name )
1696 Return the shape associated to the mesh
1704 def SetShape(self, geom):
1706 Associate the given shape to the mesh (entails the recreation of the mesh)
1709 geom: the shape to be meshed (GEOM_Object)
1712 self.mesh = self.smeshpyD.CreateMesh(geom)
1714 def HasShapeToMesh(self):
1716 Return ``True`` if this mesh is based on geometry
1718 return self.mesh.HasShapeToMesh()
1722 Load mesh from the study after opening the study
1726 def IsReadyToCompute(self, theSubObject):
1728 Return true if the hypotheses are defined well
1731 theSubObject: a sub-shape of a mesh shape
1737 return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1739 def GetAlgoState(self, theSubObject):
1741 Return errors of hypotheses definition.
1742 The list of errors is empty if everything is OK.
1745 theSubObject: a sub-shape of a mesh shape
1751 return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1753 def GetGeometryByMeshElement(self, theElementID, theGeomName):
1755 Return a geometrical object on which the given element was built.
1756 The returned geometrical object, if not nil, is either found in the
1757 study or published by this method with the given name
1760 theElementID: the id of the mesh element
1761 theGeomName: the user-defined name of the geometrical object
1764 GEOM.GEOM_Object instance
1767 return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1769 def MeshDimension(self):
1771 Return the mesh dimension depending on the dimension of the underlying shape
1772 or, if the mesh is not based on any shape, basing on deimension of elements
1775 mesh dimension as an integer value [0,3]
1778 if self.mesh.HasShapeToMesh():
1779 shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1780 if len( shells ) > 0 :
1782 elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1784 elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1789 if self.NbVolumes() > 0: return 3
1790 if self.NbFaces() > 0: return 2
1791 if self.NbEdges() > 0: return 1
1794 def Evaluate(self, geom=0):
1796 Evaluate size of prospective mesh on a shape
1799 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1800 To know predicted number of e.g. edges, inquire it this way::
1802 Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1805 if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1807 geom = self.mesh.GetShapeToMesh()
1810 return self.smeshpyD.Evaluate(self.mesh, geom)
1813 def Compute(self, geom=0, discardModifs=False, refresh=False):
1815 Compute the mesh and return the status of the computation
1818 geom: geomtrical shape on which mesh data should be computed
1819 discardModifs: if True and the mesh has been edited since
1820 a last total re-compute and that may prevent successful partial re-compute,
1821 then the mesh is cleaned before Compute()
1822 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1828 if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1830 geom = self.mesh.GetShapeToMesh()
1835 if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1837 ok = self.smeshpyD.Compute(self.mesh, geom)
1838 except SALOME.SALOME_Exception as ex:
1839 print("Mesh computation failed, exception caught:")
1840 print(" ", ex.details.text)
1843 print("Mesh computation failed, exception caught:")
1844 traceback.print_exc()
1848 # Treat compute errors
1849 computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1851 for err in computeErrors:
1852 if self.mesh.HasShapeToMesh():
1853 shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1855 stdErrors = ["OK", #COMPERR_OK
1856 "Invalid input mesh", #COMPERR_BAD_INPUT_MESH
1857 "std::exception", #COMPERR_STD_EXCEPTION
1858 "OCC exception", #COMPERR_OCC_EXCEPTION
1859 "..", #COMPERR_SLM_EXCEPTION
1860 "Unknown exception", #COMPERR_EXCEPTION
1861 "Memory allocation problem", #COMPERR_MEMORY_PB
1862 "Algorithm failed", #COMPERR_ALGO_FAILED
1863 "Unexpected geometry", #COMPERR_BAD_SHAPE
1864 "Warning", #COMPERR_WARNING
1865 "Computation cancelled",#COMPERR_CANCELED
1866 "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1868 if err.code < len(stdErrors): errText = stdErrors[err.code]
1870 errText = "code %s" % -err.code
1871 if errText: errText += ". "
1872 errText += err.comment
1873 if allReasons: allReasons += "\n"
1875 allReasons += '- "%s"%s - %s' %(err.algoName, shapeText, errText)
1877 allReasons += '- "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1881 errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1883 if err.isGlobalAlgo:
1891 reason = '%s %sD algorithm is missing' % (glob, dim)
1892 elif err.state == HYP_MISSING:
1893 reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1894 % (glob, dim, name, dim))
1895 elif err.state == HYP_NOTCONFORM:
1896 reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1897 elif err.state == HYP_BAD_PARAMETER:
1898 reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1899 % ( glob, dim, name ))
1900 elif err.state == HYP_BAD_GEOMETRY:
1901 reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1902 'geometry' % ( glob, dim, name ))
1903 elif err.state == HYP_HIDDEN_ALGO:
1904 reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1905 'algorithm of upper dimension generating %sD mesh'
1906 % ( glob, dim, name, glob, dim ))
1908 reason = ("For unknown reason. "
1909 "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1911 if allReasons: allReasons += "\n"
1912 allReasons += "- " + reason
1914 if not ok or allReasons != "":
1915 msg = '"' + GetName(self.mesh) + '"'
1916 if ok: msg += " has been computed with warnings"
1917 else: msg += " has not been computed"
1918 if allReasons != "": msg += ":"
1923 if salome.sg.hasDesktop():
1924 if not isinstance( refresh, list): # not a call from subMesh.Compute()
1925 if refresh: salome.sg.updateObjBrowser()
1929 def GetComputeErrors(self, shape=0 ):
1931 Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1935 shape = self.mesh.GetShapeToMesh()
1936 return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1938 def GetSubShapeName(self, subShapeID ):
1940 Return a name of a sub-shape by its ID.
1941 Possible variants (for *subShapeID* == 3):
1943 - **"Face_12"** - published sub-shape
1944 - **FACE #3** - not published sub-shape
1945 - **sub-shape #3** - invalid sub-shape ID
1946 - **#3** - error in this function
1949 subShapeID: a unique ID of a sub-shape
1952 a string describing the sub-shape
1956 if not self.mesh.HasShapeToMesh():
1960 mainIOR = salome.orb.object_to_string( self.GetShape() )
1962 mainSO = s.FindObjectIOR(mainIOR)
1965 shapeText = '"%s"' % mainSO.GetName()
1966 subIt = s.NewChildIterator(mainSO)
1968 subSO = subIt.Value()
1970 obj = subSO.GetObject()
1971 if not obj: continue
1972 go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
1975 ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
1978 if ids == subShapeID:
1979 shapeText = '"%s"' % subSO.GetName()
1982 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
1984 shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
1986 shapeText = 'sub-shape #%s' % (subShapeID)
1988 shapeText = "#%s" % (subShapeID)
1991 def GetFailedShapes(self, publish=False):
1993 Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
1994 error of an algorithm
1997 publish: if *True*, the returned groups will be published in the study
2000 a list of GEOM groups each named after a failed algorithm
2005 computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
2006 for err in computeErrors:
2007 shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
2008 if not shape: continue
2009 if err.algoName in algo2shapes:
2010 algo2shapes[ err.algoName ].append( shape )
2012 algo2shapes[ err.algoName ] = [ shape ]
2016 for algoName, shapes in list(algo2shapes.items()):
2018 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
2019 otherTypeShapes = []
2021 group = self.geompyD.CreateGroup( self.geom, groupType )
2022 for shape in shapes:
2023 if shape.GetShapeType() == shapes[0].GetShapeType():
2024 sameTypeShapes.append( shape )
2026 otherTypeShapes.append( shape )
2027 self.geompyD.UnionList( group, sameTypeShapes )
2029 group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
2031 group.SetName( algoName )
2032 groups.append( group )
2033 shapes = otherTypeShapes
2036 for group in groups:
2037 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
2040 def GetMeshOrder(self):
2042 Return sub-mesh objects list in meshing order
2045 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2048 return self.mesh.GetMeshOrder()
2050 def SetMeshOrder(self, submeshes):
2052 Set order in which concurrent sub-meshes should be meshed
2055 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2058 return self.mesh.SetMeshOrder(submeshes)
2060 def Clear(self, refresh=False):
2062 Remove all nodes and elements generated on geometry. Imported elements remain.
2065 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2069 if ( salome.sg.hasDesktop() ):
2070 if refresh: salome.sg.updateObjBrowser()
2072 def ClearSubMesh(self, geomId, refresh=False):
2074 Remove all nodes and elements of indicated shape
2077 geomId: the ID of a sub-shape to remove elements on
2078 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2081 self.mesh.ClearSubMesh(geomId)
2082 if salome.sg.hasDesktop():
2083 if refresh: salome.sg.updateObjBrowser()
2085 def AutomaticTetrahedralization(self, fineness=0):
2087 Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
2090 fineness: [0.0,1.0] defines mesh fineness
2096 dim = self.MeshDimension()
2098 self.RemoveGlobalHypotheses()
2099 self.Segment().AutomaticLength(fineness)
2101 self.Triangle().LengthFromEdges()
2106 return self.Compute()
2108 def AutomaticHexahedralization(self, fineness=0):
2110 Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2113 fineness: [0.0, 1.0] defines mesh fineness
2119 dim = self.MeshDimension()
2120 # assign the hypotheses
2121 self.RemoveGlobalHypotheses()
2122 self.Segment().AutomaticLength(fineness)
2129 return self.Compute()
2131 def AddHypothesis(self, hyp, geom=0):
2136 hyp: a hypothesis to assign
2137 geom: a subhape of mesh geometry
2140 :class:`SMESH.Hypothesis_Status`
2143 if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2144 hyp, geom = geom, hyp
2145 if isinstance( hyp, Mesh_Algorithm ):
2146 hyp = hyp.GetAlgorithm()
2151 geom = self.mesh.GetShapeToMesh()
2154 if self.mesh.HasShapeToMesh():
2155 hyp_type = hyp.GetName()
2156 lib_name = hyp.GetLibName()
2157 # checkAll = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2158 # if checkAll and geom:
2159 # checkAll = geom.GetType() == 37
2161 isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2163 AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2164 status = self.mesh.AddHypothesis(geom, hyp)
2166 status = HYP_BAD_GEOMETRY, ""
2167 hyp_name = GetName( hyp )
2170 geom_name = geom.GetName()
2171 isAlgo = hyp._narrow( SMESH_Algo )
2172 TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2175 def IsUsedHypothesis(self, hyp, geom):
2177 Return True if an algorithm or hypothesis is assigned to a given shape
2180 hyp: an algorithm or hypothesis to check
2181 geom: a subhape of mesh geometry
2187 if not hyp: # or not geom
2189 if isinstance( hyp, Mesh_Algorithm ):
2190 hyp = hyp.GetAlgorithm()
2192 hyps = self.GetHypothesisList(geom)
2194 if h.GetId() == hyp.GetId():
2198 def RemoveHypothesis(self, hyp, geom=0):
2200 Unassign a hypothesis
2203 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2204 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2207 :class:`SMESH.Hypothesis_Status`
2212 if isinstance( hyp, Mesh_Algorithm ):
2213 hyp = hyp.GetAlgorithm()
2219 if self.IsUsedHypothesis( hyp, shape ):
2220 return self.mesh.RemoveHypothesis( shape, hyp )
2221 hypName = GetName( hyp )
2222 geoName = GetName( shape )
2223 print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2226 def GetHypothesisList(self, geom):
2228 Get the list of hypotheses added on a geometry
2231 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2234 the sequence of :class:`SMESH.SMESH_Hypothesis`
2237 return self.mesh.GetHypothesisList( geom )
2239 def RemoveGlobalHypotheses(self):
2241 Remove all global hypotheses
2244 current_hyps = self.mesh.GetHypothesisList( self.geom )
2245 for hyp in current_hyps:
2246 self.mesh.RemoveHypothesis( self.geom, hyp )
2249 def ExportMED(self, *args, **kwargs):
2251 Export the mesh in a file in MED format
2252 allowing to overwrite the file if it exists or add the exported data to its contents
2255 fileName: is the file name
2256 auto_groups (boolean): parameter for creating/not creating
2257 the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2258 the typical use is auto_groups=False.
2259 minor (int): define the minor version (y, where version is x.y.z) of MED file format.
2260 The minor must be between 0 and the current minor version of MED file library.
2261 If minor is equal to -1, the minor version is not changed (default).
2262 The major version (x, where version is x.y.z) cannot be changed.
2263 overwrite (boolean): parameter for overwriting/not overwriting the file
2264 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2265 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2267 - 1D if all mesh nodes lie on OX coordinate axis, or
2268 - 2D if all mesh nodes lie on XOY coordinate plane, or
2269 - 3D in the rest cases.
2271 If *autoDimension* is *False*, the space dimension is always 3.
2272 fields: list of GEOM fields defined on the shape to mesh.
2273 geomAssocFields: each character of this string means a need to export a
2274 corresponding field; correspondence between fields and characters
2277 - 'v' stands for "_vertices_" field;
2278 - 'e' stands for "_edges_" field;
2279 - 'f' stands for "_faces_" field;
2280 - 's' stands for "_solids_" field.
2282 zTolerance (float): tolerance in Z direction. If Z coordinate of a node is
2283 close to zero within a given tolerance, the coordinate is set to zero.
2284 If *ZTolerance* is negative (default), the node coordinates are kept as is.
2286 # process positional arguments
2287 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2289 auto_groups = args[1] if len(args) > 1 else False
2290 minor = args[2] if len(args) > 2 else -1
2291 overwrite = args[3] if len(args) > 3 else True
2292 meshPart = args[4] if len(args) > 4 else None
2293 autoDimension = args[5] if len(args) > 5 else True
2294 fields = args[6] if len(args) > 6 else []
2295 geomAssocFields = args[7] if len(args) > 7 else ''
2296 z_tolerance = args[8] if len(args) > 8 else -1.
2297 # process keywords arguments
2298 auto_groups = kwargs.get("auto_groups", auto_groups)
2299 minor = kwargs.get("minor", minor)
2300 overwrite = kwargs.get("overwrite", overwrite)
2301 meshPart = kwargs.get("meshPart", meshPart)
2302 autoDimension = kwargs.get("autoDimension", autoDimension)
2303 fields = kwargs.get("fields", fields)
2304 geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2305 z_tolerance = kwargs.get("zTolerance", z_tolerance)
2307 # invoke engine's function
2308 if meshPart or fields or geomAssocFields or z_tolerance > 0:
2309 unRegister = genObjUnRegister()
2310 if isinstance( meshPart, list ):
2311 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2312 unRegister.set( meshPart )
2314 z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
2315 self.mesh.SetParameters(Parameters)
2317 self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
2318 fields, geomAssocFields, z_tolerance)
2320 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2322 def ExportSAUV(self, f, auto_groups=0):
2324 Export the mesh in a file in SAUV format
2329 auto_groups: boolean parameter for creating/not creating
2330 the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2331 the typical use is auto_groups=False.
2334 self.mesh.ExportSAUV(f, auto_groups)
2336 def ExportDAT(self, f, meshPart=None):
2338 Export the mesh in a file in DAT format
2342 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2346 unRegister = genObjUnRegister()
2347 if isinstance( meshPart, list ):
2348 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2349 unRegister.set( meshPart )
2350 self.mesh.ExportPartToDAT( meshPart, f )
2352 self.mesh.ExportDAT(f)
2354 def ExportUNV(self, f, meshPart=None):
2356 Export the mesh in a file in UNV format
2360 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2364 unRegister = genObjUnRegister()
2365 if isinstance( meshPart, list ):
2366 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2367 unRegister.set( meshPart )
2368 self.mesh.ExportPartToUNV( meshPart, f )
2370 self.mesh.ExportUNV(f)
2372 def ExportSTL(self, f, ascii=1, meshPart=None):
2374 Export the mesh in a file in STL format
2378 ascii: defines the file encoding
2379 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2383 unRegister = genObjUnRegister()
2384 if isinstance( meshPart, list ):
2385 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2386 unRegister.set( meshPart )
2387 self.mesh.ExportPartToSTL( meshPart, f, ascii )
2389 self.mesh.ExportSTL(f, ascii)
2391 def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2393 Export the mesh in a file in CGNS format
2397 overwrite: boolean parameter for overwriting/not overwriting the file
2398 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2399 groupElemsByType: if True all elements of same entity type are exported at ones,
2400 else elements are exported in order of their IDs which can cause creation
2401 of multiple cgns sections
2404 unRegister = genObjUnRegister()
2405 if isinstance( meshPart, list ):
2406 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2407 unRegister.set( meshPart )
2408 if isinstance( meshPart, Mesh ):
2409 meshPart = meshPart.mesh
2411 meshPart = self.mesh
2412 self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2414 def ExportGMF(self, f, meshPart=None):
2416 Export the mesh in a file in GMF format.
2417 GMF files must have .mesh extension for the ASCII format and .meshb for
2418 the bynary format. Other extensions are not allowed.
2422 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2425 unRegister = genObjUnRegister()
2426 if isinstance( meshPart, list ):
2427 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2428 unRegister.set( meshPart )
2429 if isinstance( meshPart, Mesh ):
2430 meshPart = meshPart.mesh
2432 meshPart = self.mesh
2433 self.mesh.ExportGMF(meshPart, f, True)
2435 def ExportToMED(self, *args, **kwargs):
2437 Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2438 Export the mesh in a file in MED format
2439 allowing to overwrite the file if it exists or add the exported data to its contents
2442 fileName: the file name
2443 opt (boolean): parameter for creating/not creating
2444 the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2445 overwrite: boolean parameter for overwriting/not overwriting the file
2446 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2448 - 1D if all mesh nodes lie on OX coordinate axis, or
2449 - 2D if all mesh nodes lie on XOY coordinate plane, or
2450 - 3D in the rest cases.
2452 If **autoDimension** is *False*, the space dimension is always 3.
2455 print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2456 # process positional arguments
2457 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2459 auto_groups = args[1] if len(args) > 1 else False
2460 overwrite = args[2] if len(args) > 2 else True
2461 autoDimension = args[3] if len(args) > 3 else True
2462 # process keywords arguments
2463 auto_groups = kwargs.get("opt", auto_groups) # old keyword name
2464 auto_groups = kwargs.get("auto_groups", auto_groups) # new keyword name
2465 overwrite = kwargs.get("overwrite", overwrite)
2466 autoDimension = kwargs.get("autoDimension", autoDimension)
2468 # invoke engine's function
2469 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2471 def ExportToMEDX(self, *args, **kwargs):
2473 Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2474 Export the mesh in a file in MED format
2477 fileName: the file name
2478 opt (boolean): parameter for creating/not creating
2479 the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2480 overwrite: boolean parameter for overwriting/not overwriting the file
2481 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2483 - 1D if all mesh nodes lie on OX coordinate axis, or
2484 - 2D if all mesh nodes lie on XOY coordinate plane, or
2485 - 3D in the rest cases.
2487 If **autoDimension** is *False*, the space dimension is always 3.
2490 print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2491 # process positional arguments
2492 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2494 auto_groups = args[1] if len(args) > 1 else False
2495 overwrite = args[2] if len(args) > 2 else True
2496 autoDimension = args[3] if len(args) > 3 else True
2497 # process keywords arguments
2498 auto_groups = kwargs.get("auto_groups", auto_groups)
2499 overwrite = kwargs.get("overwrite", overwrite)
2500 autoDimension = kwargs.get("autoDimension", autoDimension)
2502 # invoke engine's function
2503 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2505 # Operations with groups:
2506 # ----------------------
2507 def CreateEmptyGroup(self, elementType, name):
2509 Create an empty standalone mesh group
2512 elementType: the :class:`type <SMESH.ElementType>` of elements in the group;
2513 either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2514 name: the name of the mesh group
2517 :class:`SMESH.SMESH_Group`
2520 return self.mesh.CreateGroup(elementType, name)
2522 def Group(self, grp, name=""):
2524 Create a mesh group based on the geometric object *grp*
2525 and give it a *name*.
2526 If *name* is not defined the name of the geometric group is used
2529 Works like :meth:`GroupOnGeom`.
2532 grp: a geometric group, a vertex, an edge, a face or a solid
2533 name: the name of the mesh group
2536 :class:`SMESH.SMESH_GroupOnGeom`
2539 return self.GroupOnGeom(grp, name)
2541 def GroupOnGeom(self, grp, name="", typ=None):
2543 Create a mesh group based on the geometrical object *grp*
2544 and give it a *name*.
2545 if *name* is not defined the name of the geometric group is used
2548 grp: a geometrical group, a vertex, an edge, a face or a solid
2549 name: the name of the mesh group
2550 typ: the type of elements in the group; either of
2551 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2552 automatically detected by the type of the geometry
2555 :class:`SMESH.SMESH_GroupOnGeom`
2558 AssureGeomPublished( self, grp, name )
2560 name = grp.GetName()
2562 typ = self._groupTypeFromShape( grp )
2563 return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2565 def _groupTypeFromShape( self, shape ):
2567 Pivate method to get a type of group on geometry
2569 tgeo = str(shape.GetShapeType())
2570 if tgeo == "VERTEX":
2572 elif tgeo == "EDGE":
2574 elif tgeo == "FACE" or tgeo == "SHELL":
2576 elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2578 elif tgeo == "COMPOUND":
2579 sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2581 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2582 return self._groupTypeFromShape( sub[0] )
2584 raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2587 def GroupOnFilter(self, typ, name, filter):
2589 Create a mesh group with given *name* based on the *filter*.
2590 It is a special type of group dynamically updating it's contents during
2594 typ: the type of elements in the group; either of
2595 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2596 name: the name of the mesh group
2597 filter (SMESH.Filter): the filter defining group contents
2600 :class:`SMESH.SMESH_GroupOnFilter`
2603 return self.mesh.CreateGroupFromFilter(typ, name, filter)
2605 def MakeGroupByIds(self, groupName, elementType, elemIDs):
2607 Create a mesh group by the given ids of elements
2610 groupName: the name of the mesh group
2611 elementType: the type of elements in the group; either of
2612 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2613 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2616 :class:`SMESH.SMESH_Group`
2619 group = self.mesh.CreateGroup(elementType, groupName)
2620 if isinstance( elemIDs, Mesh ):
2621 elemIDs = elemIDs.GetMesh()
2622 if hasattr( elemIDs, "GetIDs" ):
2623 if hasattr( elemIDs, "SetMesh" ):
2624 elemIDs.SetMesh( self.GetMesh() )
2625 group.AddFrom( elemIDs )
2633 CritType=FT_Undefined,
2636 UnaryOp=FT_Undefined,
2639 Create a mesh group by the given conditions
2642 groupName: the name of the mesh group
2643 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2644 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2645 Note that the items starting from FT_LessThan are not suitable for CritType.
2646 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2647 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2648 UnaryOp (SMESH.FunctorType): SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2649 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2650 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2653 :class:`SMESH.SMESH_GroupOnFilter`
2656 aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2657 group = self.MakeGroupByCriterion(groupName, aCriterion)
2660 def MakeGroupByCriterion(self, groupName, Criterion):
2662 Create a mesh group by the given criterion
2665 groupName: the name of the mesh group
2666 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2669 :class:`SMESH.SMESH_GroupOnFilter`
2672 :meth:`smeshBuilder.GetCriterion`
2675 return self.MakeGroupByCriteria( groupName, [Criterion] )
2677 def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2679 Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2682 groupName: the name of the mesh group
2683 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2684 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2687 :class:`SMESH.SMESH_GroupOnFilter`
2690 :meth:`smeshBuilder.GetCriterion`
2693 aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2694 group = self.MakeGroupByFilter(groupName, aFilter)
2697 def MakeGroupByFilter(self, groupName, theFilter):
2699 Create a mesh group by the given filter
2702 groupName (string): the name of the mesh group
2703 theFilter (SMESH.Filter): the filter
2706 :class:`SMESH.SMESH_GroupOnFilter`
2709 :meth:`smeshBuilder.GetFilter`
2712 #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2713 #theFilter.SetMesh( self.mesh )
2714 #group.AddFrom( theFilter )
2715 group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2718 def RemoveGroup(self, group):
2723 group (SMESH.SMESH_GroupBase): group to remove
2726 self.mesh.RemoveGroup(group)
2728 def RemoveGroupWithContents(self, group):
2730 Remove a group with its contents
2733 group (SMESH.SMESH_GroupBase): group to remove
2736 self.mesh.RemoveGroupWithContents(group)
2738 def GetGroups(self, elemType = SMESH.ALL):
2740 Get the list of groups existing in the mesh in the order of creation
2741 (starting from the oldest one)
2744 elemType (SMESH.ElementType): type of elements the groups contain;
2745 by default groups of elements of all types are returned
2748 a list of :class:`SMESH.SMESH_GroupBase`
2751 groups = self.mesh.GetGroups()
2752 if elemType == SMESH.ALL:
2756 if g.GetType() == elemType:
2757 typedGroups.append( g )
2764 Get the number of groups existing in the mesh
2767 the quantity of groups as an integer value
2770 return self.mesh.NbGroups()
2772 def GetGroupNames(self):
2774 Get the list of names of groups existing in the mesh
2780 groups = self.GetGroups()
2782 for group in groups:
2783 names.append(group.GetName())
2786 def GetGroupByName(self, name, elemType = None):
2788 Find groups by name and type
2791 name (string): name of the group of interest
2792 elemType (SMESH.ElementType): type of elements the groups contain;
2793 by default one group of any type is returned;
2794 if elemType == SMESH.ALL then all groups of any type are returned
2797 a list of :class:`SMESH.SMESH_GroupBase`
2801 for group in self.GetGroups():
2802 if group.GetName() == name:
2803 if elemType is None:
2805 if ( elemType == SMESH.ALL or
2806 group.GetType() == elemType ):
2807 groups.append( group )
2810 def UnionGroups(self, group1, group2, name):
2812 Produce a union of two groups.
2813 A new group is created. All mesh elements that are
2814 present in the initial groups are added to the new one
2817 group1 (SMESH.SMESH_GroupBase): a group
2818 group2 (SMESH.SMESH_GroupBase): another group
2821 instance of :class:`SMESH.SMESH_Group`
2824 return self.mesh.UnionGroups(group1, group2, name)
2826 def UnionListOfGroups(self, groups, name):
2828 Produce a union list of groups.
2829 New group is created. All mesh elements that are present in
2830 initial groups are added to the new one
2833 groups: list of :class:`SMESH.SMESH_GroupBase`
2836 instance of :class:`SMESH.SMESH_Group`
2838 return self.mesh.UnionListOfGroups(groups, name)
2840 def IntersectGroups(self, group1, group2, name):
2842 Prodice an intersection of two groups.
2843 A new group is created. All mesh elements that are common
2844 for the two initial groups are added to the new one.
2847 group1 (SMESH.SMESH_GroupBase): a group
2848 group2 (SMESH.SMESH_GroupBase): another group
2851 instance of :class:`SMESH.SMESH_Group`
2854 return self.mesh.IntersectGroups(group1, group2, name)
2856 def IntersectListOfGroups(self, groups, name):
2858 Produce an intersection of groups.
2859 New group is created. All mesh elements that are present in all
2860 initial groups simultaneously are added to the new one
2863 groups: a list of :class:`SMESH.SMESH_GroupBase`
2866 instance of :class:`SMESH.SMESH_Group`
2868 return self.mesh.IntersectListOfGroups(groups, name)
2870 def CutGroups(self, main_group, tool_group, name):
2872 Produce a cut of two groups.
2873 A new group is created. All mesh elements that are present in
2874 the main group but are not present in the tool group are added to the new one
2877 main_group (SMESH.SMESH_GroupBase): a group to cut from
2878 tool_group (SMESH.SMESH_GroupBase): a group to cut by
2881 an instance of :class:`SMESH.SMESH_Group`
2884 return self.mesh.CutGroups(main_group, tool_group, name)
2886 def CutListOfGroups(self, main_groups, tool_groups, name):
2888 Produce a cut of groups.
2889 A new group is created. All mesh elements that are present in main groups
2890 but do not present in tool groups are added to the new one
2893 main_group: groups to cut from (list of :class:`SMESH.SMESH_GroupBase`)
2894 tool_group: groups to cut by (list of :class:`SMESH.SMESH_GroupBase`)
2897 an instance of :class:`SMESH.SMESH_Group`
2900 return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2902 def CreateDimGroup(self, groups, elemType, name,
2903 nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2905 Create a standalone group of entities basing on nodes of other groups.