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