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,
738 Concatenate the given meshes into one mesh. All groups of input meshes will be
739 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
750 an instance of class :class:`Mesh`
753 if not meshes: return None
754 for i,m in enumerate(meshes):
755 if isinstance(m, Mesh):
756 meshes[i] = m.GetMesh()
757 mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
758 meshes[0].SetParameters(Parameters)
760 aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
761 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
763 aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
764 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
765 aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
768 def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
770 Create a mesh by copying a part of another mesh.
773 meshPart: a part of mesh to copy, either
774 :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
775 To copy nodes or elements not forming any mesh object,
776 pass result of :meth:`Mesh.GetIDSource` as *meshPart*
777 meshName: a name of the new mesh
778 toCopyGroups: to create in the new mesh groups the copied elements belongs to
779 toKeepIDs: to preserve order of the copied elements or not
782 an instance of class :class:`Mesh`
785 if (isinstance( meshPart, Mesh )):
786 meshPart = meshPart.GetMesh()
787 mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
788 return Mesh(self, self.geompyD, mesh)
790 def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
792 Return IDs of sub-shapes
795 theMainObject (GEOM.GEOM_Object): a shape
796 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
798 the list of integer values
801 return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
803 def GetPattern(self):
805 Create a pattern mapper.
808 an instance of :class:`SMESH.SMESH_Pattern`
810 :ref:`Example of Patterns usage <tui_pattern_mapping>`
813 return SMESH._objref_SMESH_Gen.GetPattern(self)
815 def SetBoundaryBoxSegmentation(self, nbSegments):
817 Set number of segments per diagonal of boundary box of geometry, by which
818 default segment length of appropriate 1D hypotheses is defined in GUI.
822 SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
824 # Filtering. Auxiliary functions:
825 # ------------------------------
827 def GetEmptyCriterion(self):
829 Create an empty criterion
832 :class:`SMESH.Filter.Criterion`
835 Type = self.EnumToLong(FT_Undefined)
836 Compare = self.EnumToLong(FT_Undefined)
840 UnaryOp = self.EnumToLong(FT_Undefined)
841 BinaryOp = self.EnumToLong(FT_Undefined)
844 Precision = -1 ##@1e-07
845 return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
846 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
848 def GetCriterion(self,elementType,
850 Compare = FT_EqualTo,
852 UnaryOp=FT_Undefined,
853 BinaryOp=FT_Undefined,
856 Create a criterion by the given parameters
857 Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
860 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
861 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
862 Note that the items starting from FT_LessThan are not suitable for *CritType*.
863 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
864 Threshold: the threshold value (range of ids as string, shape, numeric)
865 UnaryOp: SMESH.FT_LogicalNOT or SMESH.FT_Undefined
866 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
868 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
869 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
872 :class:`SMESH.Filter.Criterion`
874 Example: :ref:`combining_filters`
877 if not CritType in SMESH.FunctorType._items:
878 raise TypeError("CritType should be of SMESH.FunctorType")
879 aCriterion = self.GetEmptyCriterion()
880 aCriterion.TypeOfElement = elementType
881 aCriterion.Type = self.EnumToLong(CritType)
882 aCriterion.Tolerance = Tolerance
884 aThreshold = Threshold
886 if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
887 aCriterion.Compare = self.EnumToLong(Compare)
888 elif Compare == "=" or Compare == "==":
889 aCriterion.Compare = self.EnumToLong(FT_EqualTo)
891 aCriterion.Compare = self.EnumToLong(FT_LessThan)
893 aCriterion.Compare = self.EnumToLong(FT_MoreThan)
894 elif Compare != FT_Undefined:
895 aCriterion.Compare = self.EnumToLong(FT_EqualTo)
898 if CritType in [FT_BelongToGeom, FT_BelongToPlane, FT_BelongToGenSurface,
899 FT_BelongToCylinder, FT_LyingOnGeom]:
900 # Check that Threshold is GEOM object
901 if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
902 aCriterion.ThresholdStr = GetName(aThreshold)
903 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
904 if not aCriterion.ThresholdID:
905 name = aCriterion.ThresholdStr
907 name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
908 aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
909 # or a name of GEOM object
910 elif isinstance( aThreshold, str ):
911 aCriterion.ThresholdStr = aThreshold
913 raise TypeError("The Threshold should be a shape.")
914 if isinstance(UnaryOp,float):
915 aCriterion.Tolerance = UnaryOp
916 UnaryOp = FT_Undefined
918 elif CritType == FT_BelongToMeshGroup:
919 # Check that Threshold is a group
920 if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
921 if aThreshold.GetType() != elementType:
922 raise ValueError("Group type mismatches Element type")
923 aCriterion.ThresholdStr = aThreshold.GetName()
924 aCriterion.ThresholdID = salome.orb.object_to_string( aThreshold )
925 study = salome.myStudy
927 so = study.FindObjectIOR( aCriterion.ThresholdID )
931 aCriterion.ThresholdID = entry
933 raise TypeError("The Threshold should be a Mesh Group")
934 elif CritType == FT_RangeOfIds:
935 # Check that Threshold is string
936 if isinstance(aThreshold, str):
937 aCriterion.ThresholdStr = aThreshold
939 raise TypeError("The Threshold should be a string.")
940 elif CritType == FT_CoplanarFaces:
941 # Check the Threshold
942 if isinstance(aThreshold, int):
943 aCriterion.ThresholdID = str(aThreshold)
944 elif isinstance(aThreshold, str):
947 raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
948 aCriterion.ThresholdID = aThreshold
950 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
951 elif CritType == FT_ConnectedElements:
952 # Check the Threshold
953 if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
954 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
955 if not aCriterion.ThresholdID:
956 name = aThreshold.GetName()
958 name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
959 aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
960 elif isinstance(aThreshold, int): # node id
961 aCriterion.Threshold = aThreshold
962 elif isinstance(aThreshold, list): # 3 point coordinates
963 if len( aThreshold ) < 3:
964 raise ValueError("too few point coordinates, must be 3")
965 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
966 elif isinstance(aThreshold, str):
967 if aThreshold.isdigit():
968 aCriterion.Threshold = aThreshold # node id
970 aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
972 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
973 "or a list of point coordinates and not '%s'"%aThreshold)
974 elif CritType == FT_ElemGeomType:
975 # Check the Threshold
977 aCriterion.Threshold = self.EnumToLong(aThreshold)
978 assert( aThreshold in SMESH.GeometryType._items )
980 if isinstance(aThreshold, int):
981 aCriterion.Threshold = aThreshold
983 raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
986 elif CritType == FT_EntityType:
987 # Check the Threshold
989 aCriterion.Threshold = self.EnumToLong(aThreshold)
990 assert( aThreshold in SMESH.EntityType._items )
992 if isinstance(aThreshold, int):
993 aCriterion.Threshold = aThreshold
995 raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
999 elif CritType == FT_GroupColor:
1000 # Check the Threshold
1002 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
1004 raise TypeError("The threshold value should be of SALOMEDS.Color type")
1006 elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
1007 FT_LinearOrQuadratic, FT_BadOrientedVolume,
1008 FT_BareBorderFace, FT_BareBorderVolume,
1009 FT_OverConstrainedFace, FT_OverConstrainedVolume,
1010 FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
1011 # At this point the Threshold is unnecessary
1012 if aThreshold == FT_LogicalNOT:
1013 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1014 elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1015 aCriterion.BinaryOp = aThreshold
1019 aThreshold = float(aThreshold)
1020 aCriterion.Threshold = aThreshold
1022 raise TypeError("The Threshold should be a number.")
1025 if Threshold == FT_LogicalNOT or UnaryOp == FT_LogicalNOT:
1026 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1028 if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1029 aCriterion.BinaryOp = self.EnumToLong(Threshold)
1031 if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1032 aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1034 if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1035 aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1039 def GetFilter(self,elementType,
1040 CritType=FT_Undefined,
1043 UnaryOp=FT_Undefined,
1047 Create a filter with the given parameters
1050 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1051 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1052 Note that the items starting from FT_LessThan are not suitable for CritType.
1053 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1054 Threshold: the threshold value (range of ids as string, shape, numeric)
1055 UnaryOp: SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1056 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1057 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1058 mesh: the mesh to initialize the filter with
1061 :class:`SMESH.Filter`
1064 See :doc:`Filters usage examples <tui_filters>`
1067 aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1068 aFilterMgr = self.CreateFilterManager()
1069 aFilter = aFilterMgr.CreateFilter()
1071 aCriteria.append(aCriterion)
1072 aFilter.SetCriteria(aCriteria)
1074 if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1075 else : aFilter.SetMesh( mesh )
1076 aFilterMgr.UnRegister()
1079 def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1081 Create a filter from criteria
1084 criteria: a list of :class:`SMESH.Filter.Criterion`
1085 binOp: binary operator used when binary operator of criteria is undefined
1088 :class:`SMESH.Filter`
1091 See :doc:`Filters usage examples <tui_filters>`
1094 for i in range( len( criteria ) - 1 ):
1095 if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1096 criteria[i].BinaryOp = self.EnumToLong( binOp )
1097 aFilterMgr = self.CreateFilterManager()
1098 aFilter = aFilterMgr.CreateFilter()
1099 aFilter.SetCriteria(criteria)
1100 aFilterMgr.UnRegister()
1103 def GetFunctor(self,theCriterion):
1105 Create a numerical functor by its type
1108 theCriterion (SMESH.FunctorType): functor type.
1109 Note that not all items correspond to numerical functors.
1112 :class:`SMESH.NumericalFunctor`
1115 if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1117 aFilterMgr = self.CreateFilterManager()
1119 if theCriterion == FT_AspectRatio:
1120 functor = aFilterMgr.CreateAspectRatio()
1121 elif theCriterion == FT_AspectRatio3D:
1122 functor = aFilterMgr.CreateAspectRatio3D()
1123 elif theCriterion == FT_Warping:
1124 functor = aFilterMgr.CreateWarping()
1125 elif theCriterion == FT_MinimumAngle:
1126 functor = aFilterMgr.CreateMinimumAngle()
1127 elif theCriterion == FT_Taper:
1128 functor = aFilterMgr.CreateTaper()
1129 elif theCriterion == FT_Skew:
1130 functor = aFilterMgr.CreateSkew()
1131 elif theCriterion == FT_Area:
1132 functor = aFilterMgr.CreateArea()
1133 elif theCriterion == FT_Volume3D:
1134 functor = aFilterMgr.CreateVolume3D()
1135 elif theCriterion == FT_MaxElementLength2D:
1136 functor = aFilterMgr.CreateMaxElementLength2D()
1137 elif theCriterion == FT_MaxElementLength3D:
1138 functor = aFilterMgr.CreateMaxElementLength3D()
1139 elif theCriterion == FT_MultiConnection:
1140 functor = aFilterMgr.CreateMultiConnection()
1141 elif theCriterion == FT_MultiConnection2D:
1142 functor = aFilterMgr.CreateMultiConnection2D()
1143 elif theCriterion == FT_Length:
1144 functor = aFilterMgr.CreateLength()
1145 elif theCriterion == FT_Length2D:
1146 functor = aFilterMgr.CreateLength2D()
1147 elif theCriterion == FT_Deflection2D:
1148 functor = aFilterMgr.CreateDeflection2D()
1149 elif theCriterion == FT_NodeConnectivityNumber:
1150 functor = aFilterMgr.CreateNodeConnectivityNumber()
1151 elif theCriterion == FT_BallDiameter:
1152 functor = aFilterMgr.CreateBallDiameter()
1154 print("Error: given parameter is not numerical functor type.")
1155 aFilterMgr.UnRegister()
1158 def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1163 theHType (string): mesh hypothesis type
1164 theLibName (string): mesh plug-in library name
1167 created hypothesis instance
1169 hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1171 if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1174 # wrap hypothesis methods
1175 for meth_name in dir( hyp.__class__ ):
1176 if not meth_name.startswith("Get") and \
1177 not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1178 method = getattr ( hyp.__class__, meth_name )
1179 if callable(method):
1180 setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1184 def GetMeshInfo(self, obj):
1186 Get the mesh statistic.
1187 Use :meth:`smeshBuilder.EnumToLong` to get an integer from
1188 an item of :class:`SMESH.EntityType`.
1191 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1194 if isinstance( obj, Mesh ):
1197 if hasattr(obj, "GetMeshInfo"):
1198 values = obj.GetMeshInfo()
1199 for i in range(SMESH.Entity_Last._v):
1200 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1204 def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1206 Get minimum distance between two objects
1208 * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1209 * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1212 src1 (SMESH.SMESH_IDSource): first source object
1213 src2 (SMESH.SMESH_IDSource): second source object
1214 id1 (int): node/element id from the first source
1215 id2 (int): node/element id from the second (or first) source
1216 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1217 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1220 minimum distance value
1223 :meth:`GetMinDistance`
1226 result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1230 result = result.value
1233 def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1235 Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1237 * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1238 * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1241 src1 (SMESH.SMESH_IDSource): first source object
1242 src2 (SMESH.SMESH_IDSource): second source object
1243 id1 (int): node/element id from the first source
1244 id2 (int): node/element id from the second (or first) source
1245 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1246 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1249 :class:`SMESH.Measure` structure or None if input data is invalid
1254 if isinstance(src1, Mesh): src1 = src1.mesh
1255 if isinstance(src2, Mesh): src2 = src2.mesh
1256 if src2 is None and id2 != 0: src2 = src1
1257 if not hasattr(src1, "_narrow"): return None
1258 src1 = src1._narrow(SMESH.SMESH_IDSource)
1259 if not src1: return None
1260 unRegister = genObjUnRegister()
1263 e = m.GetMeshEditor()
1265 src1 = e.MakeIDSource([id1], SMESH.FACE)
1267 src1 = e.MakeIDSource([id1], SMESH.NODE)
1268 unRegister.set( src1 )
1270 if hasattr(src2, "_narrow"):
1271 src2 = src2._narrow(SMESH.SMESH_IDSource)
1272 if src2 and id2 != 0:
1274 e = m.GetMeshEditor()
1276 src2 = e.MakeIDSource([id2], SMESH.FACE)
1278 src2 = e.MakeIDSource([id2], SMESH.NODE)
1279 unRegister.set( src2 )
1282 aMeasurements = self.CreateMeasurements()
1283 unRegister.set( aMeasurements )
1284 result = aMeasurements.MinDistance(src1, src2)
1287 def BoundingBox(self, objects):
1289 Get bounding box of the specified object(s)
1292 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1295 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1298 :meth:`GetBoundingBox`
1301 result = self.GetBoundingBox(objects)
1305 result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1308 def GetBoundingBox(self, objects):
1310 Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1313 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1316 :class:`SMESH.Measure` structure
1322 if isinstance(objects, tuple):
1323 objects = list(objects)
1324 if not isinstance(objects, list):
1328 if isinstance(o, Mesh):
1329 srclist.append(o.mesh)
1330 elif hasattr(o, "_narrow"):
1331 src = o._narrow(SMESH.SMESH_IDSource)
1332 if src: srclist.append(src)
1335 aMeasurements = self.CreateMeasurements()
1336 result = aMeasurements.BoundingBox(srclist)
1337 aMeasurements.UnRegister()
1340 def GetLength(self, obj):
1342 Get sum of lengths of all 1D elements in the mesh object.
1345 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1348 sum of lengths of all 1D elements
1351 if isinstance(obj, Mesh): obj = obj.mesh
1352 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1353 aMeasurements = self.CreateMeasurements()
1354 value = aMeasurements.Length(obj)
1355 aMeasurements.UnRegister()
1358 def GetArea(self, obj):
1360 Get sum of areas of all 2D elements in the mesh object.
1363 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1366 sum of areas of all 2D elements
1369 if isinstance(obj, Mesh): obj = obj.mesh
1370 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1371 aMeasurements = self.CreateMeasurements()
1372 value = aMeasurements.Area(obj)
1373 aMeasurements.UnRegister()
1376 def GetVolume(self, obj):
1378 Get sum of volumes of all 3D elements in the mesh object.
1381 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1384 sum of volumes of all 3D elements
1387 if isinstance(obj, Mesh): obj = obj.mesh
1388 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1389 aMeasurements = self.CreateMeasurements()
1390 value = aMeasurements.Volume(obj)
1391 aMeasurements.UnRegister()
1394 def GetGravityCenter(self, obj):
1396 Get gravity center of all nodes of the mesh object.
1399 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1402 Three components of the gravity center (x,y,z)
1404 if isinstance(obj, Mesh): obj = obj.mesh
1405 if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1406 aMeasurements = self.CreateMeasurements()
1407 pointStruct = aMeasurements.GravityCenter(obj)
1408 aMeasurements.UnRegister()
1409 return pointStruct.x, pointStruct.y, pointStruct.z
1411 pass # end of class smeshBuilder
1414 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1415 """Registering the new proxy for SMESH.SMESH_Gen"""
1418 def New( instance=None, instanceGeom=None):
1420 Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1421 interface to create or load meshes.
1426 salome.salome_init()
1427 from salome.smesh import smeshBuilder
1428 smesh = smeshBuilder.New()
1431 instance: CORBA proxy of SMESH Engine. If None, the default Engine is used.
1432 instanceGeom: CORBA proxy of GEOM Engine. If None, the default Engine is used.
1434 :class:`smeshBuilder` instance
1439 if instance and isinstance( instance, SALOMEDS._objref_Study ):
1441 sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1446 smeshInst = smeshBuilder()
1447 assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1448 smeshInst.init_smesh(instanceGeom)
1452 # Public class: Mesh
1453 # ==================
1456 class Mesh(metaclass = MeshMeta):
1458 This class allows defining and managing a mesh.
1459 It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1460 It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1461 new nodes and elements and by changing the existing entities), to get information
1462 about a mesh and to export a mesh in different formats.
1469 def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1474 Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1475 sets the GUI name of this mesh to *name*.
1478 smeshpyD: an instance of smeshBuilder class
1479 geompyD: an instance of geomBuilder class
1480 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1481 name: Study name of the mesh
1484 self.smeshpyD = smeshpyD
1485 self.geompyD = geompyD
1490 if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1493 # publish geom of mesh (issue 0021122)
1494 if not self.geom.GetStudyEntry():
1498 geo_name = name + " shape"
1500 geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1501 geompyD.addToStudy( self.geom, geo_name )
1502 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1504 elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1507 self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1509 self.smeshpyD.SetName(self.mesh, name)
1511 self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1514 self.geom = self.mesh.GetShapeToMesh()
1516 self.editor = self.mesh.GetMeshEditor()
1517 self.functors = [None] * SMESH.FT_Undefined._v
1519 # set self to algoCreator's
1520 for attrName in dir(self):
1521 attr = getattr( self, attrName )
1522 if isinstance( attr, algoCreator ):
1523 setattr( self, attrName, attr.copy( self ))
1530 Destructor. Clean-up resources
1533 #self.mesh.UnRegister()
1537 def SetMesh(self, theMesh):
1539 Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1542 theMesh: a :class:`SMESH.SMESH_Mesh` object
1546 # do not call Register() as this prevents mesh servant deletion at closing study
1547 #if self.mesh: self.mesh.UnRegister()
1550 #self.mesh.Register()
1551 self.geom = self.mesh.GetShapeToMesh()
1556 Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1559 a :class:`SMESH.SMESH_Mesh` object
1566 Get the name of the mesh
1569 the name of the mesh as a string
1572 name = GetName(self.GetMesh())
1575 def SetName(self, name):
1577 Set a name to the mesh
1580 name: a new name of the mesh
1583 self.smeshpyD.SetName(self.GetMesh(), name)
1585 def GetSubMesh(self, geom, name):
1587 Get a sub-mesh object associated to a *geom* geometrical object.
1590 geom: a geometrical object (shape)
1591 name: a name for the sub-mesh in the Object Browser
1594 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1595 which lies on the given shape
1598 A sub-mesh is implicitly created when a sub-shape is specified at
1599 creating an algorithm, for example::
1601 algo1D = mesh.Segment(geom=Edge_1)
1603 create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1604 The created sub-mesh can be retrieved from the algorithm::
1606 submesh = algo1D.GetSubMesh()
1609 AssureGeomPublished( self, geom, name )
1610 submesh = self.mesh.GetSubMesh( geom, name )
1615 Return the shape associated to the mesh
1623 def SetShape(self, geom):
1625 Associate the given shape to the mesh (entails the recreation of the mesh)
1628 geom: the shape to be meshed (GEOM_Object)
1631 self.mesh = self.smeshpyD.CreateMesh(geom)
1633 def HasShapeToMesh(self):
1635 Return ``True`` if this mesh is based on geometry
1637 return self.mesh.HasShapeToMesh()
1641 Load mesh from the study after opening the study
1645 def IsReadyToCompute(self, theSubObject):
1647 Return true if the hypotheses are defined well
1650 theSubObject: a sub-shape of a mesh shape
1656 return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1658 def GetAlgoState(self, theSubObject):
1660 Return errors of hypotheses definition.
1661 The list of errors is empty if everything is OK.
1664 theSubObject: a sub-shape of a mesh shape
1670 return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1672 def GetGeometryByMeshElement(self, theElementID, theGeomName):
1674 Return a geometrical object on which the given element was built.
1675 The returned geometrical object, if not nil, is either found in the
1676 study or published by this method with the given name
1679 theElementID: the id of the mesh element
1680 theGeomName: the user-defined name of the geometrical object
1683 GEOM.GEOM_Object instance
1686 return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1688 def MeshDimension(self):
1690 Return the mesh dimension depending on the dimension of the underlying shape
1691 or, if the mesh is not based on any shape, basing on deimension of elements
1694 mesh dimension as an integer value [0,3]
1697 if self.mesh.HasShapeToMesh():
1698 shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1699 if len( shells ) > 0 :
1701 elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1703 elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1708 if self.NbVolumes() > 0: return 3
1709 if self.NbFaces() > 0: return 2
1710 if self.NbEdges() > 0: return 1
1713 def Evaluate(self, geom=0):
1715 Evaluate size of prospective mesh on a shape
1718 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1719 To know predicted number of e.g. edges, inquire it this way::
1721 Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1724 if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1726 geom = self.mesh.GetShapeToMesh()
1729 return self.smeshpyD.Evaluate(self.mesh, geom)
1732 def Compute(self, geom=0, discardModifs=False, refresh=False):
1734 Compute the mesh and return the status of the computation
1737 geom: geomtrical shape on which mesh data should be computed
1738 discardModifs: if True and the mesh has been edited since
1739 a last total re-compute and that may prevent successful partial re-compute,
1740 then the mesh is cleaned before Compute()
1741 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1747 if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1749 geom = self.mesh.GetShapeToMesh()
1754 if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1756 ok = self.smeshpyD.Compute(self.mesh, geom)
1757 except SALOME.SALOME_Exception as ex:
1758 print("Mesh computation failed, exception caught:")
1759 print(" ", ex.details.text)
1762 print("Mesh computation failed, exception caught:")
1763 traceback.print_exc()
1767 # Treat compute errors
1768 computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1770 for err in computeErrors:
1771 if self.mesh.HasShapeToMesh():
1772 shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1774 stdErrors = ["OK", #COMPERR_OK
1775 "Invalid input mesh", #COMPERR_BAD_INPUT_MESH
1776 "std::exception", #COMPERR_STD_EXCEPTION
1777 "OCC exception", #COMPERR_OCC_EXCEPTION
1778 "..", #COMPERR_SLM_EXCEPTION
1779 "Unknown exception", #COMPERR_EXCEPTION
1780 "Memory allocation problem", #COMPERR_MEMORY_PB
1781 "Algorithm failed", #COMPERR_ALGO_FAILED
1782 "Unexpected geometry", #COMPERR_BAD_SHAPE
1783 "Warning", #COMPERR_WARNING
1784 "Computation cancelled",#COMPERR_CANCELED
1785 "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1787 if err.code < len(stdErrors): errText = stdErrors[err.code]
1789 errText = "code %s" % -err.code
1790 if errText: errText += ". "
1791 errText += err.comment
1792 if allReasons: allReasons += "\n"
1794 allReasons += '- "%s"%s - %s' %(err.algoName, shapeText, errText)
1796 allReasons += '- "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1800 errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1802 if err.isGlobalAlgo:
1810 reason = '%s %sD algorithm is missing' % (glob, dim)
1811 elif err.state == HYP_MISSING:
1812 reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1813 % (glob, dim, name, dim))
1814 elif err.state == HYP_NOTCONFORM:
1815 reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1816 elif err.state == HYP_BAD_PARAMETER:
1817 reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1818 % ( glob, dim, name ))
1819 elif err.state == HYP_BAD_GEOMETRY:
1820 reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1821 'geometry' % ( glob, dim, name ))
1822 elif err.state == HYP_HIDDEN_ALGO:
1823 reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1824 'algorithm of upper dimension generating %sD mesh'
1825 % ( glob, dim, name, glob, dim ))
1827 reason = ("For unknown reason. "
1828 "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1830 if allReasons: allReasons += "\n"
1831 allReasons += "- " + reason
1833 if not ok or allReasons != "":
1834 msg = '"' + GetName(self.mesh) + '"'
1835 if ok: msg += " has been computed with warnings"
1836 else: msg += " has not been computed"
1837 if allReasons != "": msg += ":"
1842 if salome.sg.hasDesktop():
1843 if not isinstance( refresh, list): # not a call from subMesh.Compute()
1844 if refresh: salome.sg.updateObjBrowser()
1848 def GetComputeErrors(self, shape=0 ):
1850 Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1854 shape = self.mesh.GetShapeToMesh()
1855 return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1857 def GetSubShapeName(self, subShapeID ):
1859 Return a name of a sub-shape by its ID.
1860 Possible variants (for *subShapeID* == 3):
1862 - **"Face_12"** - published sub-shape
1863 - **FACE #3** - not published sub-shape
1864 - **sub-shape #3** - invalid sub-shape ID
1865 - **#3** - error in this function
1868 subShapeID: a unique ID of a sub-shape
1871 a string describing the sub-shape
1875 if not self.mesh.HasShapeToMesh():
1879 mainIOR = salome.orb.object_to_string( self.GetShape() )
1881 mainSO = s.FindObjectIOR(mainIOR)
1884 shapeText = '"%s"' % mainSO.GetName()
1885 subIt = s.NewChildIterator(mainSO)
1887 subSO = subIt.Value()
1889 obj = subSO.GetObject()
1890 if not obj: continue
1891 go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
1894 ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
1897 if ids == subShapeID:
1898 shapeText = '"%s"' % subSO.GetName()
1901 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
1903 shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
1905 shapeText = 'sub-shape #%s' % (subShapeID)
1907 shapeText = "#%s" % (subShapeID)
1910 def GetFailedShapes(self, publish=False):
1912 Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
1913 error of an algorithm
1916 publish: if *True*, the returned groups will be published in the study
1919 a list of GEOM groups each named after a failed algorithm
1924 computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
1925 for err in computeErrors:
1926 shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
1927 if not shape: continue
1928 if err.algoName in algo2shapes:
1929 algo2shapes[ err.algoName ].append( shape )
1931 algo2shapes[ err.algoName ] = [ shape ]
1935 for algoName, shapes in list(algo2shapes.items()):
1937 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
1938 otherTypeShapes = []
1940 group = self.geompyD.CreateGroup( self.geom, groupType )
1941 for shape in shapes:
1942 if shape.GetShapeType() == shapes[0].GetShapeType():
1943 sameTypeShapes.append( shape )
1945 otherTypeShapes.append( shape )
1946 self.geompyD.UnionList( group, sameTypeShapes )
1948 group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
1950 group.SetName( algoName )
1951 groups.append( group )
1952 shapes = otherTypeShapes
1955 for group in groups:
1956 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
1959 def GetMeshOrder(self):
1961 Return sub-mesh objects list in meshing order
1964 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1967 return self.mesh.GetMeshOrder()
1969 def SetMeshOrder(self, submeshes):
1971 Set order in which concurrent sub-meshes should be meshed
1974 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1977 return self.mesh.SetMeshOrder(submeshes)
1979 def Clear(self, refresh=False):
1981 Remove all nodes and elements generated on geometry. Imported elements remain.
1984 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1988 if ( salome.sg.hasDesktop() ):
1989 if refresh: salome.sg.updateObjBrowser()
1991 def ClearSubMesh(self, geomId, refresh=False):
1993 Remove all nodes and elements of indicated shape
1996 geomId: the ID of a sub-shape to remove elements on
1997 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2000 self.mesh.ClearSubMesh(geomId)
2001 if salome.sg.hasDesktop():
2002 if refresh: salome.sg.updateObjBrowser()
2004 def AutomaticTetrahedralization(self, fineness=0):
2006 Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
2009 fineness: [0.0,1.0] defines mesh fineness
2015 dim = self.MeshDimension()
2017 self.RemoveGlobalHypotheses()
2018 self.Segment().AutomaticLength(fineness)
2020 self.Triangle().LengthFromEdges()
2025 return self.Compute()
2027 def AutomaticHexahedralization(self, fineness=0):
2029 Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2032 fineness: [0.0, 1.0] defines mesh fineness
2038 dim = self.MeshDimension()
2039 # assign the hypotheses
2040 self.RemoveGlobalHypotheses()
2041 self.Segment().AutomaticLength(fineness)
2048 return self.Compute()
2050 def AddHypothesis(self, hyp, geom=0):
2055 hyp: a hypothesis to assign
2056 geom: a subhape of mesh geometry
2059 :class:`SMESH.Hypothesis_Status`
2062 if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2063 hyp, geom = geom, hyp
2064 if isinstance( hyp, Mesh_Algorithm ):
2065 hyp = hyp.GetAlgorithm()
2070 geom = self.mesh.GetShapeToMesh()
2073 if self.mesh.HasShapeToMesh():
2074 hyp_type = hyp.GetName()
2075 lib_name = hyp.GetLibName()
2076 # checkAll = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2077 # if checkAll and geom:
2078 # checkAll = geom.GetType() == 37
2080 isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2082 AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2083 status = self.mesh.AddHypothesis(geom, hyp)
2085 status = HYP_BAD_GEOMETRY, ""
2086 hyp_name = GetName( hyp )
2089 geom_name = geom.GetName()
2090 isAlgo = hyp._narrow( SMESH_Algo )
2091 TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2094 def IsUsedHypothesis(self, hyp, geom):
2096 Return True if an algorithm or hypothesis is assigned to a given shape
2099 hyp: an algorithm or hypothesis to check
2100 geom: a subhape of mesh geometry
2106 if not hyp: # or not geom
2108 if isinstance( hyp, Mesh_Algorithm ):
2109 hyp = hyp.GetAlgorithm()
2111 hyps = self.GetHypothesisList(geom)
2113 if h.GetId() == hyp.GetId():
2117 def RemoveHypothesis(self, hyp, geom=0):
2119 Unassign a hypothesis
2122 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2123 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2126 :class:`SMESH.Hypothesis_Status`
2131 if isinstance( hyp, Mesh_Algorithm ):
2132 hyp = hyp.GetAlgorithm()
2138 if self.IsUsedHypothesis( hyp, shape ):
2139 return self.mesh.RemoveHypothesis( shape, hyp )
2140 hypName = GetName( hyp )
2141 geoName = GetName( shape )
2142 print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2145 def GetHypothesisList(self, geom):
2147 Get the list of hypotheses added on a geometry
2150 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2153 the sequence of :class:`SMESH.SMESH_Hypothesis`
2156 return self.mesh.GetHypothesisList( geom )
2158 def RemoveGlobalHypotheses(self):
2160 Remove all global hypotheses
2163 current_hyps = self.mesh.GetHypothesisList( self.geom )
2164 for hyp in current_hyps:
2165 self.mesh.RemoveHypothesis( self.geom, hyp )
2168 def ExportMED(self, *args, **kwargs):
2170 Export the mesh in a file in MED format
2171 allowing to overwrite the file if it exists or add the exported data to its contents
2174 fileName: is the file name
2175 auto_groups (boolean): parameter for creating/not creating
2176 the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2177 the typical use is auto_groups=False.
2178 minor (int): define the minor version (y, where version is x.y.z) of MED file format.
2179 The minor must be between 0 and the current minor version of MED file library.
2180 If minor is equal to -1, the minor version is not changed (default).
2181 The major version (x, where version is x.y.z) cannot be changed.
2182 overwrite (boolean): parameter for overwriting/not overwriting the file
2183 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2184 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2186 - 1D if all mesh nodes lie on OX coordinate axis, or
2187 - 2D if all mesh nodes lie on XOY coordinate plane, or
2188 - 3D in the rest cases.
2190 If *autoDimension* is *False*, the space dimension is always 3.
2191 fields: list of GEOM fields defined on the shape to mesh.
2192 geomAssocFields: each character of this string means a need to export a
2193 corresponding field; correspondence between fields and characters is following:
2195 - 'v' stands for "_vertices_" field;
2196 - 'e' stands for "_edges_" field;
2197 - 'f' stands for "_faces_" field;
2198 - 's' stands for "_solids_" field.
2200 # process positional arguments
2201 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2203 auto_groups = args[1] if len(args) > 1 else False
2204 minor = args[2] if len(args) > 2 else -1
2205 overwrite = args[3] if len(args) > 3 else True
2206 meshPart = args[4] if len(args) > 4 else None
2207 autoDimension = args[5] if len(args) > 5 else True
2208 fields = args[6] if len(args) > 6 else []
2209 geomAssocFields = args[7] if len(args) > 7 else ''
2210 # process keywords arguments
2211 auto_groups = kwargs.get("auto_groups", auto_groups)
2212 minor = kwargs.get("minor", minor)
2213 overwrite = kwargs.get("overwrite", overwrite)
2214 meshPart = kwargs.get("meshPart", meshPart)
2215 autoDimension = kwargs.get("autoDimension", autoDimension)
2216 fields = kwargs.get("fields", fields)
2217 geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2218 # invoke engine's function
2219 if meshPart or fields or geomAssocFields:
2220 unRegister = genObjUnRegister()
2221 if isinstance( meshPart, list ):
2222 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2223 unRegister.set( meshPart )
2224 self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
2225 fields, geomAssocFields)
2227 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2229 def ExportSAUV(self, f, auto_groups=0):
2231 Export the mesh in a file in SAUV format
2236 auto_groups: boolean parameter for creating/not creating
2237 the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2238 the typical use is auto_groups=False.
2241 self.mesh.ExportSAUV(f, auto_groups)
2243 def ExportDAT(self, f, meshPart=None):
2245 Export the mesh in a file in DAT format
2249 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2253 unRegister = genObjUnRegister()
2254 if isinstance( meshPart, list ):
2255 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2256 unRegister.set( meshPart )
2257 self.mesh.ExportPartToDAT( meshPart, f )
2259 self.mesh.ExportDAT(f)
2261 def ExportUNV(self, f, meshPart=None):
2263 Export the mesh in a file in UNV format
2267 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2271 unRegister = genObjUnRegister()
2272 if isinstance( meshPart, list ):
2273 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2274 unRegister.set( meshPart )
2275 self.mesh.ExportPartToUNV( meshPart, f )
2277 self.mesh.ExportUNV(f)
2279 def ExportSTL(self, f, ascii=1, meshPart=None):
2281 Export the mesh in a file in STL format
2285 ascii: defines the file encoding
2286 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2290 unRegister = genObjUnRegister()
2291 if isinstance( meshPart, list ):
2292 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2293 unRegister.set( meshPart )
2294 self.mesh.ExportPartToSTL( meshPart, f, ascii )
2296 self.mesh.ExportSTL(f, ascii)
2298 def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2300 Export the mesh in a file in CGNS format
2304 overwrite: boolean parameter for overwriting/not overwriting the file
2305 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2306 groupElemsByType: if True all elements of same entity type are exported at ones,
2307 else elements are exported in order of their IDs which can cause creation
2308 of multiple cgns sections
2311 unRegister = genObjUnRegister()
2312 if isinstance( meshPart, list ):
2313 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2314 unRegister.set( meshPart )
2315 if isinstance( meshPart, Mesh ):
2316 meshPart = meshPart.mesh
2318 meshPart = self.mesh
2319 self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2321 def ExportGMF(self, f, meshPart=None):
2323 Export the mesh in a file in GMF format.
2324 GMF files must have .mesh extension for the ASCII format and .meshb for
2325 the bynary format. Other extensions are not allowed.
2329 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2332 unRegister = genObjUnRegister()
2333 if isinstance( meshPart, list ):
2334 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2335 unRegister.set( meshPart )
2336 if isinstance( meshPart, Mesh ):
2337 meshPart = meshPart.mesh
2339 meshPart = self.mesh
2340 self.mesh.ExportGMF(meshPart, f, True)
2342 def ExportToMED(self, *args, **kwargs):
2344 Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2345 Export the mesh in a file in MED format
2346 allowing to overwrite the file if it exists or add the exported data to its contents
2349 fileName: the file name
2350 opt (boolean): parameter for creating/not creating
2351 the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2352 overwrite: boolean parameter for overwriting/not overwriting the file
2353 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2355 - 1D if all mesh nodes lie on OX coordinate axis, or
2356 - 2D if all mesh nodes lie on XOY coordinate plane, or
2357 - 3D in the rest cases.
2359 If **autoDimension** is *False*, the space dimension is always 3.
2362 print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2363 # process positional arguments
2364 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2366 auto_groups = args[1] if len(args) > 1 else False
2367 overwrite = args[2] if len(args) > 2 else True
2368 autoDimension = args[3] if len(args) > 3 else True
2369 # process keywords arguments
2370 auto_groups = kwargs.get("opt", auto_groups) # old keyword name
2371 auto_groups = kwargs.get("auto_groups", auto_groups) # new keyword name
2372 overwrite = kwargs.get("overwrite", overwrite)
2373 autoDimension = kwargs.get("autoDimension", autoDimension)
2375 # invoke engine's function
2376 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2378 def ExportToMEDX(self, *args, **kwargs):
2380 Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2381 Export the mesh in a file in MED format
2384 fileName: the file name
2385 opt (boolean): parameter for creating/not creating
2386 the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2387 overwrite: boolean parameter for overwriting/not overwriting the file
2388 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2390 - 1D if all mesh nodes lie on OX coordinate axis, or
2391 - 2D if all mesh nodes lie on XOY coordinate plane, or
2392 - 3D in the rest cases.
2394 If **autoDimension** is *False*, the space dimension is always 3.
2397 print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2398 # process positional arguments
2399 #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2401 auto_groups = args[1] if len(args) > 1 else False
2402 overwrite = args[2] if len(args) > 2 else True
2403 autoDimension = args[3] if len(args) > 3 else True
2404 # process keywords arguments
2405 auto_groups = kwargs.get("auto_groups", auto_groups)
2406 overwrite = kwargs.get("overwrite", overwrite)
2407 autoDimension = kwargs.get("autoDimension", autoDimension)
2409 # invoke engine's function
2410 self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2412 # Operations with groups:
2413 # ----------------------
2414 def CreateEmptyGroup(self, elementType, name):
2416 Create an empty standalone mesh group
2419 elementType: the :class:`type <SMESH.ElementType>` of elements in the group;
2420 either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2421 name: the name of the mesh group
2424 :class:`SMESH.SMESH_Group`
2427 return self.mesh.CreateGroup(elementType, name)
2429 def Group(self, grp, name=""):
2431 Create a mesh group based on the geometric object *grp*
2432 and give it a *name*.
2433 If *name* is not defined the name of the geometric group is used
2436 Works like :meth:`GroupOnGeom`.
2439 grp: a geometric group, a vertex, an edge, a face or a solid
2440 name: the name of the mesh group
2443 :class:`SMESH.SMESH_GroupOnGeom`
2446 return self.GroupOnGeom(grp, name)
2448 def GroupOnGeom(self, grp, name="", typ=None):
2450 Create a mesh group based on the geometrical object *grp*
2451 and give it a *name*.
2452 if *name* is not defined the name of the geometric group is used
2455 grp: a geometrical group, a vertex, an edge, a face or a solid
2456 name: the name of the mesh group
2457 typ: the type of elements in the group; either of
2458 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2459 automatically detected by the type of the geometry
2462 :class:`SMESH.SMESH_GroupOnGeom`
2465 AssureGeomPublished( self, grp, name )
2467 name = grp.GetName()
2469 typ = self._groupTypeFromShape( grp )
2470 return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2472 def _groupTypeFromShape( self, shape ):
2474 Pivate method to get a type of group on geometry
2476 tgeo = str(shape.GetShapeType())
2477 if tgeo == "VERTEX":
2479 elif tgeo == "EDGE":
2481 elif tgeo == "FACE" or tgeo == "SHELL":
2483 elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2485 elif tgeo == "COMPOUND":
2486 sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2488 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2489 return self._groupTypeFromShape( sub[0] )
2491 raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2494 def GroupOnFilter(self, typ, name, filter):
2496 Create a mesh group with given *name* based on the *filter*.
2497 It is a special type of group dynamically updating it's contents during
2501 typ: the type of elements in the group; either of
2502 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2503 name: the name of the mesh group
2504 filter (SMESH.Filter): the filter defining group contents
2507 :class:`SMESH.SMESH_GroupOnFilter`
2510 return self.mesh.CreateGroupFromFilter(typ, name, filter)
2512 def MakeGroupByIds(self, groupName, elementType, elemIDs):
2514 Create a mesh group by the given ids of elements
2517 groupName: the name of the mesh group
2518 elementType: the type of elements in the group; either of
2519 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2520 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2523 :class:`SMESH.SMESH_Group`
2526 group = self.mesh.CreateGroup(elementType, groupName)
2527 if isinstance( elemIDs, Mesh ):
2528 elemIDs = elemIDs.GetMesh()
2529 if hasattr( elemIDs, "GetIDs" ):
2530 if hasattr( elemIDs, "SetMesh" ):
2531 elemIDs.SetMesh( self.GetMesh() )
2532 group.AddFrom( elemIDs )
2540 CritType=FT_Undefined,
2543 UnaryOp=FT_Undefined,
2546 Create a mesh group by the given conditions
2549 groupName: the name of the mesh group
2550 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2551 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2552 Note that the items starting from FT_LessThan are not suitable for CritType.
2553 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2554 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2555 UnaryOp (SMESH.FunctorType): SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2556 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2557 SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2560 :class:`SMESH.SMESH_GroupOnFilter`
2563 aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2564 group = self.MakeGroupByCriterion(groupName, aCriterion)
2567 def MakeGroupByCriterion(self, groupName, Criterion):
2569 Create a mesh group by the given criterion
2572 groupName: the name of the mesh group
2573 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2576 :class:`SMESH.SMESH_GroupOnFilter`
2579 :meth:`smeshBuilder.GetCriterion`
2582 return self.MakeGroupByCriteria( groupName, [Criterion] )
2584 def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2586 Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2589 groupName: the name of the mesh group
2590 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2591 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2594 :class:`SMESH.SMESH_GroupOnFilter`
2597 :meth:`smeshBuilder.GetCriterion`
2600 aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2601 group = self.MakeGroupByFilter(groupName, aFilter)
2604 def MakeGroupByFilter(self, groupName, theFilter):
2606 Create a mesh group by the given filter
2609 groupName (string): the name of the mesh group
2610 theFilter (SMESH.Filter): the filter
2613 :class:`SMESH.SMESH_GroupOnFilter`
2616 :meth:`smeshBuilder.GetFilter`
2619 #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2620 #theFilter.SetMesh( self.mesh )
2621 #group.AddFrom( theFilter )
2622 group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2625 def RemoveGroup(self, group):
2630 group (SMESH.SMESH_GroupBase): group to remove
2633 self.mesh.RemoveGroup(group)
2635 def RemoveGroupWithContents(self, group):
2637 Remove a group with its contents
2640 group (SMESH.SMESH_GroupBase): group to remove
2643 self.mesh.RemoveGroupWithContents(group)
2645 def GetGroups(self, elemType = SMESH.ALL):
2647 Get the list of groups existing in the mesh in the order of creation
2648 (starting from the oldest one)
2651 elemType (SMESH.ElementType): type of elements the groups contain;
2652 by default groups of elements of all types are returned
2655 a list of :class:`SMESH.SMESH_GroupBase`
2658 groups = self.mesh.GetGroups()
2659 if elemType == SMESH.ALL:
2663 if g.GetType() == elemType:
2664 typedGroups.append( g )
2671 Get the number of groups existing in the mesh
2674 the quantity of groups as an integer value
2677 return self.mesh.NbGroups()
2679 def GetGroupNames(self):
2681 Get the list of names of groups existing in the mesh
2687 groups = self.GetGroups()
2689 for group in groups:
2690 names.append(group.GetName())
2693 def GetGroupByName(self, name, elemType = None):
2695 Find groups by name and type
2698 name (string): name of the group of interest
2699 elemType (SMESH.ElementType): type of elements the groups contain;
2700 by default one group of any type is returned;
2701 if elemType == SMESH.ALL then all groups of any type are returned
2704 a list of :class:`SMESH.SMESH_GroupBase`
2708 for group in self.GetGroups():
2709 if group.GetName() == name:
2710 if elemType is None:
2712 if ( elemType == SMESH.ALL or
2713 group.GetType() == elemType ):
2714 groups.append( group )
2717 def UnionGroups(self, group1, group2, name):
2719 Produce a union of two groups.
2720 A new group is created. All mesh elements that are
2721 present in the initial groups are added to the new one
2724 group1 (SMESH.SMESH_GroupBase): a group
2725 group2 (SMESH.SMESH_GroupBase): another group
2728 instance of :class:`SMESH.SMESH_Group`
2731 return self.mesh.UnionGroups(group1, group2, name)
2733 def UnionListOfGroups(self, groups, name):
2735 Produce a union list of groups.
2736 New group is created. All mesh elements that are present in
2737 initial groups are added to the new one
2740 groups: list of :class:`SMESH.SMESH_GroupBase`
2743 instance of :class:`SMESH.SMESH_Group`
2745 return self.mesh.UnionListOfGroups(groups, name)
2747 def IntersectGroups(self, group1, group2, name):
2749 Prodice an intersection of two groups.
2750 A new group is created. All mesh elements that are common
2751 for the two initial groups are added to the new one.
2754 group1 (SMESH.SMESH_GroupBase): a group
2755 group2 (SMESH.SMESH_GroupBase): another group
2758 instance of :class:`SMESH.SMESH_Group`
2761 return self.mesh.IntersectGroups(group1, group2, name)
2763 def IntersectListOfGroups(self, groups, name):
2765 Produce an intersection of groups.
2766 New group is created. All mesh elements that are present in all
2767 initial groups simultaneously are added to the new one
2770 groups: a list of :class:`SMESH.SMESH_GroupBase`
2773 instance of :class:`SMESH.SMESH_Group`
2775 return self.mesh.IntersectListOfGroups(groups, name)
2777 def CutGroups(self, main_group, tool_group, name):
2779 Produce a cut of two groups.
2780 A new group is created. All mesh elements that are present in
2781 the main group but are not present in the tool group are added to the new one
2784 main_group (SMESH.SMESH_GroupBase): a group to cut from
2785 tool_group (SMESH.SMESH_GroupBase): a group to cut by
2788 an instance of :class:`SMESH.SMESH_Group`
2791 return self.mesh.CutGroups(main_group, tool_group, name)
2793 def CutListOfGroups(self, main_groups, tool_groups, name):
2795 Produce a cut of groups.
2796 A new group is created. All mesh elements that are present in main groups
2797 but do not present in tool groups are added to the new one
2800 main_group: groups to cut from (list of :class:`SMESH.SMESH_GroupBase`)
2801 tool_group: groups to cut by (list of :class:`SMESH.SMESH_GroupBase`)
2804 an instance of :class:`SMESH.SMESH_Group`
2807 return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2809 def CreateDimGroup(self, groups, elemType, name,
2810 nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2812 Create a standalone group of entities basing on nodes of other groups.
2815 groups: list of reference :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
2816 elemType: a type of elements to include to the new group; either of
2817 (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2818 name: a name of the new group.
2819 nbCommonNodes: a criterion of inclusion of an element to the new group
2820 basing on number of element nodes common with reference *groups*.
2821 Meaning of possible values are:
2823 - SMESH.ALL_NODES - include if all nodes are common,
2824 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
2825 - SMESH.AT_LEAST_ONE - include if one or more node is common,
2826 - SMEHS.MAJORITY - include if half of nodes or more are common.
2827 underlyingOnly: if *True* (default), an element is included to the
2828 new group provided that it is based on nodes of an element of *groups*;
2829 in this case the reference *groups* are supposed to be of higher dimension
2830 than *elemType*, which can be useful for example to get all faces lying on
2831 volumes of the reference *groups*.
2834 an instance of :class:`SMESH.SMESH_Group`
2837 if isinstance( groups, SMESH._objref_SMESH_IDSource ):
2839 return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
2842 def ConvertToStandalone(self, group):
2844 Convert group on geom into standalone group
2847 return self.mesh.ConvertToStandalone(group)
2849 # Get some info about mesh:
2850 # ------------------------
2852 def GetLog(self, clearAfterGet):
2854 Return the log of nodes and elements added or removed
2855 since the previous clear of the log.
2858 clearAfterGet: log is emptied after Get (safe if concurrents access)
2861 list of SMESH.log_block structures { commandType, number, coords, indexes }
2864 return self.mesh.GetLog(clearAfterGet)
2868 Clear the log of nodes and elements added or removed since the previous
2869 clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
2872 self.mesh.ClearLog()
2874 def SetAutoColor(self, theAutoColor):
2876 Toggle auto color mode on the object.
2877 If switched on, a default color of a new group in Create Group dialog is chosen randomly.
2880 theAutoColor (boolean): the flag which toggles auto color mode.
2883 self.mesh.SetAutoColor(theAutoColor)
2885 def GetAutoColor(self):
2887 Get flag of object auto color mode.
2893 return self.mesh.GetAutoColor()
2900 integer value, which is the internal Id of the mesh
2903 return self.mesh.GetId()
2905 def HasDuplicatedGroupNamesMED(self):
2907 Check the group names for duplications.
2908 Consider the maximum group name length stored in MED file.