Salome HOME
Merge branch 'occ/shaper2smesh'
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
1 # Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
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.
7 #
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.
12 #
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
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19 #  File   : smeshBuilder.py
20 #  Author : Francis KLOSS, OCC
21 #  Module : SMESH
22
23 import salome
24 from salome.geom import geomBuilder
25
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
40
41 from   SMESH import *
42 from   salome.smesh.smesh_algorithm import Mesh_Algorithm
43
44 import SALOME
45 import SALOMEDS
46 import os
47 import inspect
48
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
51 # defined
52 #
53 try:
54     SMESH.Entity_Triangle < SMESH.Entity_Quadrangle
55 except TypeError:
56     def enumitem_eq(self, other):
57         try:
58             if isinstance(other, omniORB.EnumItem):
59                 if other._parent_id == self._parent_id:
60                     return self._v == other._v
61                 else:
62                     return self._parent_id == other._parent_id
63             else:
64                 return id(self) == id(other)
65         except:
66             return id(self) == id(other)
67
68     def enumitem_lt(self, other):
69         try:
70             if isinstance(other, omniORB.EnumItem):
71                 if other._parent_id == self._parent_id:
72                     return self._v < other._v
73                 else:
74                     return self._parent_id < other._parent_id
75             else:
76                 return id(self) < id(other)
77         except:
78             return id(self) < id(other)
79
80     def enumitem_le(self, other):
81         try:
82             if isinstance(other, omniORB.EnumItem):
83                 if other._parent_id == self._parent_id:
84                     return self._v <= other._v
85                 else:
86                     return self._parent_id <= other._parent_id
87             else:
88                 return id(self) <= id(other)
89         except:
90             return id(self) <= id(other)
91
92     def enumitem_gt(self, other):
93         try:
94             if isinstance(other, omniORB.EnumItem):
95                 if other._parent_id == self._parent_id:
96                     return self._v > other._v
97                 else:
98                     return self._parent_id > other._parent_id
99             else:
100                 return id(self) > id(other)
101         except:
102             return id(self) > id(other)
103
104     def enumitem_ge(self, other):
105         try:
106             if isinstance(other, omniORB.EnumItem):
107                 if other._parent_id == self._parent_id:
108                     return self._v >= other._v
109                 else:
110                     return self._parent_id >= other._parent_id
111             else:
112                 return id(self) >= id(other)
113         except:
114             return id(self) >= id(other)
115
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
121
122
123 class MeshMeta(type):
124     """Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
125     """
126     def __instancecheck__(cls, inst):
127         """Implement isinstance(inst, cls)."""
128         return any(cls.__subclasscheck__(c)
129                    for c in {type(inst), inst.__class__})
130
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__)
134
135 def DegreesToRadians(AngleInDegrees):
136     """Convert an angle from degrees to radians
137     """
138     from math import pi
139     return AngleInDegrees * pi / 180.0
140
141 import salome_notebook
142 notebook = salome_notebook.notebook
143 # Salome notebook variable separator
144 var_separator = ":"
145
146 def ParseParameters(*args):
147     """
148     Return list of variable values from salome notebook.
149     The last argument, if is callable, is used to modify values got from notebook
150     """
151     Result = []
152     Parameters = ""
153     hasVariables = False
154     varModifFun=None
155     if args and callable(args[-1]):
156         args, varModifFun = args[:-1], args[-1]
157     for parameter in args:
158
159         Parameters += str(parameter) + var_separator
160
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)
166             hasVariables = True
167             if varModifFun:
168                 parameter = varModifFun(parameter)
169                 pass
170             pass
171         Result.append(parameter)
172
173         pass
174     Parameters = Parameters[:-1]
175     Result.append( Parameters )
176     Result.append( hasVariables )
177     return Result
178
179 def ParseAngles(*args):
180     """
181     Parse parameters while converting variables to radians
182     """
183     return ParseParameters( *( args + (DegreesToRadians, )))
184
185 def __initPointStruct(point,*args):
186     """
187     Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
188     Parameters are stored in PointStruct.parameters attribute
189     """
190     point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
191     pass
192 SMESH.PointStruct.__init__ = __initPointStruct
193
194 def __initAxisStruct(ax,*args):
195     """
196     Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
197     Parameters are stored in AxisStruct.parameters attribute
198     """
199     if len( args ) != 6:
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)
202     pass
203 SMESH.AxisStruct.__init__ = __initAxisStruct
204
205 smeshPrecisionConfusion = 1.e-07
206 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
207     """Compare real values using smeshPrecisionConfusion as tolerance
208     """
209     if abs(val1 - val2) < tol:
210         return True
211     return False
212
213 NO_NAME = "NoName"
214
215 def GetName(obj):
216     """
217     Return a name of an object
218     
219     Returns:
220         object name
221     """
222     if obj:
223         # object not null
224         if isinstance(obj, SALOMEDS._objref_SObject):
225             # study object
226             return obj.GetName()
227         try:
228             ior  = salome.orb.object_to_string(obj)
229         except:
230             ior = None
231         if ior:
232             sobj = salome.myStudy.FindObjectIOR(ior)
233             if sobj:
234                 return sobj.GetName()
235             if hasattr(obj, "GetName"):
236                 # unknown CORBA object, having GetName() method
237                 return obj.GetName()
238             else:
239                 # unknown CORBA object, no GetName() method
240                 return NO_NAME
241             pass
242         if hasattr(obj, "GetName"):
243             # unknown non-CORBA object, having GetName() method
244             return obj.GetName()
245         pass
246     raise RuntimeError("Null or invalid object")
247
248 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
249     """
250     Print error message if a hypothesis was not assigned.
251     """
252     if isAlgo:
253         hypType = "algorithm"
254     else:
255         hypType = "hypothesis"
256         pass
257     reason = ""
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:
284         pass
285     else:
286         return
287     where = geomName
288     if where:
289         where = '"%s"' % geomName
290         if mesh:
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 ))
296     elif where:
297         print('"%s" was not assigned to %s : %s' %( hypName, where, reason ))
298     else:
299         print('"%s" was not assigned : %s' %( hypName, reason ))
300         pass
301
302 def AssureGeomPublished(mesh, geom, name=''):
303     """
304     Private method. Add geom (sub-shape of the main shape) into the study if not yet there
305     """
306     if not mesh.smeshpyD.IsEnablePublish():
307         return
308     if not hasattr( geom, "GetShapeType" ):
309         return
310     if not geom.GetStudyEntry():
311         ## get a name
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)
315         if not name:
316             name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
317         ## publish
318         mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
319     return
320
321 # def FirstVertexOnCurve(mesh, edge):
322 #     """
323 #     Returns:
324 #         the first vertex of a geometrical edge by ignoring orientation
325 #     """
326 #     return mesh.geompyD.GetVertexByIndex( edge, 0, False )
327
328
329 smeshInst = None
330 """
331 Warning:
332     smeshInst is a singleton
333 """
334 engine = None
335 doLcc = False
336 created = False
337
338 class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
339     """
340     This class allows to create, load or manipulate meshes.
341     It has a set of methods to create, load or copy meshes, to combine several meshes, etc.
342     It also has methods to get infos and measure meshes.
343     """
344
345     # MirrorType enumeration
346     POINT = SMESH_MeshEditor.POINT
347     AXIS =  SMESH_MeshEditor.AXIS
348     PLANE = SMESH_MeshEditor.PLANE
349
350     # Smooth_Method enumeration
351     LAPLACIAN_SMOOTH = SMESH_MeshEditor.LAPLACIAN_SMOOTH
352     CENTROIDAL_SMOOTH = SMESH_MeshEditor.CENTROIDAL_SMOOTH
353
354     PrecisionConfusion = smeshPrecisionConfusion
355
356     # TopAbs_State enumeration
357     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = list(range(4))
358
359     # Methods of splitting a hexahedron into tetrahedra
360     Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
361
362     def __new__(cls, *args):
363         global engine
364         global smeshInst
365         global doLcc
366         #print("==== __new__", engine, smeshInst, doLcc)
367
368         if smeshInst is None:
369             # smesh engine is either retrieved from engine, or created
370             smeshInst = engine
371             # Following test avoids a recursive loop
372             if doLcc:
373                 if smeshInst is not None:
374                     # smesh engine not created: existing engine found
375                     doLcc = False
376                 if doLcc:
377                     doLcc = False
378                     # FindOrLoadComponent called:
379                     # 1. CORBA resolution of server
380                     # 2. the __new__ method is called again
381                     #print("==== smeshInst = lcc.FindOrLoadComponent ", engine, smeshInst, doLcc)
382                     smeshInst = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" )
383             else:
384                 # FindOrLoadComponent not called
385                 if smeshInst is None:
386                     # smeshBuilder instance is created from lcc.FindOrLoadComponent
387                     #print("==== smeshInst = super(smeshBuilder,cls).__new__(cls) ", engine, smeshInst, doLcc)
388                     smeshInst = super(smeshBuilder,cls).__new__(cls)
389                 else:
390                     # smesh engine not created: existing engine found
391                     #print("==== existing ", engine, smeshInst, doLcc)
392                     pass
393             #print("====1 ", smeshInst)
394             return smeshInst
395
396         #print("====2 ", smeshInst)
397         return smeshInst
398
399     def __init__(self, *args):
400         global created
401         #print("--------------- smeshbuilder __init__ ---", created)
402         if not created:
403             created = True
404             SMESH._objref_SMESH_Gen.__init__(self, *args)
405
406
407     def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
408         """
409         Dump component to the Python script.
410         This method overrides IDL function to allow default values for the parameters.
411         """
412
413         return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
414
415     def SetDumpPythonHistorical(self, isHistorical):
416         """
417         Set mode of DumpPython(), *historical* or *snapshot*.
418         In the *historical* mode, the Python Dump script includes all commands
419         performed by SMESH engine. In the *snapshot* mode, commands
420         relating to objects removed from the Study are excluded from the script
421         as well as commands not influencing the current state of meshes
422         """
423
424         if isHistorical: val = "true"
425         else:            val = "false"
426         SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
427
428     def init_smesh(self,geompyD = None):
429         """
430         Set Geometry component
431         """    
432         #print("init_smesh")
433         self.UpdateStudy(geompyD)
434         notebook.myStudy = salome.myStudy
435
436     def Mesh(self, obj=0, name=0):
437         """
438         Create a mesh. This mesh can be either 
439
440         * an empty mesh not bound to geometry, if *obj* == 0
441         * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
442         * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
443
444         Parameters:
445             obj: either 
446
447                    1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
448                       ::
449
450                         salome.myStudy.FindObjectID("0:1:2:3").GetObject() 
451
452                    2. a geometrical object for meshing
453                    3. none.
454             name: the name for the new mesh.
455
456         Returns:
457             an instance of class :class:`Mesh`.
458         """
459
460         if isinstance(obj,str):
461             obj,name = name,obj
462         return Mesh(self, self.geompyD, obj, name)
463
464     def RemoveMesh( self, mesh ):
465         """
466         Delete a mesh
467         """
468         if isinstance( mesh, Mesh ):
469             mesh = mesh.GetMesh()
470             pass
471         if not isinstance( mesh, SMESH._objref_SMESH_Mesh ):
472             raise TypeError("%s is not a mesh" % mesh )
473         so = salome.ObjectToSObject( mesh )
474         if so:
475             sb = salome.myStudy.NewBuilder()
476             sb.RemoveObjectWithChildren( so )
477         else:
478             mesh.UnRegister()
479             pass
480         return
481
482     def EnumToLong(self,theItem):
483         """
484         Return a long value from enumeration
485         """
486
487         return theItem._v
488
489     def ColorToString(self,c):
490         """
491         Convert SALOMEDS.Color to string.
492         To be used with filters.
493
494         Parameters:
495             c: color value (SALOMEDS.Color)
496
497         Returns:
498             a string representation of the color.
499         """
500
501         val = ""
502         if isinstance(c, SALOMEDS.Color):
503             val = "%s;%s;%s" % (c.R, c.G, c.B)
504         elif isinstance(c, str):
505             val = c
506         else:
507             raise ValueError("Color value should be of string or SALOMEDS.Color type")
508         return val
509
510     def GetPointStruct(self,theVertex):
511         """
512         Get :class:`SMESH.PointStruct` from vertex
513
514         Parameters:
515                 theVertex (GEOM.GEOM_Object): vertex
516
517         Returns:
518                 :class:`SMESH.PointStruct`
519         """
520         geompyD = theVertex.GetGen()
521         [x, y, z] = geompyD.PointCoordinates(theVertex)
522         return PointStruct(x,y,z)
523
524     def GetDirStruct(self,theVector):
525         """
526         Get :class:`SMESH.DirStruct` from vector
527
528         Parameters:
529                 theVector (GEOM.GEOM_Object): vector
530
531         Returns:
532                 :class:`SMESH.DirStruct`
533         """
534         geompyD = theVector.GetGen()
535         vertices = geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
536         if(len(vertices) != 2):
537             print("Error: vector object is incorrect.")
538             return None
539         p1 = geompyD.PointCoordinates(vertices[0])
540         p2 = geompyD.PointCoordinates(vertices[1])
541         pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
542         dirst = DirStruct(pnt)
543         return dirst
544
545     def MakeDirStruct(self,x,y,z):
546         """
547         Make :class:`SMESH.DirStruct` from a triplet of floats
548
549         Parameters:
550                 x,y,z (float): vector components
551
552         Returns:
553                 :class:`SMESH.DirStruct`
554         """
555
556         pnt = PointStruct(x,y,z)
557         return DirStruct(pnt)
558
559     def GetAxisStruct(self,theObj):
560         """
561         Get :class:`SMESH.AxisStruct` from a geometrical object
562
563         Parameters:
564             theObj (GEOM.GEOM_Object): line or plane
565
566         Returns:
567             :class:`SMESH.AxisStruct`
568         """
569         import GEOM
570         geompyD = theObj.GetGen()
571         edges = geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
572         axis = None
573         if len(edges) > 1:
574             vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
575             vertex3, vertex4 = geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
576             vertex1 = geompyD.PointCoordinates(vertex1)
577             vertex2 = geompyD.PointCoordinates(vertex2)
578             vertex3 = geompyD.PointCoordinates(vertex3)
579             vertex4 = geompyD.PointCoordinates(vertex4)
580             v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
581             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
582             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] ]
583             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
584             axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
585         elif len(edges) == 1:
586             vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
587             p1 = geompyD.PointCoordinates( vertex1 )
588             p2 = geompyD.PointCoordinates( vertex2 )
589             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
590             axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
591         elif theObj.GetShapeType() == GEOM.VERTEX:
592             x,y,z = geompyD.PointCoordinates( theObj )
593             axis = AxisStruct( x,y,z, 1,0,0,)
594             axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
595         return axis
596
597     # From SMESH_Gen interface:
598     # ------------------------
599
600     def SetName(self, obj, name):
601         """
602         Set the given name to an object
603
604         Parameters:
605                 obj: the object to rename
606                 name: a new object name
607         """
608
609         if isinstance( obj, Mesh ):
610             obj = obj.GetMesh()
611         elif isinstance( obj, Mesh_Algorithm ):
612             obj = obj.GetAlgorithm()
613         ior  = salome.orb.object_to_string(obj)
614         SMESH._objref_SMESH_Gen.SetName(self, ior, name)
615
616     def SetEmbeddedMode( self,theMode ):
617         """
618         Set the current mode
619         """
620
621         SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
622
623     def IsEmbeddedMode(self):
624         """
625         Get the current mode
626         """
627
628         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
629
630     def UpdateStudy( self, geompyD = None  ):
631         """
632         Update the current study. Calling UpdateStudy() allows to
633         update meshes at switching GEOM->SMESH
634         """
635         #self.UpdateStudy()
636         if not geompyD:
637             from salome.geom import geomBuilder
638             geompyD = geomBuilder.geom
639             if not geompyD:
640                 geompyD = geomBuilder.New()
641             pass
642         self.geompyD=geompyD
643         self.SetGeomEngine(geompyD)
644         SMESH._objref_SMESH_Gen.UpdateStudy(self)
645         sb = salome.myStudy.NewBuilder()
646         sc = salome.myStudy.FindComponent("SMESH")
647         if sc:
648             sb.LoadWith(sc, self)
649         pass
650     
651     def SetEnablePublish( self, theIsEnablePublish ):
652         """
653         Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
654         switch **off** publishing in the Study of mesh objects.
655         """
656        #self.SetEnablePublish(theIsEnablePublish)
657         SMESH._objref_SMESH_Gen.SetEnablePublish(self,theIsEnablePublish)
658         global notebook
659         notebook = salome_notebook.NoteBook( theIsEnablePublish )
660
661
662     def CreateMeshesFromUNV( self,theFileName ):
663         """
664         Create a Mesh object importing data from the given UNV file
665
666         Returns:
667                 an instance of class :class:`Mesh`
668         """
669
670         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromUNV(self,theFileName)
671         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
672         return aMesh
673
674     def CreateMeshesFromMED( self,theFileName ):
675         """
676         Create a Mesh object(s) importing data from the given MED file
677
678         Returns:
679                 a tuple ( list of class :class:`Mesh` instances, 
680                 :class:`SMESH.DriverMED_ReadStatus` )
681         """
682
683         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
684         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
685         return aMeshes, aStatus
686
687     def CreateMeshesFromSAUV( self,theFileName ):
688         """
689         Create a Mesh object(s) importing data from the given SAUV file
690
691         Returns:
692                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
693         """
694
695         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
696         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
697         return aMeshes, aStatus
698
699     def CreateMeshesFromSTL( self, theFileName ):
700         """
701         Create a Mesh object importing data from the given STL file
702
703         Returns:
704                 an instance of class :class:`Mesh`
705         """
706
707         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromSTL(self,theFileName)
708         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
709         return aMesh
710
711     def CreateMeshesFromCGNS( self, theFileName ):
712         """
713         Create Mesh objects importing data from the given CGNS file
714
715         Returns:
716                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
717         """
718
719         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
720         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
721         return aMeshes, aStatus
722
723     def CreateMeshesFromGMF( self, theFileName ):
724         """
725         Create a Mesh object importing data from the given GMF file.
726         GMF files must have .mesh extension for the ASCII format and .meshb for
727         the binary format.
728
729         Returns:
730                 ( an instance of class :class:`Mesh`, :class:`SMESH.ComputeError` )
731         """
732
733         aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
734                                                                         theFileName,
735                                                                         True)
736         if error.comment: print("*** CreateMeshesFromGMF() errors:\n", error.comment)
737         return Mesh(self, self.geompyD, aSmeshMesh), error
738
739     def Concatenate( self, meshes, uniteIdenticalGroups,
740                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
741                      name = "", meshToAppendTo = None):
742         """
743         Concatenate the given meshes into one mesh, optionally to meshToAppendTo.
744         All groups of input meshes will be present in the new mesh.
745
746         Parameters:
747                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
748                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
749                 mergeNodesAndElements: if True, equal nodes and elements are merged
750                 mergeTolerance: tolerance for merging nodes
751                 allGroups: forces creation of groups corresponding to every input mesh
752                 name: name of a new mesh
753                 meshToAppendTo: a mesh to append all given meshes
754
755         Returns:
756                 an instance of class :class:`Mesh`
757
758         See also: 
759                 :meth:`Mesh.Append`
760         """
761
762         if not meshes: return None
763         if not isinstance( meshes, list ):
764             meshes = [ meshes ]
765         for i,m in enumerate( meshes ):
766             if isinstance( m, Mesh ):
767                 meshes[i] = m.GetMesh()
768         mergeTolerance,Parameters,hasVars = ParseParameters( mergeTolerance )
769         if hasattr(meshes[0], "SetParameters"):
770             meshes[0].SetParameters( Parameters )
771         else:
772             meshes[0].GetMesh().SetParameters( Parameters )
773         if isinstance( meshToAppendTo, Mesh ):
774             meshToAppendTo = meshToAppendTo.GetMesh()
775         if allGroups:
776             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
777                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
778                 mergeTolerance,meshToAppendTo )
779         else:
780             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
781                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
782                 mergeTolerance,meshToAppendTo )
783
784         aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name )
785         return aMesh
786
787     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
788         """
789         Create a mesh by copying a part of another mesh.
790
791         Parameters:
792                 meshPart: a part of mesh to copy, either 
793                         :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
794                         To copy nodes or elements not forming any mesh object,
795                         pass result of :meth:`Mesh.GetIDSource` as *meshPart*
796                 meshName: a name of the new mesh
797                 toCopyGroups: to create in the new mesh groups the copied elements belongs to
798                 toKeepIDs: to preserve order of the copied elements or not
799
800         Returns:
801                 an instance of class :class:`Mesh`
802         """
803
804         if isinstance( meshPart, Mesh ):
805             meshPart = meshPart.GetMesh()
806         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
807         return Mesh(self, self.geompyD, mesh)
808
809     def CopyMeshWithGeom( self, sourceMesh, newGeom, meshName="", toCopyGroups=True,
810                           toReuseHypotheses=True, toCopyElements=True):
811         """
812         Create a mesh by copying a mesh definition (hypotheses and groups) to a new geometry.
813         It is supposed that the new geometry is a modified geometry of *sourceMesh*.
814         To facilitate and speed up the operation, consider using
815         "Set presentation parameters and sub-shapes from arguments" option in
816         a dialog of geometrical operation used to create the new geometry.
817
818         Parameters:
819                 sourceMesh: the mesh to copy definition of.
820                 newGeom: the new geometry.
821                 meshName: an optional name of the new mesh. If omitted, the mesh name is kept.
822                 toCopyGroups: to create groups in the new mesh.
823                 toReuseHypotheses: to reuse hypotheses of the *sourceMesh*.
824                 toCopyElements: to copy mesh elements present on non-modified sub-shapes of 
825                                 *sourceMesh*.
826         Returns:
827                 tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries )
828                 *invalidEntries* are study entries of objects whose
829                 counterparts are not found in the *newGeom*, followed by entries
830                 of mesh sub-objects that are invalid because they depend on a not found
831                 preceding sub-shape
832         """
833         if isinstance( sourceMesh, Mesh ):
834             sourceMesh = sourceMesh.GetMesh()
835
836         ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries = \
837            SMESH._objref_SMESH_Gen.CopyMeshWithGeom( self, sourceMesh, newGeom, meshName,
838                                                      toCopyGroups,
839                                                      toReuseHypotheses,
840                                                      toCopyElements)
841         return ( ok, Mesh(self, self.geompyD, newMesh),
842                  newGroups, newSubMeshes, newHypotheses, invalidEntries )
843
844     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
845         """
846         Return IDs of sub-shapes
847
848         Parameters:
849                 theMainObject (GEOM.GEOM_Object): a shape
850                 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
851         Returns:
852                 the list of integer values
853         """
854
855         return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
856
857     def GetPattern(self):
858         """
859         Create a pattern mapper.
860
861         Returns:
862                 an instance of :class:`SMESH.SMESH_Pattern`
863
864         :ref:`Example of Patterns usage <tui_pattern_mapping>`
865         """
866
867         return SMESH._objref_SMESH_Gen.GetPattern(self)
868
869     def SetBoundaryBoxSegmentation(self, nbSegments):
870         """
871         Set number of segments per diagonal of boundary box of geometry, by which
872         default segment length of appropriate 1D hypotheses is defined in GUI.
873         Default value is 10.
874         """
875
876         SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
877
878     # Filtering. Auxiliary functions:
879     # ------------------------------
880
881     def GetEmptyCriterion(self):
882         """
883         Create an empty criterion
884
885         Returns:
886                 :class:`SMESH.Filter.Criterion`
887         """
888
889         Type = self.EnumToLong(FT_Undefined)
890         Compare = self.EnumToLong(FT_Undefined)
891         Threshold = 0
892         ThresholdStr = ""
893         ThresholdID = ""
894         UnaryOp = self.EnumToLong(FT_Undefined)
895         BinaryOp = self.EnumToLong(FT_Undefined)
896         Tolerance = 1e-07
897         TypeOfElement = ALL
898         Precision = -1 ##@1e-07
899         return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
900                                 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
901
902     def GetCriterion(self,elementType,
903                      CritType,
904                      Compare = FT_EqualTo,
905                      Threshold="",
906                      UnaryOp=FT_Undefined,
907                      BinaryOp=FT_Undefined,
908                      Tolerance=1e-07):
909         """
910         Create a criterion by the given parameters
911         Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
912
913         Parameters:
914                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
915                 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
916                         Note that the items starting from FT_LessThan are not suitable for *CritType*.
917                 Compare:  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
918                 Threshold: the threshold value (range of ids as string, shape, numeric)
919                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
920                 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
921                         SMESH.FT_Undefined
922                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
923                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
924
925         Returns:
926                 :class:`SMESH.Filter.Criterion`
927
928         Example: :ref:`combining_filters`
929         """
930
931         if not CritType in SMESH.FunctorType._items:
932             raise TypeError("CritType should be of SMESH.FunctorType")
933         aCriterion               = self.GetEmptyCriterion()
934         aCriterion.TypeOfElement = elementType
935         aCriterion.Type          = self.EnumToLong(CritType)
936         aCriterion.Tolerance     = Tolerance
937
938         aThreshold = Threshold
939
940         if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
941             aCriterion.Compare = self.EnumToLong(Compare)
942         elif Compare == "=" or Compare == "==":
943             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
944         elif Compare == "<":
945             aCriterion.Compare = self.EnumToLong(FT_LessThan)
946         elif Compare == ">":
947             aCriterion.Compare = self.EnumToLong(FT_MoreThan)
948         elif Compare != FT_Undefined:
949             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
950             aThreshold = Compare
951
952         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
953                         FT_BelongToCylinder, FT_LyingOnGeom]:
954             # Check that Threshold is GEOM object
955             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
956                 aCriterion.ThresholdStr = GetName(aThreshold)
957                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
958                 if not aCriterion.ThresholdID:
959                     name = aCriterion.ThresholdStr
960                     if not name:
961                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
962                     geompyD = aThreshold.GetGen()
963                     aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
964             # or a name of GEOM object
965             elif isinstance( aThreshold, str ):
966                 aCriterion.ThresholdStr = aThreshold
967             else:
968                 raise TypeError("The Threshold should be a shape.")
969             if isinstance(UnaryOp,float):
970                 aCriterion.Tolerance = UnaryOp
971                 UnaryOp = FT_Undefined
972                 pass
973         elif CritType == FT_BelongToMeshGroup:
974             # Check that Threshold is a group
975             if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
976                 if aThreshold.GetType() != elementType:
977                     raise ValueError("Group type mismatches Element type")
978                 aCriterion.ThresholdStr = aThreshold.GetName()
979                 aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
980                 study = salome.myStudy
981                 if study:
982                     so = study.FindObjectIOR( aCriterion.ThresholdID )
983                     if so:
984                         entry = so.GetID()
985                         if entry:
986                             aCriterion.ThresholdID = entry
987             else:
988                 raise TypeError("The Threshold should be a Mesh Group")
989         elif CritType == FT_RangeOfIds:
990             # Check that Threshold is string
991             if isinstance(aThreshold, str):
992                 aCriterion.ThresholdStr = aThreshold
993             else:
994                 raise TypeError("The Threshold should be a string.")
995         elif CritType == FT_CoplanarFaces:
996             # Check the Threshold
997             if isinstance(aThreshold, int):
998                 aCriterion.ThresholdID = str(aThreshold)
999             elif isinstance(aThreshold, str):
1000                 ID = int(aThreshold)
1001                 if ID < 1:
1002                     raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
1003                 aCriterion.ThresholdID = aThreshold
1004             else:
1005                 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
1006         elif CritType == FT_ConnectedElements:
1007             # Check the Threshold
1008             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
1009                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
1010                 if not aCriterion.ThresholdID:
1011                     name = aThreshold.GetName()
1012                     if not name:
1013                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
1014                     geompyD = aThreshold.GetGen()
1015                     aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
1016             elif isinstance(aThreshold, int): # node id
1017                 aCriterion.Threshold = aThreshold
1018             elif isinstance(aThreshold, list): # 3 point coordinates
1019                 if len( aThreshold ) < 3:
1020                     raise ValueError("too few point coordinates, must be 3")
1021                 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
1022             elif isinstance(aThreshold, str):
1023                 if aThreshold.isdigit():
1024                     aCriterion.Threshold = aThreshold # node id
1025                 else:
1026                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
1027             else:
1028                 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
1029                       "or a list of point coordinates and not '%s'"%aThreshold)
1030         elif CritType == FT_ElemGeomType:
1031             # Check the Threshold
1032             try:
1033                 aCriterion.Threshold = self.EnumToLong(aThreshold)
1034                 assert( aThreshold in SMESH.GeometryType._items )
1035             except:
1036                 if isinstance(aThreshold, int):
1037                     aCriterion.Threshold = aThreshold
1038                 else:
1039                     raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
1040                 pass
1041             pass
1042         elif CritType == FT_EntityType:
1043             # Check the Threshold
1044             try:
1045                 aCriterion.Threshold = self.EnumToLong(aThreshold)
1046                 assert( aThreshold in SMESH.EntityType._items )
1047             except:
1048                 if isinstance(aThreshold, int):
1049                     aCriterion.Threshold = aThreshold
1050                 else:
1051                     raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
1052                 pass
1053             pass
1054
1055         elif CritType == FT_GroupColor:
1056             # Check the Threshold
1057             try:
1058                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
1059             except:
1060                 raise TypeError("The threshold value should be of SALOMEDS.Color type")
1061             pass
1062         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
1063                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
1064                           FT_BareBorderFace, FT_BareBorderVolume,
1065                           FT_OverConstrainedFace, FT_OverConstrainedVolume,
1066                           FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
1067             # At this point the Threshold is unnecessary
1068             if aThreshold ==  FT_LogicalNOT:
1069                 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1070             elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1071                 aCriterion.BinaryOp = aThreshold
1072         else:
1073             # Check Threshold
1074             try:
1075                 aThreshold = float(aThreshold)
1076                 aCriterion.Threshold = aThreshold
1077             except:
1078                 raise TypeError("The Threshold should be a number.")
1079                 return None
1080
1081         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT:
1082             aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1083
1084         if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1085             aCriterion.BinaryOp = self.EnumToLong(Threshold)
1086
1087         if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1088             aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1089
1090         if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1091             aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1092
1093         return aCriterion
1094
1095     def GetFilter(self,elementType,
1096                   CritType=FT_Undefined,
1097                   Compare=FT_EqualTo,
1098                   Threshold="",
1099                   UnaryOp=FT_Undefined,
1100                   Tolerance=1e-07,
1101                   mesh=None):
1102         """
1103         Create a filter with the given parameters
1104
1105         Parameters:
1106                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1107                 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1108                         Note that the items starting from FT_LessThan are not suitable for CritType.
1109                 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1110                 Threshold: the threshold value (range of ids as string, shape, numeric)
1111                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1112                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1113                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1114                 mesh: the mesh to initialize the filter with
1115
1116         Returns:
1117                 :class:`SMESH.Filter`
1118
1119         Examples:
1120                See :doc:`Filters usage examples <tui_filters>`
1121         """
1122
1123         aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1124         aFilterMgr = self.CreateFilterManager()
1125         aFilter = aFilterMgr.CreateFilter()
1126         aCriteria = []
1127         aCriteria.append(aCriterion)
1128         aFilter.SetCriteria(aCriteria)
1129         if mesh:
1130             if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1131             else                       : aFilter.SetMesh( mesh )
1132         aFilterMgr.UnRegister()
1133         return aFilter
1134
1135     def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1136         """
1137         Create a filter from criteria
1138
1139         Parameters:
1140                 criteria: a list of :class:`SMESH.Filter.Criterion`
1141                 binOp: binary operator used when binary operator of criteria is undefined
1142
1143         Returns:
1144                 :class:`SMESH.Filter`
1145
1146         Examples:
1147                See :doc:`Filters usage examples <tui_filters>`
1148         """
1149
1150         for i in range( len( criteria ) - 1 ):
1151             if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1152                 criteria[i].BinaryOp = self.EnumToLong( binOp )
1153         aFilterMgr = self.CreateFilterManager()
1154         aFilter = aFilterMgr.CreateFilter()
1155         aFilter.SetCriteria(criteria)
1156         aFilterMgr.UnRegister()
1157         return aFilter
1158
1159     def GetFunctor(self,theCriterion):
1160         """
1161         Create a numerical functor by its type
1162
1163         Parameters:
1164                 theCriterion (SMESH.FunctorType): functor type.
1165                         Note that not all items correspond to numerical functors.
1166
1167         Returns:
1168                 :class:`SMESH.NumericalFunctor`
1169         """
1170
1171         if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1172             return theCriterion
1173         aFilterMgr = self.CreateFilterManager()
1174         functor = None
1175         if theCriterion == FT_AspectRatio:
1176             functor = aFilterMgr.CreateAspectRatio()
1177         elif theCriterion == FT_AspectRatio3D:
1178             functor = aFilterMgr.CreateAspectRatio3D()
1179         elif theCriterion == FT_Warping:
1180             functor = aFilterMgr.CreateWarping()
1181         elif theCriterion == FT_MinimumAngle:
1182             functor = aFilterMgr.CreateMinimumAngle()
1183         elif theCriterion == FT_Taper:
1184             functor = aFilterMgr.CreateTaper()
1185         elif theCriterion == FT_Skew:
1186             functor = aFilterMgr.CreateSkew()
1187         elif theCriterion == FT_Area:
1188             functor = aFilterMgr.CreateArea()
1189         elif theCriterion == FT_Volume3D:
1190             functor = aFilterMgr.CreateVolume3D()
1191         elif theCriterion == FT_MaxElementLength2D:
1192             functor = aFilterMgr.CreateMaxElementLength2D()
1193         elif theCriterion == FT_MaxElementLength3D:
1194             functor = aFilterMgr.CreateMaxElementLength3D()
1195         elif theCriterion == FT_MultiConnection:
1196             functor = aFilterMgr.CreateMultiConnection()
1197         elif theCriterion == FT_MultiConnection2D:
1198             functor = aFilterMgr.CreateMultiConnection2D()
1199         elif theCriterion == FT_Length:
1200             functor = aFilterMgr.CreateLength()
1201         elif theCriterion == FT_Length2D:
1202             functor = aFilterMgr.CreateLength2D()
1203         elif theCriterion == FT_Length3D:
1204             functor = aFilterMgr.CreateLength3D()
1205         elif theCriterion == FT_Deflection2D:
1206             functor = aFilterMgr.CreateDeflection2D()
1207         elif theCriterion == FT_NodeConnectivityNumber:
1208             functor = aFilterMgr.CreateNodeConnectivityNumber()
1209         elif theCriterion == FT_BallDiameter:
1210             functor = aFilterMgr.CreateBallDiameter()
1211         else:
1212             print("Error: given parameter is not numerical functor type.")
1213         aFilterMgr.UnRegister()
1214         return functor
1215
1216     def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1217         """
1218         Create hypothesis
1219
1220         Parameters:
1221                 theHType (string): mesh hypothesis type
1222                 theLibName (string): mesh plug-in library name
1223
1224         Returns:
1225                 created hypothesis instance
1226         """
1227         hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1228
1229         if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1230             return hyp
1231
1232         # wrap hypothesis methods
1233         for meth_name in dir( hyp.__class__ ):
1234             if not meth_name.startswith("Get") and \
1235                not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1236                 method = getattr ( hyp.__class__, meth_name )
1237                 if callable(method):
1238                     setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1239
1240         return hyp
1241
1242     def GetHypothesisParameterValues( self, hypType, libName, mesh, shape, initParams ):
1243         """
1244         Create hypothesis initialized according to parameters
1245
1246         Parameters:
1247                 hypType (string): hypothesis type
1248                 libName (string): plug-in library name
1249                 mesh: optional mesh by which a hypotheses can initialize self
1250                 shape: optional geometry  by size of which a hypotheses can initialize self
1251                 initParams: structure SMESH.HypInitParams defining how to initialize a hypothesis
1252
1253         Returns:
1254                 created hypothesis instance
1255         """
1256         if isinstance( mesh, Mesh ):
1257             mesh = mesh.GetMesh()
1258         if isinstance( initParams, (bool,int)):
1259             initParams = SMESH.HypInitParams( not initParams, 1.0, not mesh )
1260         return SMESH._objref_SMESH_Gen.GetHypothesisParameterValues(self, hypType, libName,
1261                                                                     mesh, shape, initParams )
1262
1263     def GetMeshInfo(self, obj):
1264         """
1265         Get the mesh statistic.
1266
1267         Returns:
1268                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1269         """
1270
1271         if isinstance( obj, Mesh ):
1272             obj = obj.GetMesh()
1273         d = {}
1274         if hasattr(obj, "GetMeshInfo"):
1275             values = obj.GetMeshInfo()
1276             for i in range(SMESH.Entity_Last._v):
1277                 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1278             pass
1279         return d
1280
1281     def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1282         """
1283         Get minimum distance between two objects
1284
1285         * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1286         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1287
1288         Parameters:
1289                 src1 (SMESH.SMESH_IDSource): first source object
1290                 src2 (SMESH.SMESH_IDSource): second source object
1291                 id1 (int): node/element id from the first source
1292                 id2 (int): node/element id from the second (or first) source
1293                 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1294                 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1295
1296         Returns:
1297                 minimum distance value
1298
1299         See also: 
1300                 :meth:`GetMinDistance`
1301         """
1302
1303         result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1304         if result is None:
1305             result = 0.0
1306         else:
1307             result = result.value
1308         return result
1309
1310     def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1311         """
1312         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1313
1314         * If *src2* is None, and *id2*  = 0, distance from *src1* / *id1* to the origin is computed.
1315         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1316
1317         Parameters:
1318                 src1 (SMESH.SMESH_IDSource): first source object
1319                 src2 (SMESH.SMESH_IDSource): second source object
1320                 id1 (int): node/element id from the first source
1321                 id2 (int): node/element id from the second (or first) source
1322                 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1323                 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1324
1325         Returns:
1326                 :class:`SMESH.Measure` structure or None if input data is invalid
1327         See also: 
1328                 :meth:`MinDistance`
1329         """
1330
1331         if isinstance(src1, Mesh): src1 = src1.mesh
1332         if isinstance(src2, Mesh): src2 = src2.mesh
1333         if src2 is None and id2 != 0: src2 = src1
1334         if not hasattr(src1, "_narrow"): return None
1335         src1 = src1._narrow(SMESH.SMESH_IDSource)
1336         if not src1: return None
1337         unRegister = genObjUnRegister()
1338         if id1 != 0:
1339             m = src1.GetMesh()
1340             e = m.GetMeshEditor()
1341             if isElem1:
1342                 src1 = e.MakeIDSource([id1], SMESH.FACE)
1343             else:
1344                 src1 = e.MakeIDSource([id1], SMESH.NODE)
1345             unRegister.set( src1 )
1346             pass
1347         if hasattr(src2, "_narrow"):
1348             src2 = src2._narrow(SMESH.SMESH_IDSource)
1349             if src2 and id2 != 0:
1350                 m = src2.GetMesh()
1351                 e = m.GetMeshEditor()
1352                 if isElem2:
1353                     src2 = e.MakeIDSource([id2], SMESH.FACE)
1354                 else:
1355                     src2 = e.MakeIDSource([id2], SMESH.NODE)
1356                 unRegister.set( src2 )
1357                 pass
1358             pass
1359         aMeasurements = self.CreateMeasurements()
1360         unRegister.set( aMeasurements )
1361         result = aMeasurements.MinDistance(src1, src2)
1362         return result
1363
1364     def BoundingBox(self, objects):
1365         """
1366         Get bounding box of the specified object(s)
1367
1368         Parameters:
1369                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1370
1371         Returns:
1372                 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1373
1374         See also: 
1375                :meth:`GetBoundingBox`
1376         """
1377
1378         result = self.GetBoundingBox(objects)
1379         if result is None:
1380             result = (0.0,)*6
1381         else:
1382             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1383         return result
1384
1385     def GetBoundingBox(self, objects):
1386         """
1387         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1388
1389         Parameters:
1390                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1391
1392         Returns:
1393                 :class:`SMESH.Measure` structure
1394
1395         See also: 
1396                 :meth:`BoundingBox`
1397         """
1398
1399         if isinstance(objects, tuple):
1400             objects = list(objects)
1401         if not isinstance(objects, list):
1402             objects = [objects]
1403         srclist = []
1404         for o in objects:
1405             if isinstance(o, Mesh):
1406                 srclist.append(o.mesh)
1407             elif hasattr(o, "_narrow"):
1408                 src = o._narrow(SMESH.SMESH_IDSource)
1409                 if src: srclist.append(src)
1410                 pass
1411             pass
1412         aMeasurements = self.CreateMeasurements()
1413         result = aMeasurements.BoundingBox(srclist)
1414         aMeasurements.UnRegister()
1415         return result
1416
1417     def GetLength(self, obj):
1418         """
1419         Get sum of lengths of all 1D elements in the mesh object.
1420
1421         Parameters:
1422                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1423
1424         Returns:
1425                 sum of lengths of all 1D elements
1426         """
1427
1428         if isinstance(obj, Mesh): obj = obj.mesh
1429         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1430         aMeasurements = self.CreateMeasurements()
1431         value = aMeasurements.Length(obj)
1432         aMeasurements.UnRegister()
1433         return value
1434
1435     def GetArea(self, obj):
1436         """
1437         Get sum of areas of all 2D elements in the mesh object.
1438
1439         Parameters:
1440                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1441
1442         Returns:
1443                 sum of areas of all 2D elements
1444         """
1445
1446         if isinstance(obj, Mesh): obj = obj.mesh
1447         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1448         aMeasurements = self.CreateMeasurements()
1449         value = aMeasurements.Area(obj)
1450         aMeasurements.UnRegister()
1451         return value
1452
1453     def GetVolume(self, obj):
1454         """
1455         Get sum of volumes of all 3D elements in the mesh object.
1456
1457         Parameters:
1458                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1459
1460         Returns:
1461                 sum of volumes of all 3D elements
1462         """
1463
1464         if isinstance(obj, Mesh): obj = obj.mesh
1465         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1466         aMeasurements = self.CreateMeasurements()
1467         value = aMeasurements.Volume(obj)
1468         aMeasurements.UnRegister()
1469         return value
1470
1471     def GetGravityCenter(self, obj):
1472         """
1473         Get gravity center of all nodes of a mesh object.
1474         
1475         Parameters:            
1476                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1477
1478         Returns:        
1479                 Three components of the gravity center (x,y,z)
1480
1481         See also: 
1482                 :meth:`Mesh.BaryCenter`
1483         """
1484         if isinstance(obj, Mesh): obj = obj.mesh
1485         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1486         aMeasurements = self.CreateMeasurements()
1487         pointStruct = aMeasurements.GravityCenter(obj)
1488         aMeasurements.UnRegister()
1489         return pointStruct.x, pointStruct.y, pointStruct.z
1490
1491     def GetAngle(self, p1, p2, p3 ):
1492         """
1493         Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3)
1494
1495         Parameters:            
1496                 p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct 
1497                           or list [x,y,z]
1498
1499         Returns:        
1500             Angle in radians
1501         """
1502         if isinstance( p1, list ): p1 = PointStruct(*p1)
1503         if isinstance( p2, list ): p2 = PointStruct(*p2)
1504         if isinstance( p3, list ): p3 = PointStruct(*p3)
1505
1506         aMeasurements = self.CreateMeasurements()
1507         angle = aMeasurements.Angle(p1,p2,p3)
1508         aMeasurements.UnRegister()
1509
1510         return angle
1511
1512
1513     pass # end of class smeshBuilder
1514
1515 import omniORB
1516 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1517 """Registering the new proxy for SMESH.SMESH_Gen"""
1518
1519
1520 def New( instance=None, instanceGeom=None):
1521     """
1522     Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1523     interface to create or load meshes.
1524
1525     Typical use is::
1526
1527         import salome
1528         salome.salome_init()
1529         from salome.smesh import smeshBuilder
1530         smesh = smeshBuilder.New()
1531
1532     Parameters:
1533         instance:      CORBA proxy of SMESH Engine. If None, the default Engine is used.
1534         instanceGeom:  CORBA proxy of GEOM  Engine. If None, the default Engine is used.
1535     Returns:
1536         :class:`smeshBuilder` instance
1537     """
1538     global engine
1539     global smeshInst
1540     global doLcc
1541     if instance and isinstance( instance, SALOMEDS._objref_Study ):
1542         import sys
1543         sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1544         instance = None
1545     engine = instance
1546     if engine is None:
1547         doLcc = True
1548     smeshInst = smeshBuilder()
1549     assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1550     smeshInst.init_smesh(instanceGeom)
1551     return smeshInst
1552
1553
1554 # Public class: Mesh
1555 # ==================
1556
1557
1558 class Mesh(metaclass = MeshMeta):
1559     """
1560     This class allows defining and managing a mesh.
1561     It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1562     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1563     new nodes and elements and by changing the existing entities), to get information
1564     about a mesh and to export a mesh in different formats.
1565     """    
1566
1567     geom = 0
1568     mesh = 0
1569     editor = 0
1570
1571     def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1572
1573         """
1574         Constructor
1575
1576         Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1577         sets the GUI name of this mesh to *name*.
1578
1579         Parameters:
1580                 smeshpyD: an instance of smeshBuilder class
1581                 geompyD: an instance of geomBuilder class
1582                 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1583                 name: Study name of the mesh
1584         """
1585
1586         self.smeshpyD = smeshpyD
1587         self.geompyD = geompyD
1588         if obj is None:
1589             obj = 0
1590         objHasName = False
1591         if obj != 0:
1592             if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1593                 self.geom = obj
1594                 objHasName = True
1595                 # publish geom of mesh (issue 0021122)
1596                 if not self.geom.GetStudyEntry():
1597                     objHasName = False
1598                     geompyD.init_geom()
1599                     if name:
1600                         geo_name = name + " shape"
1601                     else:
1602                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1603                     geompyD.addToStudy( self.geom, geo_name )
1604                 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1605
1606             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1607                 self.SetMesh(obj)
1608         else:
1609             self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1610         if name:
1611             self.smeshpyD.SetName(self.mesh, name)
1612         elif objHasName:
1613             self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1614
1615         if not self.geom:
1616             self.geom = self.mesh.GetShapeToMesh()
1617
1618         self.editor   = self.mesh.GetMeshEditor()
1619         self.functors = [None] * SMESH.FT_Undefined._v
1620
1621         # set self to algoCreator's
1622         for attrName in dir(self):
1623             attr = getattr( self, attrName )
1624             if isinstance( attr, algoCreator ):
1625                 setattr( self, attrName, attr.copy( self ))
1626                 pass
1627             pass
1628         pass
1629
1630     def __del__(self):
1631         """
1632         Destructor. Clean-up resources
1633         """
1634         if self.mesh:
1635             #self.mesh.UnRegister()
1636             pass
1637         pass
1638
1639     def SetMesh(self, theMesh):
1640         """
1641         Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1642
1643         Parameters:
1644                 theMesh: a :class:`SMESH.SMESH_Mesh` object
1645         """
1646         # do not call Register() as this prevents mesh servant deletion at closing study
1647         #if self.mesh: self.mesh.UnRegister()
1648         self.mesh = theMesh
1649         if self.mesh:
1650             #self.mesh.Register()
1651             self.geom = self.mesh.GetShapeToMesh()
1652             if self.geom:
1653                 self.geompyD = self.geom.GetGen()
1654                 pass
1655         pass
1656
1657     def GetMesh(self):
1658         """
1659         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1660
1661         Returns:
1662                 a :class:`SMESH.SMESH_Mesh` object
1663         """
1664
1665         return self.mesh
1666
1667     def GetEngine(self):
1668         """
1669         Return a smeshBuilder instance created this mesh
1670         """
1671         return self.smeshpyD
1672
1673     def GetGeomEngine(self):
1674         """
1675         Return a geomBuilder instance
1676         """
1677         return self.geompyD
1678
1679     def GetName(self):
1680         """
1681         Get the name of the mesh
1682
1683         Returns:
1684                 the name of the mesh as a string
1685         """
1686
1687         name = GetName(self.GetMesh())
1688         return name
1689
1690     def SetName(self, name):
1691         """
1692         Set a name to the mesh
1693
1694         Parameters:
1695                 name: a new name of the mesh
1696         """
1697
1698         self.smeshpyD.SetName(self.GetMesh(), name)
1699
1700     def GetSubMesh(self, geom, name):
1701         """
1702         Get a sub-mesh object associated to a *geom* geometrical object.
1703
1704         Parameters:
1705                 geom: a geometrical object (shape)
1706                 name: a name for the sub-mesh in the Object Browser
1707
1708         Returns:
1709                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1710                 which lies on the given shape
1711
1712         Note:
1713                 A sub-mesh is implicitly created when a sub-shape is specified at
1714                 creating an algorithm, for example::
1715
1716                    algo1D = mesh.Segment(geom=Edge_1)
1717
1718                 create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1719                 The created sub-mesh can be retrieved from the algorithm::
1720
1721                    submesh = algo1D.GetSubMesh()
1722         """
1723
1724         AssureGeomPublished( self, geom, name )
1725         submesh = self.mesh.GetSubMesh( geom, name )
1726         return submesh
1727
1728     def GetShape(self):
1729         """
1730         Return the shape associated to the mesh
1731
1732         Returns:
1733                 a GEOM_Object
1734         """
1735
1736         return self.geom
1737
1738     def SetShape(self, geom):
1739         """
1740         Associate the given shape to the mesh (entails the recreation of the mesh)
1741
1742         Parameters:
1743                 geom: the shape to be meshed (GEOM_Object)
1744         """
1745
1746         self.mesh = self.smeshpyD.CreateMesh(geom)
1747
1748     def HasShapeToMesh(self):
1749         """
1750         Return ``True`` if this mesh is based on geometry
1751         """
1752         return self.mesh.HasShapeToMesh()
1753
1754     def Load(self):
1755         """
1756         Load mesh from the study after opening the study
1757         """
1758         self.mesh.Load()
1759
1760     def IsReadyToCompute(self, theSubObject):
1761         """
1762         Return true if the hypotheses are defined well
1763
1764         Parameters:
1765                 theSubObject: a sub-shape of a mesh shape
1766
1767         Returns:
1768                 True or False
1769         """
1770
1771         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1772
1773     def GetAlgoState(self, theSubObject):
1774         """
1775         Return errors of hypotheses definition.
1776         The list of errors is empty if everything is OK.
1777
1778         Parameters:
1779                 theSubObject: a sub-shape of a mesh shape
1780
1781         Returns:
1782                 a list of errors
1783         """
1784
1785         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1786
1787     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1788         """
1789         Return a geometrical object on which the given element was built.
1790         The returned geometrical object, if not nil, is either found in the
1791         study or published by this method with the given name
1792
1793         Parameters:
1794             theElementID: the id of the mesh element
1795             theGeomName: the user-defined name of the geometrical object
1796
1797         Returns:
1798             GEOM.GEOM_Object instance
1799         """
1800
1801         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1802
1803     def MeshDimension(self):
1804         """
1805         Return the mesh dimension depending on the dimension of the underlying shape
1806         or, if the mesh is not based on any shape, basing on deimension of elements
1807
1808         Returns:
1809                 mesh dimension as an integer value [0,3]
1810         """
1811
1812         if self.mesh.HasShapeToMesh():
1813             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1814             if len( shells ) > 0 :
1815                 return 3
1816             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1817                 return 2
1818             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1819                 return 1
1820             else:
1821                 return 0;
1822         else:
1823             if self.NbVolumes() > 0: return 3
1824             if self.NbFaces()   > 0: return 2
1825             if self.NbEdges()   > 0: return 1
1826         return 0
1827
1828     def Evaluate(self, geom=0):
1829         """
1830         Evaluate size of prospective mesh on a shape
1831
1832         Returns:
1833                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1834                 To know predicted number of e.g. edges, inquire it this way::
1835
1836                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1837         """
1838
1839         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1840             if self.geom == 0:
1841                 geom = self.mesh.GetShapeToMesh()
1842             else:
1843                 geom = self.geom
1844         return self.smeshpyD.Evaluate(self.mesh, geom)
1845
1846
1847     def Compute(self, geom=0, discardModifs=False, refresh=False):
1848         """
1849         Compute the mesh and return the status of the computation
1850
1851         Parameters:
1852                 geom: geomtrical shape on which mesh data should be computed
1853                 discardModifs: if True and the mesh has been edited since
1854                         a last total re-compute and that may prevent successful partial re-compute,
1855                         then the mesh is cleaned before Compute()
1856                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1857
1858         Returns:
1859                 True or False
1860         """
1861
1862         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1863             if self.geom == 0:
1864                 geom = self.mesh.GetShapeToMesh()
1865             else:
1866                 geom = self.geom
1867         ok = False
1868         try:
1869             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1870                 self.mesh.Clear()
1871             ok = self.smeshpyD.Compute(self.mesh, geom)
1872         except SALOME.SALOME_Exception as ex:
1873             print("Mesh computation failed, exception caught:")
1874             print("    ", ex.details.text)
1875         except:
1876             import traceback
1877             print("Mesh computation failed, exception caught:")
1878             traceback.print_exc()
1879         if True:#not ok:
1880             allReasons = ""
1881
1882             # Treat compute errors
1883             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1884             shapeText = ""
1885             for err in computeErrors:
1886                 if self.mesh.HasShapeToMesh():
1887                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1888                 errText = ""
1889                 stdErrors = ["OK",                   #COMPERR_OK
1890                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1891                              "std::exception",       #COMPERR_STD_EXCEPTION
1892                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1893                              "..",                   #COMPERR_SLM_EXCEPTION
1894                              "Unknown exception",    #COMPERR_EXCEPTION
1895                              "Memory allocation problem", #COMPERR_MEMORY_PB
1896                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1897                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1898                              "Warning",              #COMPERR_WARNING
1899                              "Computation cancelled",#COMPERR_CANCELED
1900                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1901                 if err.code > 0:
1902                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1903                 else:
1904                     errText = "code %s" % -err.code
1905                 if errText: errText += ". "
1906                 errText += err.comment
1907                 if allReasons: allReasons += "\n"
1908                 if ok:
1909                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1910                 else:
1911                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1912                 pass
1913
1914             # Treat hyp errors
1915             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1916             for err in errors:
1917                 if err.isGlobalAlgo:
1918                     glob = "global"
1919                 else:
1920                     glob = "local"
1921                     pass
1922                 dim = err.algoDim
1923                 name = err.algoName
1924                 if len(name) == 0:
1925                     reason = '%s %sD algorithm is missing' % (glob, dim)
1926                 elif err.state == HYP_MISSING:
1927                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1928                               % (glob, dim, name, dim))
1929                 elif err.state == HYP_NOTCONFORM:
1930                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1931                 elif err.state == HYP_BAD_PARAMETER:
1932                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1933                               % ( glob, dim, name ))
1934                 elif err.state == HYP_BAD_GEOMETRY:
1935                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1936                               'geometry' % ( glob, dim, name ))
1937                 elif err.state == HYP_HIDDEN_ALGO:
1938                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1939                               'algorithm of upper dimension generating %sD mesh'
1940                               % ( glob, dim, name, glob, dim ))
1941                 else:
1942                     reason = ("For unknown reason. "
1943                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1944                     pass
1945                 if allReasons: allReasons += "\n"
1946                 allReasons += "-  " + reason
1947                 pass
1948             if not ok or allReasons != "":
1949                 msg = '"' + GetName(self.mesh) + '"'
1950                 if ok: msg += " has been computed with warnings"
1951                 else:  msg += " has not been computed"
1952                 if allReasons != "": msg += ":"
1953                 else:                msg += "."
1954                 print(msg)
1955                 print(allReasons)
1956             pass
1957         if salome.sg.hasDesktop():
1958             if not isinstance( refresh, list): # not a call from subMesh.Compute()
1959                 if refresh: salome.sg.updateObjBrowser()
1960
1961         return ok
1962
1963     def GetComputeErrors(self, shape=0 ):
1964         """
1965         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1966         """
1967
1968         if shape == 0:
1969             shape = self.mesh.GetShapeToMesh()
1970         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1971
1972     def GetSubShapeName(self, subShapeID ):
1973         """
1974         Return a name of a sub-shape by its ID.
1975         Possible variants (for *subShapeID* == 3):
1976
1977                 - **"Face_12"** - published sub-shape
1978                 - **FACE #3** - not published sub-shape
1979                 - **sub-shape #3** - invalid sub-shape ID
1980                 - **#3** - error in this function
1981
1982         Parameters:
1983                 subShapeID: a unique ID of a sub-shape
1984
1985         Returns:
1986                 a string describing the sub-shape
1987
1988         """
1989
1990         if not self.mesh.HasShapeToMesh():
1991             return ""
1992         try:
1993             shapeText = ""
1994             mainIOR  = salome.orb.object_to_string( self.GetShape() )
1995             s = salome.myStudy
1996             mainSO = s.FindObjectIOR(mainIOR)
1997             if mainSO:
1998                 if subShapeID == 1:
1999                     shapeText = '"%s"' % mainSO.GetName()
2000                 subIt = s.NewChildIterator(mainSO)
2001                 while subIt.More():
2002                     subSO = subIt.Value()
2003                     subIt.Next()
2004                     obj = subSO.GetObject()
2005                     if not obj: continue
2006                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
2007                     if not go: continue
2008                     try:
2009                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
2010                     except:
2011                         continue
2012                     if ids == subShapeID:
2013                         shapeText = '"%s"' % subSO.GetName()
2014                         break
2015             if not shapeText:
2016                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
2017                 if shape:
2018                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
2019                 else:
2020                     shapeText = 'sub-shape #%s' % (subShapeID)
2021         except:
2022             shapeText = "#%s" % (subShapeID)
2023         return shapeText
2024
2025     def GetFailedShapes(self, publish=False):
2026         """
2027         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
2028         error of an algorithm
2029
2030         Parameters:
2031                 publish: if *True*, the returned groups will be published in the study
2032
2033         Returns:
2034                 a list of GEOM groups each named after a failed algorithm
2035         """
2036
2037
2038         algo2shapes = {}
2039         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
2040         for err in computeErrors:
2041             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
2042             if not shape: continue
2043             if err.algoName in algo2shapes:
2044                 algo2shapes[ err.algoName ].append( shape )
2045             else:
2046                 algo2shapes[ err.algoName ] = [ shape ]
2047             pass
2048
2049         groups = []
2050         for algoName, shapes in list(algo2shapes.items()):
2051             while shapes:
2052                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
2053                 otherTypeShapes = []
2054                 sameTypeShapes  = []
2055                 group = self.geompyD.CreateGroup( self.geom, groupType )
2056                 for shape in shapes:
2057                     if shape.GetShapeType() == shapes[0].GetShapeType():
2058                         sameTypeShapes.append( shape )
2059                     else:
2060                         otherTypeShapes.append( shape )
2061                 self.geompyD.UnionList( group, sameTypeShapes )
2062                 if otherTypeShapes:
2063                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
2064                 else:
2065                     group.SetName( algoName )
2066                 groups.append( group )
2067                 shapes = otherTypeShapes
2068             pass
2069         if publish:
2070             for group in groups:
2071                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
2072         return groups
2073
2074     def GetMeshOrder(self):
2075         """
2076         Return sub-mesh objects list in meshing order
2077
2078         Returns:
2079                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2080         """
2081
2082         return self.mesh.GetMeshOrder()
2083
2084     def SetMeshOrder(self, submeshes):
2085         """
2086         Set priority of sub-meshes. It works in two ways:
2087         
2088         * For sub-meshes with assigned algorithms of same dimension generating mesh of
2089           *several dimensions*, it sets the order in which the sub-meshes are computed.
2090         * For the rest sub-meshes, it sets the order in which the sub-meshes are checked
2091           when looking for meshing parameters to apply to a sub-shape. To impose the 
2092           order in which sub-meshes with uni-dimensional algorithms are computed, 
2093           call **submesh.Compute()** in a desired order.
2094
2095         Parameters:
2096                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2097         """
2098
2099         return self.mesh.SetMeshOrder(submeshes)
2100
2101     def Clear(self, refresh=False):
2102         """
2103         Remove all nodes and elements generated on geometry. Imported elements remain.
2104
2105         Parameters:
2106                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2107         """
2108
2109         self.mesh.Clear()
2110         if ( salome.sg.hasDesktop() ):
2111             if refresh: salome.sg.updateObjBrowser()
2112
2113     def ClearSubMesh(self, geomId, refresh=False):
2114         """
2115         Remove all nodes and elements of indicated shape
2116
2117         Parameters:
2118                 geomId: the ID of a sub-shape to remove elements on
2119                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2120         """
2121
2122         self.mesh.ClearSubMesh(geomId)
2123         if salome.sg.hasDesktop():
2124             if refresh: salome.sg.updateObjBrowser()
2125
2126     def AutomaticTetrahedralization(self, fineness=0):
2127         """
2128         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
2129
2130         Parameters:
2131                 fineness: [0.0,1.0] defines mesh fineness
2132
2133         Returns:
2134                 True or False
2135         """
2136
2137         dim = self.MeshDimension()
2138         # assign hypotheses
2139         self.RemoveGlobalHypotheses()
2140         self.Segment().AutomaticLength(fineness)
2141         if dim > 1 :
2142             self.Triangle().LengthFromEdges()
2143             pass
2144         if dim > 2 :
2145             self.Tetrahedron()
2146             pass
2147         return self.Compute()
2148
2149     def AutomaticHexahedralization(self, fineness=0):
2150         """
2151         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2152
2153         Parameters:
2154                 fineness: [0.0, 1.0] defines mesh fineness
2155
2156         Returns:
2157                 True or False
2158         """
2159
2160         dim = self.MeshDimension()
2161         # assign the hypotheses
2162         self.RemoveGlobalHypotheses()
2163         self.Segment().AutomaticLength(fineness)
2164         if dim > 1 :
2165             self.Quadrangle()
2166             pass
2167         if dim > 2 :
2168             self.Hexahedron()
2169             pass
2170         return self.Compute()
2171
2172     def AddHypothesis(self, hyp, geom=0):
2173         """
2174         Assign a hypothesis
2175
2176         Parameters:
2177                 hyp: a hypothesis to assign
2178                 geom: a subhape of mesh geometry
2179
2180         Returns:
2181                 :class:`SMESH.Hypothesis_Status`
2182         """
2183
2184         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2185             hyp, geom = geom, hyp
2186         if isinstance( hyp, Mesh_Algorithm ):
2187             hyp = hyp.GetAlgorithm()
2188             pass
2189         if not geom:
2190             geom = self.geom
2191             if not geom:
2192                 geom = self.mesh.GetShapeToMesh()
2193             pass
2194         isApplicable = True
2195         if self.mesh.HasShapeToMesh():
2196             hyp_type     = hyp.GetName()
2197             lib_name     = hyp.GetLibName()
2198             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2199             # if checkAll and geom:
2200             #     checkAll = geom.GetType() == 37
2201             checkAll     = False
2202             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2203         if isApplicable:
2204             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2205             status = self.mesh.AddHypothesis(geom, hyp)
2206         else:
2207             status = HYP_BAD_GEOMETRY, ""
2208         hyp_name = GetName( hyp )
2209         geom_name = ""
2210         if geom:
2211             geom_name = geom.GetName()
2212         isAlgo = hyp._narrow( SMESH_Algo )
2213         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2214         return status
2215
2216     def IsUsedHypothesis(self, hyp, geom):
2217         """
2218         Return True if an algorithm or hypothesis is assigned to a given shape
2219
2220         Parameters:
2221                 hyp: an algorithm or hypothesis to check
2222                 geom: a subhape of mesh geometry
2223
2224         Returns:
2225                 True of False
2226         """
2227
2228         if not hyp: # or not geom
2229             return False
2230         if isinstance( hyp, Mesh_Algorithm ):
2231             hyp = hyp.GetAlgorithm()
2232             pass
2233         hyps = self.GetHypothesisList(geom)
2234         for h in hyps:
2235             if h.GetId() == hyp.GetId():
2236                 return True
2237         return False
2238
2239     def RemoveHypothesis(self, hyp, geom=0):
2240         """
2241         Unassign a hypothesis
2242
2243         Parameters:
2244                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2245                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2246
2247         Returns:
2248                 :class:`SMESH.Hypothesis_Status`
2249         """
2250
2251         if not hyp:
2252             return None
2253         if isinstance( hyp, Mesh_Algorithm ):
2254             hyp = hyp.GetAlgorithm()
2255             pass
2256         shape = geom
2257         if not shape:
2258             shape = self.geom
2259             pass
2260         if self.IsUsedHypothesis( hyp, shape ):
2261             return self.mesh.RemoveHypothesis( shape, hyp )
2262         hypName = GetName( hyp )
2263         geoName = GetName( shape )
2264         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2265         return None
2266
2267     def GetHypothesisList(self, geom):
2268         """
2269         Get the list of hypotheses added on a geometry
2270
2271         Parameters:
2272                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2273
2274         Returns:
2275                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2276         """
2277
2278         return self.mesh.GetHypothesisList( geom )
2279
2280     def RemoveGlobalHypotheses(self):
2281         """
2282         Remove all global hypotheses
2283         """
2284
2285         current_hyps = self.mesh.GetHypothesisList( self.geom )
2286         for hyp in current_hyps:
2287             self.mesh.RemoveHypothesis( self.geom, hyp )
2288             pass
2289         pass
2290     def ExportMED(self, *args, **kwargs):
2291         """
2292         Export the mesh in a file in MED format
2293         allowing to overwrite the file if it exists or add the exported data to its contents
2294
2295         Parameters:
2296                 fileName: is the file name
2297                 auto_groups (boolean): parameter for creating/not creating
2298                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2299                         the typical use is auto_groups=False.
2300                 minor (int): define the minor version (y, where version is x.y.z) of MED file format.
2301                         The minor must be between 0 and the current minor version of MED file library.
2302                         If minor is equal to -1, the minor version is not changed (default).
2303                         The major version (x, where version is x.y.z) cannot be changed.
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                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2307
2308                         - 1D if all mesh nodes lie on OX coordinate axis, or
2309                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2310                         - 3D in the rest cases.
2311
2312                         If *autoDimension* is *False*, the space dimension is always 3.
2313                 fields: list of GEOM fields defined on the shape to mesh.
2314                 geomAssocFields: each character of this string means a need to export a 
2315                         corresponding field; correspondence between fields and characters 
2316                         is following:
2317
2318                         - 'v' stands for "_vertices_" field;
2319                         - 'e' stands for "_edges_" field;
2320                         - 'f' stands for "_faces_" field;
2321                         - 's' stands for "_solids_" field.
2322
2323                 zTolerance (float): tolerance in Z direction. If Z coordinate of a node is 
2324                              close to zero within a given tolerance, the coordinate is set to zero.
2325                              If *ZTolerance* is negative (default), the node coordinates are kept as is.
2326         """
2327         # process positional arguments
2328         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2329         fileName        = args[0]
2330         auto_groups     = args[1] if len(args) > 1 else False
2331         minor           = args[2] if len(args) > 2 else -1
2332         overwrite       = args[3] if len(args) > 3 else True
2333         meshPart        = args[4] if len(args) > 4 else None
2334         autoDimension   = args[5] if len(args) > 5 else True
2335         fields          = args[6] if len(args) > 6 else []
2336         geomAssocFields = args[7] if len(args) > 7 else ''
2337         z_tolerance     = args[8] if len(args) > 8 else -1.
2338         # process keywords arguments
2339         auto_groups     = kwargs.get("auto_groups", auto_groups)
2340         minor           = kwargs.get("minor", minor)
2341         overwrite       = kwargs.get("overwrite", overwrite)
2342         meshPart        = kwargs.get("meshPart", meshPart)
2343         autoDimension   = kwargs.get("autoDimension", autoDimension)
2344         fields          = kwargs.get("fields", fields)
2345         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2346         z_tolerance     = kwargs.get("zTolerance", z_tolerance)
2347
2348         # invoke engine's function
2349         if meshPart or fields or geomAssocFields or z_tolerance > 0:
2350             unRegister = genObjUnRegister()
2351             if isinstance( meshPart, list ):
2352                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2353                 unRegister.set( meshPart )
2354
2355             z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
2356             self.mesh.SetParameters(Parameters)
2357
2358             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
2359                                        fields, geomAssocFields, z_tolerance)
2360         else:
2361             self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2362
2363     def ExportSAUV(self, f, auto_groups=0):
2364         """
2365         Export the mesh in a file in SAUV format
2366
2367
2368         Parameters:
2369                 f: is the file name
2370                 auto_groups: boolean parameter for creating/not creating
2371                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2372                         the typical use is auto_groups=False.
2373         """
2374
2375         self.mesh.ExportSAUV(f, auto_groups)
2376
2377     def ExportDAT(self, f, meshPart=None):
2378         """
2379         Export the mesh in a file in DAT format
2380
2381         Parameters:
2382                 f: the file name
2383                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2384         """
2385
2386         if meshPart:
2387             unRegister = genObjUnRegister()
2388             if isinstance( meshPart, list ):
2389                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2390                 unRegister.set( meshPart )
2391             self.mesh.ExportPartToDAT( meshPart, f )
2392         else:
2393             self.mesh.ExportDAT(f)
2394
2395     def ExportUNV(self, f, meshPart=None):
2396         """
2397         Export the mesh in a file in UNV format
2398
2399         Parameters:
2400                 f: the file name
2401                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2402         """
2403
2404         if meshPart:
2405             unRegister = genObjUnRegister()
2406             if isinstance( meshPart, list ):
2407                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2408                 unRegister.set( meshPart )
2409             self.mesh.ExportPartToUNV( meshPart, f )
2410         else:
2411             self.mesh.ExportUNV(f)
2412
2413     def ExportSTL(self, f, ascii=1, meshPart=None):
2414         """
2415         Export the mesh in a file in STL format
2416
2417         Parameters:
2418                 f: the file name
2419                 ascii: defines the file encoding
2420                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2421         """
2422
2423         if meshPart:
2424             unRegister = genObjUnRegister()
2425             if isinstance( meshPart, list ):
2426                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2427                 unRegister.set( meshPart )
2428             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2429         else:
2430             self.mesh.ExportSTL(f, ascii)
2431
2432     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2433         """
2434         Export the mesh in a file in CGNS format
2435
2436         Parameters:
2437                 f: is the file name
2438                 overwrite: boolean parameter for overwriting/not overwriting the file
2439                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2440                 groupElemsByType: if True all elements of same entity type are exported at ones,
2441                         else elements are exported in order of their IDs which can cause creation
2442                         of multiple cgns sections
2443         """
2444
2445         unRegister = genObjUnRegister()
2446         if isinstance( meshPart, list ):
2447             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2448             unRegister.set( meshPart )
2449         if isinstance( meshPart, Mesh ):
2450             meshPart = meshPart.mesh
2451         elif not meshPart:
2452             meshPart = self.mesh
2453         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2454
2455     def ExportGMF(self, f, meshPart=None):
2456         """
2457         Export the mesh in a file in GMF format.
2458         GMF files must have .mesh extension for the ASCII format and .meshb for
2459         the bynary format. Other extensions are not allowed.
2460
2461         Parameters:
2462                 f: is the file name
2463                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2464         """
2465
2466         unRegister = genObjUnRegister()
2467         if isinstance( meshPart, list ):
2468             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2469             unRegister.set( meshPart )
2470         if isinstance( meshPart, Mesh ):
2471             meshPart = meshPart.mesh
2472         elif not meshPart:
2473             meshPart = self.mesh
2474         self.mesh.ExportGMF(meshPart, f, True)
2475
2476     def ExportToMED(self, *args, **kwargs):
2477         """
2478         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2479         Export the mesh in a file in MED format
2480         allowing to overwrite the file if it exists or add the exported data to its contents
2481
2482         Parameters:
2483                 fileName: the file name
2484                 opt (boolean): parameter for creating/not creating
2485                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2486                 overwrite: boolean parameter for overwriting/not overwriting the file
2487                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2488
2489                         - 1D if all mesh nodes lie on OX coordinate axis, or
2490                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2491                         - 3D in the rest cases.
2492
2493                         If **autoDimension** is *False*, the space dimension is always 3.
2494         """
2495     
2496         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2497         # process positional arguments
2498         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2499         fileName      = args[0]
2500         auto_groups   = args[1] if len(args) > 1 else False
2501         overwrite     = args[2] if len(args) > 2 else True
2502         autoDimension = args[3] if len(args) > 3 else True
2503         # process keywords arguments
2504         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2505         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2506         overwrite     = kwargs.get("overwrite", overwrite)
2507         autoDimension = kwargs.get("autoDimension", autoDimension)
2508         minor = -1
2509         # invoke engine's function
2510         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2511
2512     def ExportToMEDX(self, *args, **kwargs):
2513         """
2514         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2515         Export the mesh in a file in MED format
2516
2517         Parameters:
2518                 fileName: the file name
2519                 opt (boolean): parameter for creating/not creating
2520                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2521                 overwrite: boolean parameter for overwriting/not overwriting the file
2522                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2523
2524                         - 1D if all mesh nodes lie on OX coordinate axis, or
2525                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2526                         - 3D in the rest cases.
2527
2528                         If **autoDimension** is *False*, the space dimension is always 3.
2529                 """
2530
2531         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2532         # process positional arguments
2533         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2534         fileName      = args[0]
2535         auto_groups   = args[1] if len(args) > 1 else False
2536         overwrite     = args[2] if len(args) > 2 else True
2537         autoDimension = args[3] if len(args) > 3 else True
2538         # process keywords arguments
2539         auto_groups   = kwargs.get("auto_groups", auto_groups)
2540         overwrite     = kwargs.get("overwrite", overwrite)
2541         autoDimension = kwargs.get("autoDimension", autoDimension)
2542         minor = -1
2543         # invoke engine's function
2544         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2545         return
2546
2547
2548     def Append(self, meshes, uniteIdenticalGroups = True,
2549                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
2550         """
2551         Append given meshes into this mesh.
2552         All groups of input meshes will be created in this mesh.
2553
2554         Parameters:
2555                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to append
2556                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
2557                 mergeNodesAndElements: if True, equal nodes and elements are merged
2558                 mergeTolerance: tolerance for merging nodes
2559                 allGroups: forces creation of groups corresponding to every input mesh
2560         """
2561         self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups,
2562                                    mergeNodesAndElements, mergeTolerance, allGroups,
2563                                    meshToAppendTo = self.GetMesh() )
2564
2565     # Operations with groups:
2566     # ----------------------
2567     def CreateEmptyGroup(self, elementType, name):
2568         """
2569         Create an empty standalone mesh group
2570
2571         Parameters:
2572                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2573                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2574                 name: the name of the mesh group
2575
2576         Returns:
2577                 :class:`SMESH.SMESH_Group`
2578         """
2579
2580         return self.mesh.CreateGroup(elementType, name)
2581
2582     def Group(self, grp, name=""):
2583         """
2584         Create a mesh group based on the geometric object *grp*
2585         and give it a *name*.
2586         If *name* is not defined the name of the geometric group is used
2587
2588         Note:
2589                 Works like :meth:`GroupOnGeom`.
2590
2591         Parameters:
2592                 grp:  a geometric group, a vertex, an edge, a face or a solid
2593                 name: the name of the mesh group
2594
2595         Returns:
2596                 :class:`SMESH.SMESH_GroupOnGeom`
2597         """
2598
2599         return self.GroupOnGeom(grp, name)
2600
2601     def GroupOnGeom(self, grp, name="", typ=None):
2602         """
2603         Create a mesh group based on the geometrical object *grp*
2604         and give it a *name*.
2605         if *name* is not defined the name of the geometric group is used
2606
2607         Parameters:
2608                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2609                 name: the name of the mesh group
2610                 typ:  the type of elements in the group; either of
2611                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2612                         automatically detected by the type of the geometry
2613
2614         Returns:
2615                 :class:`SMESH.SMESH_GroupOnGeom`
2616         """
2617
2618         AssureGeomPublished( self, grp, name )
2619         if name == "":
2620             name = grp.GetName()
2621         if not typ:
2622             typ = self._groupTypeFromShape( grp )
2623         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2624
2625     def _groupTypeFromShape( self, shape ):
2626         """
2627         Pivate method to get a type of group on geometry
2628         """
2629         tgeo = str(shape.GetShapeType())
2630         if tgeo == "VERTEX":
2631             typ = NODE
2632         elif tgeo == "EDGE" or tgeo == "WIRE":
2633             typ = EDGE
2634         elif tgeo == "FACE" or tgeo == "SHELL":
2635             typ = FACE
2636         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2637             typ = VOLUME
2638         elif tgeo == "COMPOUND":
2639             sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2640             if not sub:
2641                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2642             return self._groupTypeFromShape( sub[0] )
2643         else:
2644             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2645         return typ
2646
2647     def GroupOnFilter(self, typ, name, filter):
2648         """
2649         Create a mesh group with given *name* based on the *filter*.
2650         It is a special type of group dynamically updating it's contents during
2651         mesh modification
2652
2653         Parameters:
2654                 typ: the type of elements in the group; either of
2655                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2656                 name: the name of the mesh group
2657                 filter (SMESH.Filter): the filter defining group contents
2658
2659         Returns:
2660                 :class:`SMESH.SMESH_GroupOnFilter`
2661         """
2662
2663         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2664
2665     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2666         """
2667         Create a mesh group by the given ids of elements
2668
2669         Parameters:
2670                 groupName: the name of the mesh group
2671                 elementType: the type of elements in the group; either of
2672                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2673                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2674
2675         Returns:
2676                 :class:`SMESH.SMESH_Group`
2677         """
2678
2679         group = self.mesh.CreateGroup(elementType, groupName)
2680         if isinstance( elemIDs, Mesh ):
2681             elemIDs = elemIDs.GetMesh()
2682         if hasattr( elemIDs, "GetIDs" ):
2683             if hasattr( elemIDs, "SetMesh" ):
2684                 elemIDs.SetMesh( self.GetMesh() )
2685             group.AddFrom( elemIDs )
2686         else:
2687             group.Add(elemIDs)
2688         return group
2689
2690     def MakeGroup(self,
2691                   groupName,
2692                   elementType,
2693                   CritType=FT_Undefined,
2694                   Compare=FT_EqualTo,
2695                   Threshold="",
2696                   UnaryOp=FT_Undefined,
2697                   Tolerance=1e-07):
2698         """
2699         Create a mesh group by the given conditions
2700
2701         Parameters:
2702                 groupName: the name of the mesh group
2703                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2704                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2705                         Note that the items starting from FT_LessThan are not suitable for CritType.
2706                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2707                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2708                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2709                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2710                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2711
2712         Returns:
2713                 :class:`SMESH.SMESH_GroupOnFilter`
2714         """
2715
2716         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2717         group = self.MakeGroupByCriterion(groupName, aCriterion)
2718         return group
2719
2720     def MakeGroupByCriterion(self, groupName, Criterion):
2721         """
2722         Create a mesh group by the given criterion
2723
2724         Parameters:
2725                 groupName: the name of the mesh group
2726                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2727
2728         Returns:
2729                 :class:`SMESH.SMESH_GroupOnFilter`
2730
2731         See Also:
2732                 :meth:`smeshBuilder.GetCriterion`
2733         """
2734
2735         return self.MakeGroupByCriteria( groupName, [Criterion] )
2736
2737     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2738         """
2739         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2740
2741         Parameters:
2742                 groupName: the name of the mesh group
2743                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2744                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2745
2746         Returns:
2747                 :class:`SMESH.SMESH_GroupOnFilter`
2748
2749         See Also:
2750                 :meth:`smeshBuilder.GetCriterion`
2751         """
2752
2753         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2754         group = self.MakeGroupByFilter(groupName, aFilter)
2755         return group
2756
2757     def MakeGroupByFilter(self, groupName, theFilter):
2758         """
2759         Create a mesh group by the given filter
2760
2761         Parameters:
2762                 groupName (string): the name of the mesh group
2763                 theFilter (SMESH.Filter): the filter
2764
2765         Returns:
2766                 :class:`SMESH.SMESH_GroupOnFilter`
2767
2768         See Also:
2769                 :meth:`smeshBuilder.GetFilter`
2770         """
2771
2772         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2773         #theFilter.SetMesh( self.mesh )
2774         #group.AddFrom( theFilter )
2775         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2776         return group
2777
2778     def RemoveGroup(self, group):
2779         """
2780         Remove a group
2781
2782         Parameters:
2783                 group (SMESH.SMESH_GroupBase): group to remove
2784         """
2785
2786         self.mesh.RemoveGroup(group)
2787
2788     def RemoveGroupWithContents(self, group):
2789         """
2790         Remove a group with its contents
2791
2792         Parameters:
2793                 group (SMESH.SMESH_GroupBase): group to remove
2794
2795         Note:
2796                 This operation can create gaps in numeration of nodes or elements.
2797                 Call :meth:`RenumberElements` to remove the gaps.
2798         """
2799
2800         self.mesh.RemoveGroupWithContents(group)
2801
2802     def GetGroups(self, elemType = SMESH.ALL):
2803         """
2804         Get the list of groups existing in the mesh in the order of creation 
2805         (starting from the oldest one)
2806
2807         Parameters:
2808                 elemType (SMESH.ElementType): type of elements the groups contain;
2809                         by default groups of elements of all types are returned
2810
2811         Returns:
2812                 a list of :class:`SMESH.SMESH_GroupBase`
2813         """
2814
2815         groups = self.mesh.GetGroups()
2816         if elemType == SMESH.ALL:
2817             return groups
2818         typedGroups = []
2819         for g in groups:
2820             if g.GetType() == elemType:
2821                 typedGroups.append( g )
2822                 pass
2823             pass
2824         return typedGroups
2825
2826     def NbGroups(self):
2827         """
2828         Get the number of groups existing in the mesh
2829
2830         Returns:
2831                 the quantity of groups as an integer value
2832         """
2833
2834         return self.mesh.NbGroups()
2835
2836     def GetGroupNames(self):
2837         """
2838         Get the list of names of groups existing in the mesh
2839
2840         Returns:
2841                 list of strings
2842         """
2843
2844         groups = self.GetGroups()
2845         names = []
2846         for group in groups:
2847             names.append(group.GetName())
2848         return names
2849
2850     def GetGroupByName(self, name, elemType = None):
2851         """
2852         Find groups by name and type
2853
2854         Parameters:
2855                 name (string): name of the group of interest
2856                 elemType (SMESH.ElementType): type of elements the groups contain;
2857                         by default one group of any type is returned;
2858                         if elemType == SMESH.ALL then all groups of any type are returned
2859
2860         Returns:
2861                 a list of :class:`SMESH.SMESH_GroupBase`
2862         """
2863
2864         groups = []
2865         for group in self.GetGroups():
2866             if group.GetName() == name:
2867                 if elemType is None:
2868                     return [group]
2869                 if ( elemType == SMESH.ALL or
2870                      group.GetType() == elemType ):
2871                     groups.append( group )
2872         return groups
2873
2874     def UnionGroups(self, group1, group2, name):
2875         """
2876         Produce a union of two groups.
2877         A new group is created. All mesh elements that are
2878         present in the initial groups are added to the new one
2879
2880         Parameters:
2881            group1 (SMESH.SMESH_GroupBase): a group
2882            group2 (SMESH.SMESH_GroupBase): another group
2883
2884         Returns:
2885                 instance of :class:`SMESH.SMESH_Group`
2886         """
2887
2888         return self.mesh.UnionGroups(group1, group2, name)
2889
2890     def UnionListOfGroups(self, groups, name):
2891         """
2892         Produce a union list of groups.
2893         New group is created. All mesh elements that are present in
2894         initial groups are added to the new one
2895
2896         Parameters:
2897            groups: list of :class:`SMESH.SMESH_GroupBase`