Salome HOME
Merge branch 'master' of https://codev-tuleap.cea.fr/plugins/git/salome/smesh
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
1 # Copyright (C) 2007-2021  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 from StdMeshers import BlockCS
44
45 import SALOME
46 import SALOMEDS
47 import os
48 import inspect
49
50 # In case the omniORBpy EnumItem class does not fully support Python 3
51 # (for instance in version 4.2.1-2), the comparison ordering methods must be
52 # defined
53 #
54 try:
55     SMESH.Entity_Triangle < SMESH.Entity_Quadrangle
56 except TypeError:
57     def enumitem_eq(self, other):
58         try:
59             if isinstance(other, omniORB.EnumItem):
60                 if other._parent_id == self._parent_id:
61                     return self._v == other._v
62                 else:
63                     return self._parent_id == other._parent_id
64             else:
65                 return id(self) == id(other)
66         except:
67             return id(self) == id(other)
68
69     def enumitem_lt(self, other):
70         try:
71             if isinstance(other, omniORB.EnumItem):
72                 if other._parent_id == self._parent_id:
73                     return self._v < other._v
74                 else:
75                     return self._parent_id < other._parent_id
76             else:
77                 return id(self) < id(other)
78         except:
79             return id(self) < id(other)
80
81     def enumitem_le(self, other):
82         try:
83             if isinstance(other, omniORB.EnumItem):
84                 if other._parent_id == self._parent_id:
85                     return self._v <= other._v
86                 else:
87                     return self._parent_id <= other._parent_id
88             else:
89                 return id(self) <= id(other)
90         except:
91             return id(self) <= id(other)
92
93     def enumitem_gt(self, other):
94         try:
95             if isinstance(other, omniORB.EnumItem):
96                 if other._parent_id == self._parent_id:
97                     return self._v > other._v
98                 else:
99                     return self._parent_id > other._parent_id
100             else:
101                 return id(self) > id(other)
102         except:
103             return id(self) > id(other)
104
105     def enumitem_ge(self, other):
106         try:
107             if isinstance(other, omniORB.EnumItem):
108                 if other._parent_id == self._parent_id:
109                     return self._v >= other._v
110                 else:
111                     return self._parent_id >= other._parent_id
112             else:
113                 return id(self) >= id(other)
114         except:
115             return id(self) >= id(other)
116
117     omniORB.EnumItem.__eq__ = enumitem_eq
118     omniORB.EnumItem.__lt__ = enumitem_lt
119     omniORB.EnumItem.__le__ = enumitem_le
120     omniORB.EnumItem.__gt__ = enumitem_gt
121     omniORB.EnumItem.__ge__ = enumitem_ge
122
123
124 class MeshMeta(type):
125     """Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
126     """
127     def __instancecheck__(cls, inst):
128         """Implement isinstance(inst, cls)."""
129         return any(cls.__subclasscheck__(c)
130                    for c in {type(inst), inst.__class__})
131
132     def __subclasscheck__(cls, sub):
133         """Implement issubclass(sub, cls)."""
134         return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
135
136 def DegreesToRadians(AngleInDegrees):
137     """Convert an angle from degrees to radians
138     """
139     from math import pi
140     return AngleInDegrees * pi / 180.0
141
142 import salome_notebook
143 notebook = salome_notebook.notebook
144 # Salome notebook variable separator
145 var_separator = ":"
146
147 def ParseParameters(*args):
148     """
149     Return list of variable values from salome notebook.
150     The last argument, if is callable, is used to modify values got from notebook
151     """
152     Result = []
153     Parameters = ""
154     hasVariables = False
155     varModifFun=None
156     if args and callable(args[-1]):
157         args, varModifFun = args[:-1], args[-1]
158     for parameter in args:
159
160         Parameters += str(parameter) + var_separator
161
162         if isinstance(parameter,str):
163             # check if there is an inexistent variable name
164             if not notebook.isVariable(parameter):
165                 raise ValueError("Variable with name '" + parameter + "' doesn't exist!!!")
166             parameter = notebook.get(parameter)
167             hasVariables = True
168             if varModifFun:
169                 parameter = varModifFun(parameter)
170                 pass
171             pass
172         Result.append(parameter)
173
174         pass
175     Parameters = Parameters[:-1]
176     Result.append( Parameters )
177     Result.append( hasVariables )
178     return Result
179
180 def ParseAngles(*args):
181     """
182     Parse parameters while converting variables to radians
183     """
184     return ParseParameters( *( args + (DegreesToRadians, )))
185
186 def __initPointStruct(point,*args):
187     """
188     Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
189     Parameters are stored in PointStruct.parameters attribute
190     """
191     point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
192     pass
193 SMESH.PointStruct.__init__ = __initPointStruct
194
195 def __initAxisStruct(ax,*args):
196     """
197     Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
198     Parameters are stored in AxisStruct.parameters attribute
199     """
200     if len( args ) != 6:
201         raise RuntimeError("Bad nb args (%s) passed in SMESH.AxisStruct(x,y,z,dx,dy,dz)"%(len( args )))
202     ax.x, ax.y, ax.z, ax.vx, ax.vy, ax.vz, ax.parameters,hasVars = ParseParameters(*args)
203     pass
204 SMESH.AxisStruct.__init__ = __initAxisStruct
205
206 smeshPrecisionConfusion = 1.e-07
207 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
208     """Compare real values using smeshPrecisionConfusion as tolerance
209     """
210     if abs(val1 - val2) < tol:
211         return True
212     return False
213
214 NO_NAME = "NoName"
215
216 def GetName(obj):
217     """
218     Return a name of an object
219     
220     Returns:
221         object name
222     """
223     if obj:
224         # object not null
225         if isinstance(obj, SALOMEDS._objref_SObject):
226             # study object
227             return obj.GetName()
228         try:
229             ior  = salome.orb.object_to_string(obj)
230         except:
231             ior = None
232         if ior:
233             sobj = salome.myStudy.FindObjectIOR(ior)
234             if sobj:
235                 return sobj.GetName()
236             if hasattr(obj, "GetName"):
237                 # unknown CORBA object, having GetName() method
238                 return obj.GetName()
239             else:
240                 # unknown CORBA object, no GetName() method
241                 return NO_NAME
242             pass
243         if hasattr(obj, "GetName"):
244             # unknown non-CORBA object, having GetName() method
245             return obj.GetName()
246         pass
247     raise RuntimeError("Null or invalid object")
248
249 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
250     """
251     Print error message if a hypothesis was not assigned.
252     """
253     if isAlgo:
254         hypType = "algorithm"
255     else:
256         hypType = "hypothesis"
257         pass
258     reason = ""
259     if hasattr( status, "__getitem__" ):
260         status, reason = status[0], status[1]
261     if status == HYP_UNKNOWN_FATAL:
262         reason = "for unknown reason"
263     elif status == HYP_INCOMPATIBLE:
264         reason = "this hypothesis mismatches the algorithm"
265     elif status == HYP_NOTCONFORM:
266         reason = "a non-conform mesh would be built"
267     elif status == HYP_ALREADY_EXIST:
268         if isAlgo: return # it does not influence anything
269         reason = hypType + " of the same dimension is already assigned to this shape"
270     elif status == HYP_BAD_DIM:
271         reason = hypType + " mismatches the shape"
272     elif status == HYP_CONCURRENT :
273         reason = "there are concurrent hypotheses on sub-shapes"
274     elif status == HYP_BAD_SUBSHAPE:
275         reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
276     elif status == HYP_BAD_GEOMETRY:
277         reason = "the algorithm is not applicable to this geometry"
278     elif status == HYP_HIDDEN_ALGO:
279         reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
280     elif status == HYP_HIDING_ALGO:
281         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
282     elif status == HYP_NEED_SHAPE:
283         reason = "algorithm can't work without shape"
284     elif status == HYP_INCOMPAT_HYPS:
285         pass
286     else:
287         return
288     where = geomName
289     if where:
290         where = '"%s"' % geomName
291         if mesh:
292             meshName = GetName( mesh )
293             if meshName and meshName != NO_NAME:
294                 where = '"%s" shape in "%s" mesh ' % ( geomName, meshName )
295     if status < HYP_UNKNOWN_FATAL and where:
296         print('"%s" was assigned to %s but %s' %( hypName, where, reason ))
297     elif where:
298         print('"%s" was not assigned to %s : %s' %( hypName, where, reason ))
299     else:
300         print('"%s" was not assigned : %s' %( hypName, reason ))
301         pass
302
303 def AssureGeomPublished(mesh, geom, name=''):
304     """
305     Private method. Add geom (sub-shape of the main shape) into the study if not yet there
306     """
307     if not mesh.smeshpyD.IsEnablePublish():
308         return
309     if not hasattr( geom, "GetShapeType" ):
310         return
311     if not geom.GetStudyEntry():
312         ## get a name
313         if not name and geom.GetShapeType() != geomBuilder.GEOM.COMPOUND:
314             # for all groups SubShapeName() return "Compound_-1"
315             name = mesh.geompyD.SubShapeName(geom, mesh.geom)
316         if not name:
317             name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
318         ## publish
319         mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
320     return
321
322 # def FirstVertexOnCurve(mesh, edge):
323 #     """
324 #     Returns:
325 #         the first vertex of a geometrical edge by ignoring orientation
326 #     """
327 #     return mesh.geompyD.GetVertexByIndex( edge, 0, False )
328
329
330 smeshInst = None
331 """
332 Warning:
333     smeshInst is a singleton
334 """
335 engine = None
336 doLcc = False
337 created = False
338
339 class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
340     """
341     This class allows to create, load or manipulate meshes.
342     It has a set of methods to create, load or copy meshes, to combine several meshes, etc.
343     It also has methods to get infos and measure meshes.
344     """
345
346     # MirrorType enumeration
347     POINT = SMESH_MeshEditor.POINT
348     AXIS =  SMESH_MeshEditor.AXIS
349     PLANE = SMESH_MeshEditor.PLANE
350
351     # Smooth_Method enumeration
352     LAPLACIAN_SMOOTH = SMESH_MeshEditor.LAPLACIAN_SMOOTH
353     CENTROIDAL_SMOOTH = SMESH_MeshEditor.CENTROIDAL_SMOOTH
354
355     PrecisionConfusion = smeshPrecisionConfusion
356
357     # TopAbs_State enumeration
358     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = list(range(4))
359
360     # Methods of splitting a hexahedron into tetrahedra
361     Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
362
363     def __new__(cls, *args):
364         global engine
365         global smeshInst
366         global doLcc
367         #print("==== __new__", engine, smeshInst, doLcc)
368
369         if smeshInst is None:
370             # smesh engine is either retrieved from engine, or created
371             smeshInst = engine
372             # Following test avoids a recursive loop
373             if doLcc:
374                 if smeshInst is not None:
375                     # smesh engine not created: existing engine found
376                     doLcc = False
377                 if doLcc:
378                     doLcc = False
379                     # FindOrLoadComponent called:
380                     # 1. CORBA resolution of server
381                     # 2. the __new__ method is called again
382                     #print("==== smeshInst = lcc.FindOrLoadComponent ", engine, smeshInst, doLcc)
383                     smeshInst = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" )
384             else:
385                 # FindOrLoadComponent not called
386                 if smeshInst is None:
387                     # smeshBuilder instance is created from lcc.FindOrLoadComponent
388                     #print("==== smeshInst = super(smeshBuilder,cls).__new__(cls) ", engine, smeshInst, doLcc)
389                     smeshInst = super(smeshBuilder,cls).__new__(cls)
390                 else:
391                     # smesh engine not created: existing engine found
392                     #print("==== existing ", engine, smeshInst, doLcc)
393                     pass
394             #print("====1 ", smeshInst)
395             return smeshInst
396
397         #print("====2 ", smeshInst)
398         return smeshInst
399
400     def __init__(self, *args):
401         global created
402         #print("--------------- smeshbuilder __init__ ---", created)
403         if not created:
404             created = True
405             SMESH._objref_SMESH_Gen.__init__(self, *args)
406
407
408     def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
409         """
410         Dump component to the Python script.
411         This method overrides IDL function to allow default values for the parameters.
412         """
413
414         return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
415
416     def SetDumpPythonHistorical(self, isHistorical):
417         """
418         Set mode of DumpPython(), *historical* or *snapshot*.
419         In the *historical* mode, the Python Dump script includes all commands
420         performed by SMESH engine. In the *snapshot* mode, commands
421         relating to objects removed from the Study are excluded from the script
422         as well as commands not influencing the current state of meshes
423         """
424
425         if isHistorical: val = "true"
426         else:            val = "false"
427         SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
428
429     def init_smesh(self,geompyD = None):
430         """
431         Set Geometry component
432         """    
433         #print("init_smesh")
434         self.UpdateStudy(geompyD)
435         notebook.myStudy = salome.myStudy
436
437     def Mesh(self, obj=0, name=0):
438         """
439         Create a mesh. This mesh can be either 
440
441         * an empty mesh not bound to geometry, if *obj* == 0
442         * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
443         * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
444
445         Parameters:
446             obj: either 
447
448                    1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
449                       ::
450
451                         salome.myStudy.FindObjectID("0:1:2:3").GetObject() 
452
453                    2. a geometrical object for meshing
454                    3. none.
455             name: the name for the new mesh.
456
457         Returns:
458             an instance of class :class:`Mesh`.
459         """
460
461         if isinstance(obj,str):
462             obj,name = name,obj
463         return Mesh(self, self.geompyD, obj, name)
464
465     def RemoveMesh( self, mesh ):
466         """
467         Delete a mesh
468         """
469         if isinstance( mesh, Mesh ):
470             mesh = mesh.GetMesh()
471             pass
472         if not isinstance( mesh, SMESH._objref_SMESH_Mesh ):
473             raise TypeError("%s is not a mesh" % mesh )
474         so = salome.ObjectToSObject( mesh )
475         if so:
476             sb = salome.myStudy.NewBuilder()
477             sb.RemoveObjectWithChildren( so )
478         else:
479             mesh.UnRegister()
480             pass
481         return
482
483     def EnumToLong(self,theItem):
484         """
485         Return a long value from enumeration
486         """
487
488         return theItem._v
489
490     def ColorToString(self,c):
491         """
492         Convert SALOMEDS.Color to string.
493         To be used with filters.
494
495         Parameters:
496             c: color value (SALOMEDS.Color)
497
498         Returns:
499             a string representation of the color.
500         """
501
502         val = ""
503         if isinstance(c, SALOMEDS.Color):
504             val = "%s;%s;%s" % (c.R, c.G, c.B)
505         elif isinstance(c, str):
506             val = c
507         else:
508             raise ValueError("Color value should be of string or SALOMEDS.Color type")
509         return val
510
511     def GetPointStruct(self,theVertex):
512         """
513         Get :class:`SMESH.PointStruct` from vertex
514
515         Parameters:
516                 theVertex (GEOM.GEOM_Object): vertex
517
518         Returns:
519                 :class:`SMESH.PointStruct`
520         """
521         geompyD = theVertex.GetGen()
522         [x, y, z] = geompyD.PointCoordinates(theVertex)
523         return PointStruct(x,y,z)
524
525     def GetDirStruct(self,theVector):
526         """
527         Get :class:`SMESH.DirStruct` from vector
528
529         Parameters:
530                 theVector (GEOM.GEOM_Object): vector
531
532         Returns:
533                 :class:`SMESH.DirStruct`
534         """
535         geompyD = theVector.GetGen()
536         vertices = geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
537         if(len(vertices) != 2):
538             print("Error: vector object is incorrect.")
539             return None
540         p1 = geompyD.PointCoordinates(vertices[0])
541         p2 = geompyD.PointCoordinates(vertices[1])
542         pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
543         dirst = DirStruct(pnt)
544         return dirst
545
546     def MakeDirStruct(self,x,y,z):
547         """
548         Make :class:`SMESH.DirStruct` from a triplet of floats
549
550         Parameters:
551                 x,y,z (float): vector components
552
553         Returns:
554                 :class:`SMESH.DirStruct`
555         """
556
557         pnt = PointStruct(x,y,z)
558         return DirStruct(pnt)
559
560     def GetAxisStruct(self,theObj):
561         """
562         Get :class:`SMESH.AxisStruct` from a geometrical object
563
564         Parameters:
565             theObj (GEOM.GEOM_Object): line or plane
566
567         Returns:
568             :class:`SMESH.AxisStruct`
569         """
570         import GEOM
571         geompyD = theObj.GetGen()
572         edges = geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
573         axis = None
574         if len(edges) > 1:
575             vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
576             vertex3, vertex4 = geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
577             vertex1 = geompyD.PointCoordinates(vertex1)
578             vertex2 = geompyD.PointCoordinates(vertex2)
579             vertex3 = geompyD.PointCoordinates(vertex3)
580             vertex4 = geompyD.PointCoordinates(vertex4)
581             v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
582             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
583             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] ]
584             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
585             axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
586         elif len(edges) == 1:
587             vertex1, vertex2 = geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
588             p1 = geompyD.PointCoordinates( vertex1 )
589             p2 = geompyD.PointCoordinates( vertex2 )
590             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
591             axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
592         elif theObj.GetShapeType() == GEOM.VERTEX:
593             x,y,z = geompyD.PointCoordinates( theObj )
594             axis = AxisStruct( x,y,z, 1,0,0,)
595             axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
596         return axis
597
598     # From SMESH_Gen interface:
599     # ------------------------
600
601     def SetName(self, obj, name):
602         """
603         Set the given name to an object
604
605         Parameters:
606                 obj: the object to rename
607                 name: a new object name
608         """
609
610         if isinstance( obj, Mesh ):
611             obj = obj.GetMesh()
612         elif isinstance( obj, Mesh_Algorithm ):
613             obj = obj.GetAlgorithm()
614         ior  = salome.orb.object_to_string(obj)
615         SMESH._objref_SMESH_Gen.SetName(self, ior, name)
616
617     def SetEmbeddedMode( self,theMode ):
618         """
619         Set the current mode
620         """
621
622         SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
623
624     def IsEmbeddedMode(self):
625         """
626         Get the current mode
627         """
628
629         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
630
631     def UpdateStudy( self, geompyD = None  ):
632         """
633         Update the current study. Calling UpdateStudy() allows to
634         update meshes at switching GEOM->SMESH
635         """
636         #self.UpdateStudy()
637         if not geompyD:
638             from salome.geom import geomBuilder
639             geompyD = geomBuilder.geom
640             if not geompyD:
641                 geompyD = geomBuilder.New()
642             pass
643         self.geompyD=geompyD
644         self.SetGeomEngine(geompyD)
645         SMESH._objref_SMESH_Gen.UpdateStudy(self)
646         sb = salome.myStudy.NewBuilder()
647         sc = salome.myStudy.FindComponent("SMESH")
648         if sc:
649             sb.LoadWith(sc, self)
650         pass
651     
652     def SetEnablePublish( self, theIsEnablePublish ):
653         """
654         Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
655         switch **off** publishing in the Study of mesh objects.
656         """
657        #self.SetEnablePublish(theIsEnablePublish)
658         SMESH._objref_SMESH_Gen.SetEnablePublish(self,theIsEnablePublish)
659         global notebook
660         notebook = salome_notebook.NoteBook( theIsEnablePublish )
661
662
663     def CreateMeshesFromUNV( self,theFileName ):
664         """
665         Create a Mesh object importing data from the given UNV file
666
667         Returns:
668                 an instance of class :class:`Mesh`
669         """
670
671         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromUNV(self,theFileName)
672         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
673         return aMesh
674
675     def CreateMeshesFromMED( self,theFileName ):
676         """
677         Create a Mesh object(s) importing data from the given MED file
678
679         Returns:
680                 a tuple ( list of class :class:`Mesh` instances, 
681                 :class:`SMESH.DriverMED_ReadStatus` )
682         """
683
684         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
685         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
686         return aMeshes, aStatus
687
688     def CreateMeshesFromSAUV( self,theFileName ):
689         """
690         Create a Mesh object(s) importing data from the given SAUV file
691
692         Returns:
693                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
694         """
695
696         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
697         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
698         return aMeshes, aStatus
699
700     def CreateMeshesFromSTL( self, theFileName ):
701         """
702         Create a Mesh object importing data from the given STL file
703
704         Returns:
705                 an instance of class :class:`Mesh`
706         """
707
708         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromSTL(self,theFileName)
709         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
710         return aMesh
711
712     def CreateMeshesFromCGNS( self, theFileName ):
713         """
714         Create Mesh objects importing data from the given CGNS file
715
716         Returns:
717                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
718         """
719
720         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
721         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
722         return aMeshes, aStatus
723
724     def CreateMeshesFromGMF( self, theFileName ):
725         """
726         Create a Mesh object importing data from the given GMF file.
727         GMF files must have .mesh extension for the ASCII format and .meshb for
728         the binary format.
729
730         Returns:
731                 ( an instance of class :class:`Mesh`, :class:`SMESH.ComputeError` )
732         """
733
734         aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
735                                                                         theFileName,
736                                                                         True)
737         if error.comment: print("*** CreateMeshesFromGMF() errors:\n", error.comment)
738         return Mesh(self, self.geompyD, aSmeshMesh), error
739
740     def Concatenate( self, meshes, uniteIdenticalGroups,
741                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
742                      name = "", meshToAppendTo = None):
743         """
744         Concatenate the given meshes into one mesh, optionally to meshToAppendTo.
745         All groups of input meshes will be present in the new mesh.
746
747         Parameters:
748                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
749                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
750                 mergeNodesAndElements: if True, equal nodes and elements are merged
751                 mergeTolerance: tolerance for merging nodes
752                 allGroups: forces creation of groups corresponding to every input mesh
753                 name: name of a new mesh
754                 meshToAppendTo: a mesh to append all given meshes
755
756         Returns:
757                 an instance of class :class:`Mesh`
758
759         See also: 
760                 :meth:`Mesh.Append`
761         """
762
763         if not meshes: return None
764         if not isinstance( meshes, list ):
765             meshes = [ meshes ]
766         for i,m in enumerate( meshes ):
767             if isinstance( m, Mesh ):
768                 meshes[i] = m.GetMesh()
769         mergeTolerance,Parameters,hasVars = ParseParameters( mergeTolerance )
770         if hasattr(meshes[0], "SetParameters"):
771             meshes[0].SetParameters( Parameters )
772         else:
773             meshes[0].GetMesh().SetParameters( Parameters )
774         if isinstance( meshToAppendTo, Mesh ):
775             meshToAppendTo = meshToAppendTo.GetMesh()
776         if allGroups:
777             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
778                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
779                 mergeTolerance,meshToAppendTo )
780         else:
781             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
782                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,
783                 mergeTolerance,meshToAppendTo )
784
785         aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name )
786         return aMesh
787
788     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
789         """
790         Create a mesh by copying a part of another mesh.
791
792         Parameters:
793                 meshPart: a part of mesh to copy, either 
794                         :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
795                         To copy nodes or elements not forming any mesh object,
796                         pass result of :meth:`Mesh.GetIDSource` as *meshPart*
797                 meshName: a name of the new mesh
798                 toCopyGroups: to create in the new mesh groups the copied elements belongs to
799                 toKeepIDs: to preserve order of the copied elements or not
800
801         Returns:
802                 an instance of class :class:`Mesh`
803         """
804
805         if isinstance( meshPart, Mesh ):
806             meshPart = meshPart.GetMesh()
807         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
808         return Mesh(self, self.geompyD, mesh)
809
810     def CopyMeshWithGeom( self, sourceMesh, newGeom, meshName="", toCopyGroups=True,
811                           toReuseHypotheses=True, toCopyElements=True):
812         """
813         Create a mesh by copying a mesh definition (hypotheses and groups) to a new geometry.
814         It is supposed that the new geometry is a modified geometry of *sourceMesh*.
815         To facilitate and speed up the operation, consider using
816         "Set presentation parameters and sub-shapes from arguments" option in
817         a dialog of geometrical operation used to create the new geometry.
818
819         Parameters:
820                 sourceMesh: the mesh to copy definition of.
821                 newGeom: the new geometry.
822                 meshName: an optional name of the new mesh. If omitted, the mesh name is kept.
823                 toCopyGroups: to create groups in the new mesh.
824                 toReuseHypotheses: to reuse hypotheses of the *sourceMesh*.
825                 toCopyElements: to copy mesh elements present on non-modified sub-shapes of 
826                                 *sourceMesh*.
827         Returns:
828                 tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries )
829                 *invalidEntries* are study entries of objects whose
830                 counterparts are not found in the *newGeom*, followed by entries
831                 of mesh sub-objects that are invalid because they depend on a not found
832                 preceding sub-shape
833         """
834         if isinstance( sourceMesh, Mesh ):
835             sourceMesh = sourceMesh.GetMesh()
836
837         ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries = \
838            SMESH._objref_SMESH_Gen.CopyMeshWithGeom( self, sourceMesh, newGeom, meshName,
839                                                      toCopyGroups,
840                                                      toReuseHypotheses,
841                                                      toCopyElements)
842         return ( ok, Mesh(self, self.geompyD, newMesh),
843                  newGroups, newSubMeshes, newHypotheses, invalidEntries )
844
845     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
846         """
847         Return IDs of sub-shapes
848
849         Parameters:
850                 theMainObject (GEOM.GEOM_Object): a shape
851                 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
852         Returns:
853                 the list of integer values
854         """
855
856         return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
857
858     def GetPattern(self):
859         """
860         Create a pattern mapper.
861
862         Returns:
863                 an instance of :class:`SMESH.SMESH_Pattern`
864
865         :ref:`Example of Patterns usage <tui_pattern_mapping>`
866         """
867
868         return SMESH._objref_SMESH_Gen.GetPattern(self)
869
870     def SetBoundaryBoxSegmentation(self, nbSegments):
871         """
872         Set number of segments per diagonal of boundary box of geometry, by which
873         default segment length of appropriate 1D hypotheses is defined in GUI.
874         Default value is 10.
875         """
876
877         SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
878
879     # Filtering. Auxiliary functions:
880     # ------------------------------
881
882     def GetEmptyCriterion(self):
883         """
884         Create an empty criterion
885
886         Returns:
887                 :class:`SMESH.Filter.Criterion`
888         """
889
890         Type = self.EnumToLong(FT_Undefined)
891         Compare = self.EnumToLong(FT_Undefined)
892         Threshold = 0
893         ThresholdStr = ""
894         ThresholdID = ""
895         UnaryOp = self.EnumToLong(FT_Undefined)
896         BinaryOp = self.EnumToLong(FT_Undefined)
897         Tolerance = 1e-07
898         TypeOfElement = ALL
899         Precision = -1 ##@1e-07
900         return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
901                                 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
902
903     def GetCriterion(self,elementType,
904                      CritType,
905                      Compare = FT_EqualTo,
906                      Threshold="",
907                      UnaryOp=FT_Undefined,
908                      BinaryOp=FT_Undefined,
909                      Tolerance=1e-07):
910         """
911         Create a criterion by the given parameters
912         Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
913
914         Parameters:
915                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
916                 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
917                         Note that the items starting from FT_LessThan are not suitable for *CritType*.
918                 Compare:  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
919                 Threshold: the threshold value (range of ids as string, shape, numeric)
920                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
921                 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
922                         SMESH.FT_Undefined
923                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
924                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
925
926         Returns:
927                 :class:`SMESH.Filter.Criterion`
928
929         Example: :ref:`combining_filters`
930         """
931
932         if not CritType in SMESH.FunctorType._items:
933             raise TypeError("CritType should be of SMESH.FunctorType")
934         aCriterion               = self.GetEmptyCriterion()
935         aCriterion.TypeOfElement = elementType
936         aCriterion.Type          = self.EnumToLong(CritType)
937         aCriterion.Tolerance     = Tolerance
938
939         aThreshold = Threshold
940
941         if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
942             aCriterion.Compare = self.EnumToLong(Compare)
943         elif Compare == "=" or Compare == "==":
944             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
945         elif Compare == "<":
946             aCriterion.Compare = self.EnumToLong(FT_LessThan)
947         elif Compare == ">":
948             aCriterion.Compare = self.EnumToLong(FT_MoreThan)
949         elif Compare != FT_Undefined:
950             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
951             aThreshold = Compare
952
953         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
954                         FT_BelongToCylinder, FT_LyingOnGeom]:
955             # Check that Threshold is GEOM object
956             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
957                 aCriterion.ThresholdStr = GetName(aThreshold)
958                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
959                 if not aCriterion.ThresholdID:
960                     name = aCriterion.ThresholdStr
961                     if not name:
962                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
963                     geompyD = aThreshold.GetGen()
964                     aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
965             # or a name of GEOM object
966             elif isinstance( aThreshold, str ):
967                 aCriterion.ThresholdStr = aThreshold
968             else:
969                 raise TypeError("The Threshold should be a shape.")
970             if isinstance(UnaryOp,float):
971                 aCriterion.Tolerance = UnaryOp
972                 UnaryOp = FT_Undefined
973                 pass
974         elif CritType == FT_BelongToMeshGroup:
975             # Check that Threshold is a group
976             if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
977                 if aThreshold.GetType() != elementType:
978                     raise ValueError("Group type mismatches Element type")
979                 aCriterion.ThresholdStr = aThreshold.GetName()
980                 aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
981                 study = salome.myStudy
982                 if study:
983                     so = study.FindObjectIOR( aCriterion.ThresholdID )
984                     if so:
985                         entry = so.GetID()
986                         if entry:
987                             aCriterion.ThresholdID = entry
988             else:
989                 raise TypeError("The Threshold should be a Mesh Group")
990         elif CritType == FT_RangeOfIds:
991             # Check that Threshold is string
992             if isinstance(aThreshold, str):
993                 aCriterion.ThresholdStr = aThreshold
994             else:
995                 raise TypeError("The Threshold should be a string.")
996         elif CritType == FT_CoplanarFaces:
997             # Check the Threshold
998             if isinstance(aThreshold, int):
999                 aCriterion.ThresholdID = str(aThreshold)
1000             elif isinstance(aThreshold, str):
1001                 ID = int(aThreshold)
1002                 if ID < 1:
1003                     raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
1004                 aCriterion.ThresholdID = aThreshold
1005             else:
1006                 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
1007         elif CritType == FT_ConnectedElements:
1008             # Check the Threshold
1009             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
1010                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
1011                 if not aCriterion.ThresholdID:
1012                     name = aThreshold.GetName()
1013                     if not name:
1014                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
1015                     geompyD = aThreshold.GetGen()
1016                     aCriterion.ThresholdID = geompyD.addToStudy( aThreshold, name )
1017             elif isinstance(aThreshold, int): # node id
1018                 aCriterion.Threshold = aThreshold
1019             elif isinstance(aThreshold, list): # 3 point coordinates
1020                 if len( aThreshold ) < 3:
1021                     raise ValueError("too few point coordinates, must be 3")
1022                 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
1023             elif isinstance(aThreshold, str):
1024                 if aThreshold.isdigit():
1025                     aCriterion.Threshold = aThreshold # node id
1026                 else:
1027                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
1028             else:
1029                 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
1030                       "or a list of point coordinates and not '%s'"%aThreshold)
1031         elif CritType == FT_ElemGeomType:
1032             # Check the Threshold
1033             try:
1034                 aCriterion.Threshold = self.EnumToLong(aThreshold)
1035                 assert( aThreshold in SMESH.GeometryType._items )
1036             except:
1037                 if isinstance(aThreshold, int):
1038                     aCriterion.Threshold = aThreshold
1039                 else:
1040                     raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
1041                 pass
1042             pass
1043         elif CritType == FT_EntityType:
1044             # Check the Threshold
1045             try:
1046                 aCriterion.Threshold = self.EnumToLong(aThreshold)
1047                 assert( aThreshold in SMESH.EntityType._items )
1048             except:
1049                 if isinstance(aThreshold, int):
1050                     aCriterion.Threshold = aThreshold
1051                 else:
1052                     raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
1053                 pass
1054             pass
1055
1056         elif CritType == FT_GroupColor:
1057             # Check the Threshold
1058             try:
1059                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
1060             except:
1061                 raise TypeError("The threshold value should be of SALOMEDS.Color type")
1062             pass
1063         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
1064                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
1065                           FT_BareBorderFace, FT_BareBorderVolume,
1066                           FT_OverConstrainedFace, FT_OverConstrainedVolume,
1067                           FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
1068             # At this point the Threshold is unnecessary
1069             if aThreshold ==  FT_LogicalNOT:
1070                 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1071             elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1072                 aCriterion.BinaryOp = aThreshold
1073         else:
1074             # Check Threshold
1075             try:
1076                 aThreshold = float(aThreshold)
1077                 aCriterion.Threshold = aThreshold
1078             except:
1079                 raise TypeError("The Threshold should be a number.")
1080                 return None
1081
1082         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT:
1083             aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1084
1085         if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1086             aCriterion.BinaryOp = self.EnumToLong(Threshold)
1087
1088         if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1089             aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1090
1091         if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1092             aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1093
1094         return aCriterion
1095
1096     def GetFilter(self,elementType,
1097                   CritType=FT_Undefined,
1098                   Compare=FT_EqualTo,
1099                   Threshold="",
1100                   UnaryOp=FT_Undefined,
1101                   Tolerance=1e-07,
1102                   mesh=None):
1103         """
1104         Create a filter with the given parameters
1105
1106         Parameters:
1107                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1108                 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1109                         Note that the items starting from FT_LessThan are not suitable for CritType.
1110                 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1111                 Threshold: the threshold value (range of ids as string, shape, numeric)
1112                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1113                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1114                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1115                 mesh: the mesh to initialize the filter with
1116
1117         Returns:
1118                 :class:`SMESH.Filter`
1119
1120         Examples:
1121                See :doc:`Filters usage examples <tui_filters>`
1122         """
1123
1124         aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1125         aFilterMgr = self.CreateFilterManager()
1126         aFilter = aFilterMgr.CreateFilter()
1127         aCriteria = []
1128         aCriteria.append(aCriterion)
1129         aFilter.SetCriteria(aCriteria)
1130         if mesh:
1131             if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1132             else                       : aFilter.SetMesh( mesh )
1133         aFilterMgr.UnRegister()
1134         return aFilter
1135
1136     def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1137         """
1138         Create a filter from criteria
1139
1140         Parameters:
1141                 criteria: a list of :class:`SMESH.Filter.Criterion`
1142                 binOp: binary operator used when binary operator of criteria is undefined
1143
1144         Returns:
1145                 :class:`SMESH.Filter`
1146
1147         Examples:
1148                See :doc:`Filters usage examples <tui_filters>`
1149         """
1150
1151         for i in range( len( criteria ) - 1 ):
1152             if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1153                 criteria[i].BinaryOp = self.EnumToLong( binOp )
1154         aFilterMgr = self.CreateFilterManager()
1155         aFilter = aFilterMgr.CreateFilter()
1156         aFilter.SetCriteria(criteria)
1157         aFilterMgr.UnRegister()
1158         return aFilter
1159
1160     def GetFunctor(self,theCriterion):
1161         """
1162         Create a numerical functor by its type
1163
1164         Parameters:
1165                 theCriterion (SMESH.FunctorType): functor type.
1166                         Note that not all items correspond to numerical functors.
1167
1168         Returns:
1169                 :class:`SMESH.NumericalFunctor`
1170         """
1171
1172         if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1173             return theCriterion
1174         aFilterMgr = self.CreateFilterManager()
1175         functor = None
1176         if theCriterion == FT_AspectRatio:
1177             functor = aFilterMgr.CreateAspectRatio()
1178         elif theCriterion == FT_AspectRatio3D:
1179             functor = aFilterMgr.CreateAspectRatio3D()
1180         elif theCriterion == FT_Warping:
1181             functor = aFilterMgr.CreateWarping()
1182         elif theCriterion == FT_MinimumAngle:
1183             functor = aFilterMgr.CreateMinimumAngle()
1184         elif theCriterion == FT_Taper:
1185             functor = aFilterMgr.CreateTaper()
1186         elif theCriterion == FT_Skew:
1187             functor = aFilterMgr.CreateSkew()
1188         elif theCriterion == FT_Area:
1189             functor = aFilterMgr.CreateArea()
1190         elif theCriterion == FT_Volume3D:
1191             functor = aFilterMgr.CreateVolume3D()
1192         elif theCriterion == FT_MaxElementLength2D:
1193             functor = aFilterMgr.CreateMaxElementLength2D()
1194         elif theCriterion == FT_MaxElementLength3D:
1195             functor = aFilterMgr.CreateMaxElementLength3D()
1196         elif theCriterion == FT_MultiConnection:
1197             functor = aFilterMgr.CreateMultiConnection()
1198         elif theCriterion == FT_MultiConnection2D:
1199             functor = aFilterMgr.CreateMultiConnection2D()
1200         elif theCriterion == FT_Length:
1201             functor = aFilterMgr.CreateLength()
1202         elif theCriterion == FT_Length2D:
1203             functor = aFilterMgr.CreateLength2D()
1204         elif theCriterion == FT_Length3D:
1205             functor = aFilterMgr.CreateLength3D()
1206         elif theCriterion == FT_Deflection2D:
1207             functor = aFilterMgr.CreateDeflection2D()
1208         elif theCriterion == FT_NodeConnectivityNumber:
1209             functor = aFilterMgr.CreateNodeConnectivityNumber()
1210         elif theCriterion == FT_BallDiameter:
1211             functor = aFilterMgr.CreateBallDiameter()
1212         else:
1213             print("Error: given parameter is not numerical functor type.")
1214         aFilterMgr.UnRegister()
1215         return functor
1216
1217     def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1218         """
1219         Create hypothesis
1220
1221         Parameters:
1222                 theHType (string): mesh hypothesis type
1223                 theLibName (string): mesh plug-in library name
1224
1225         Returns:
1226                 created hypothesis instance
1227         """
1228         hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1229
1230         if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1231             return hyp
1232
1233         # wrap hypothesis methods
1234         for meth_name in dir( hyp.__class__ ):
1235             if not meth_name.startswith("Get") and \
1236                not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1237                 method = getattr ( hyp.__class__, meth_name )
1238                 if callable(method):
1239                     setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1240
1241         return hyp
1242
1243     def GetHypothesisParameterValues( self, hypType, libName, mesh, shape, initParams ):
1244         """
1245         Create hypothesis initialized according to parameters
1246
1247         Parameters:
1248                 hypType (string): hypothesis type
1249                 libName (string): plug-in library name
1250                 mesh: optional mesh by which a hypotheses can initialize self
1251                 shape: optional geometry  by size of which a hypotheses can initialize self
1252                 initParams: structure SMESH.HypInitParams defining how to initialize a hypothesis
1253
1254         Returns:
1255                 created hypothesis instance
1256         """
1257         if isinstance( mesh, Mesh ):
1258             mesh = mesh.GetMesh()
1259         if isinstance( initParams, (bool,int)):
1260             initParams = SMESH.HypInitParams( not initParams, 1.0, not mesh )
1261         return SMESH._objref_SMESH_Gen.GetHypothesisParameterValues(self, hypType, libName,
1262                                                                     mesh, shape, initParams )
1263
1264     def GetMeshInfo(self, obj):
1265         """
1266         Get the mesh statistic.
1267
1268         Returns:
1269                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1270         """
1271
1272         if isinstance( obj, Mesh ):
1273             obj = obj.GetMesh()
1274         d = {}
1275         if hasattr(obj, "GetMeshInfo"):
1276             values = obj.GetMeshInfo()
1277             for i in range(SMESH.Entity_Last._v):
1278                 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1279             pass
1280         return d
1281
1282     def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1283         """
1284         Get minimum distance between two objects
1285
1286         * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1287         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1288
1289         Parameters:
1290                 src1 (SMESH.SMESH_IDSource): first source object
1291                 src2 (SMESH.SMESH_IDSource): second source object
1292                 id1 (int): node/element id from the first source
1293                 id2 (int): node/element id from the second (or first) source
1294                 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1295                 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1296
1297         Returns:
1298                 minimum distance value
1299
1300         See also: 
1301                 :meth:`GetMinDistance`
1302         """
1303
1304         result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1305         if result is None:
1306             result = 0.0
1307         else:
1308             result = result.value
1309         return result
1310
1311     def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1312         """
1313         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1314
1315         * If *src2* is None, and *id2*  = 0, distance from *src1* / *id1* to the origin is computed.
1316         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1317
1318         Parameters:
1319                 src1 (SMESH.SMESH_IDSource): first source object
1320                 src2 (SMESH.SMESH_IDSource): second source object
1321                 id1 (int): node/element id from the first source
1322                 id2 (int): node/element id from the second (or first) source
1323                 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1324                 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1325
1326         Returns:
1327                 :class:`SMESH.Measure` structure or None if input data is invalid
1328         See also: 
1329                 :meth:`MinDistance`
1330         """
1331
1332         if isinstance(src1, Mesh): src1 = src1.mesh
1333         if isinstance(src2, Mesh): src2 = src2.mesh
1334         if src2 is None and id2 != 0: src2 = src1
1335         if not hasattr(src1, "_narrow"): return None
1336         src1 = src1._narrow(SMESH.SMESH_IDSource)
1337         if not src1: return None
1338         unRegister = genObjUnRegister()
1339         if id1 != 0:
1340             m = src1.GetMesh()
1341             e = m.GetMeshEditor()
1342             if isElem1:
1343                 src1 = e.MakeIDSource([id1], SMESH.FACE)
1344             else:
1345                 src1 = e.MakeIDSource([id1], SMESH.NODE)
1346             unRegister.set( src1 )
1347             pass
1348         if hasattr(src2, "_narrow"):
1349             src2 = src2._narrow(SMESH.SMESH_IDSource)
1350             if src2 and id2 != 0:
1351                 m = src2.GetMesh()
1352                 e = m.GetMeshEditor()
1353                 if isElem2:
1354                     src2 = e.MakeIDSource([id2], SMESH.FACE)
1355                 else:
1356                     src2 = e.MakeIDSource([id2], SMESH.NODE)
1357                 unRegister.set( src2 )
1358                 pass
1359             pass
1360         aMeasurements = self.CreateMeasurements()
1361         unRegister.set( aMeasurements )
1362         result = aMeasurements.MinDistance(src1, src2)
1363         return result
1364
1365     def BoundingBox(self, objects):
1366         """
1367         Get bounding box of the specified object(s)
1368
1369         Parameters:
1370                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1371
1372         Returns:
1373                 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1374
1375         See also: 
1376                :meth:`GetBoundingBox`
1377         """
1378
1379         result = self.GetBoundingBox(objects)
1380         if result is None:
1381             result = (0.0,)*6
1382         else:
1383             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1384         return result
1385
1386     def GetBoundingBox(self, objects):
1387         """
1388         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1389
1390         Parameters:
1391                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1392
1393         Returns:
1394                 :class:`SMESH.Measure` structure
1395
1396         See also: 
1397                 :meth:`BoundingBox`
1398         """
1399
1400         if isinstance(objects, tuple):
1401             objects = list(objects)
1402         if not isinstance(objects, list):
1403             objects = [objects]
1404         srclist = []
1405         for o in objects:
1406             if isinstance(o, Mesh):
1407                 srclist.append(o.mesh)
1408             elif hasattr(o, "_narrow"):
1409                 src = o._narrow(SMESH.SMESH_IDSource)
1410                 if src: srclist.append(src)
1411                 pass
1412             pass
1413         aMeasurements = self.CreateMeasurements()
1414         result = aMeasurements.BoundingBox(srclist)
1415         aMeasurements.UnRegister()
1416         return result
1417
1418     def GetLength(self, obj):
1419         """
1420         Get sum of lengths of all 1D elements in the mesh object.
1421
1422         Parameters:
1423                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1424
1425         Returns:
1426                 sum of lengths of all 1D elements
1427         """
1428
1429         if isinstance(obj, Mesh): obj = obj.mesh
1430         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1431         aMeasurements = self.CreateMeasurements()
1432         value = aMeasurements.Length(obj)
1433         aMeasurements.UnRegister()
1434         return value
1435
1436     def GetArea(self, obj):
1437         """
1438         Get sum of areas of all 2D elements in the mesh object.
1439
1440         Parameters:
1441                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1442
1443         Returns:
1444                 sum of areas of all 2D elements
1445         """
1446
1447         if isinstance(obj, Mesh): obj = obj.mesh
1448         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1449         aMeasurements = self.CreateMeasurements()
1450         value = aMeasurements.Area(obj)
1451         aMeasurements.UnRegister()
1452         return value
1453
1454     def GetVolume(self, obj):
1455         """
1456         Get sum of volumes of all 3D elements in the mesh object.
1457
1458         Parameters:
1459                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1460
1461         Returns:
1462                 sum of volumes of all 3D elements
1463         """
1464
1465         if isinstance(obj, Mesh): obj = obj.mesh
1466         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1467         aMeasurements = self.CreateMeasurements()
1468         value = aMeasurements.Volume(obj)
1469         aMeasurements.UnRegister()
1470         return value
1471
1472     def GetGravityCenter(self, obj):
1473         """
1474         Get gravity center of all nodes of a mesh object.
1475         
1476         Parameters:            
1477                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1478
1479         Returns:        
1480                 Three components of the gravity center (x,y,z)
1481
1482         See also: 
1483                 :meth:`Mesh.BaryCenter`
1484         """
1485         if isinstance(obj, Mesh): obj = obj.mesh
1486         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1487         aMeasurements = self.CreateMeasurements()
1488         pointStruct = aMeasurements.GravityCenter(obj)
1489         aMeasurements.UnRegister()
1490         return pointStruct.x, pointStruct.y, pointStruct.z
1491
1492     def GetAngle(self, p1, p2, p3 ):
1493         """
1494         Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3)
1495
1496         Parameters:            
1497                 p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct 
1498                           or list [x,y,z]
1499
1500         Returns:        
1501             Angle in radians
1502         """
1503         if isinstance( p1, list ): p1 = PointStruct(*p1)
1504         if isinstance( p2, list ): p2 = PointStruct(*p2)
1505         if isinstance( p3, list ): p3 = PointStruct(*p3)
1506
1507         aMeasurements = self.CreateMeasurements()
1508         angle = aMeasurements.Angle(p1,p2,p3)
1509         aMeasurements.UnRegister()
1510
1511         return angle
1512
1513
1514     pass # end of class smeshBuilder
1515
1516 import omniORB
1517 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1518 """Registering the new proxy for SMESH.SMESH_Gen"""
1519
1520
1521 def New( instance=None, instanceGeom=None):
1522     """
1523     Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1524     interface to create or load meshes.
1525
1526     Typical use is::
1527
1528         import salome
1529         salome.salome_init()
1530         from salome.smesh import smeshBuilder
1531         smesh = smeshBuilder.New()
1532
1533     Parameters:
1534         instance:      CORBA proxy of SMESH Engine. If None, the default Engine is used.
1535         instanceGeom:  CORBA proxy of GEOM  Engine. If None, the default Engine is used.
1536     Returns:
1537         :class:`smeshBuilder` instance
1538     """
1539     global engine
1540     global smeshInst
1541     global doLcc
1542     if instance and isinstance( instance, SALOMEDS._objref_Study ):
1543         import sys
1544         sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1545         instance = None
1546     engine = instance
1547     if engine is None:
1548         doLcc = True
1549     smeshInst = smeshBuilder()
1550     assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1551     smeshInst.init_smesh(instanceGeom)
1552     return smeshInst
1553
1554
1555 # Public class: Mesh
1556 # ==================
1557
1558
1559 class Mesh(metaclass = MeshMeta):
1560     """
1561     This class allows defining and managing a mesh.
1562     It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1563     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1564     new nodes and elements and by changing the existing entities), to get information
1565     about a mesh and to export a mesh in different formats.
1566     """    
1567
1568     geom = 0
1569     mesh = 0
1570     editor = 0
1571
1572     def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1573
1574         """
1575         Constructor
1576
1577         Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1578         sets the GUI name of this mesh to *name*.
1579
1580         Parameters:
1581                 smeshpyD: an instance of smeshBuilder class
1582                 geompyD: an instance of geomBuilder class
1583                 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1584                 name: Study name of the mesh
1585         """
1586
1587         self.smeshpyD = smeshpyD
1588         self.geompyD = geompyD
1589         if obj is None:
1590             obj = 0
1591         objHasName = False
1592         if obj != 0:
1593             if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1594                 self.geom = obj
1595                 objHasName = True
1596                 # publish geom of mesh (issue 0021122)
1597                 if not self.geom.GetStudyEntry():
1598                     objHasName = False
1599                     geompyD.init_geom()
1600                     if name:
1601                         geo_name = name + " shape"
1602                     else:
1603                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1604                     geompyD.addToStudy( self.geom, geo_name )
1605                 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1606
1607             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1608                 self.SetMesh(obj)
1609         else:
1610             self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1611         if name:
1612             self.smeshpyD.SetName(self.mesh, name)
1613         elif objHasName:
1614             self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1615
1616         if not self.geom:
1617             self.geom = self.mesh.GetShapeToMesh()
1618
1619         self.editor   = self.mesh.GetMeshEditor()
1620         self.functors = [None] * SMESH.FT_Undefined._v
1621
1622         # set self to algoCreator's
1623         for attrName in dir(self):
1624             attr = getattr( self, attrName )
1625             if isinstance( attr, algoCreator ):
1626                 setattr( self, attrName, attr.copy( self ))
1627                 pass
1628             pass
1629         pass
1630
1631     def __del__(self):
1632         """
1633         Destructor. Clean-up resources
1634         """
1635         if self.mesh:
1636             #self.mesh.UnRegister()
1637             pass
1638         pass
1639
1640     def SetMesh(self, theMesh):
1641         """
1642         Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1643
1644         Parameters:
1645                 theMesh: a :class:`SMESH.SMESH_Mesh` object
1646         """
1647         # do not call Register() as this prevents mesh servant deletion at closing study
1648         #if self.mesh: self.mesh.UnRegister()
1649         self.mesh = theMesh
1650         if self.mesh:
1651             #self.mesh.Register()
1652             self.geom = self.mesh.GetShapeToMesh()
1653             if self.geom:
1654                 self.geompyD = None
1655                 try:
1656                     if salome.sg.hasDesktop():
1657                         so = salome.ObjectToSObject( self.geom )
1658                         comp = so.GetFatherComponent()
1659                         if comp.ComponentDataType() == "SHAPERSTUDY":
1660                             import shaperBuilder
1661                             self.geompyD = shaperBuilder.New()
1662                 except:
1663                     pass
1664                 if not self.geompyD:
1665                     self.geompyD = self.geom.GetGen()
1666                 pass
1667
1668     def GetMesh(self):
1669         """
1670         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1671
1672         Returns:
1673                 a :class:`SMESH.SMESH_Mesh` object
1674         """
1675
1676         return self.mesh
1677
1678     def GetEngine(self):
1679         """
1680         Return a smeshBuilder instance created this mesh
1681         """
1682         return self.smeshpyD
1683
1684     def GetGeomEngine(self):
1685         """
1686         Return a geomBuilder instance
1687         """
1688         return self.geompyD
1689
1690     def GetName(self):
1691         """
1692         Get the name of the mesh
1693
1694         Returns:
1695                 the name of the mesh as a string
1696         """
1697
1698         name = GetName(self.GetMesh())
1699         return name
1700
1701     def SetName(self, name):
1702         """
1703         Set a name to the mesh
1704
1705         Parameters:
1706                 name: a new name of the mesh
1707         """
1708
1709         self.smeshpyD.SetName(self.GetMesh(), name)
1710
1711     def GetSubMesh(self, geom, name):
1712         """
1713         Get a sub-mesh object associated to a *geom* geometrical object.
1714
1715         Parameters:
1716                 geom: a geometrical object (shape)
1717                 name: a name for the sub-mesh in the Object Browser
1718
1719         Returns:
1720                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1721                 which lies on the given shape
1722
1723         Note:
1724                 A sub-mesh is implicitly created when a sub-shape is specified at
1725                 creating an algorithm, for example::
1726
1727                    algo1D = mesh.Segment(geom=Edge_1)
1728
1729                 create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1730                 The created sub-mesh can be retrieved from the algorithm::
1731
1732                    submesh = algo1D.GetSubMesh()
1733         """
1734
1735         AssureGeomPublished( self, geom, name )
1736         submesh = self.mesh.GetSubMesh( geom, name )
1737         return submesh
1738
1739     def GetShape(self):
1740         """
1741         Return the shape associated to the mesh
1742
1743         Returns:
1744                 a GEOM_Object
1745         """
1746
1747         return self.geom
1748
1749     def SetShape(self, geom):
1750         """
1751         Associate the given shape to the mesh (entails the recreation of the mesh)
1752
1753         Parameters:
1754                 geom: the shape to be meshed (GEOM_Object)
1755         """
1756
1757         self.mesh = self.smeshpyD.CreateMesh(geom)
1758
1759     def HasShapeToMesh(self):
1760         """
1761         Return ``True`` if this mesh is based on geometry
1762         """
1763         return self.mesh.HasShapeToMesh()
1764
1765     def Load(self):
1766         """
1767         Load mesh from the study after opening the study
1768         """
1769         self.mesh.Load()
1770
1771     def IsReadyToCompute(self, theSubObject):
1772         """
1773         Return true if the hypotheses are defined well
1774
1775         Parameters:
1776                 theSubObject: a sub-shape of a mesh shape
1777
1778         Returns:
1779                 True or False
1780         """
1781
1782         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1783
1784     def GetAlgoState(self, theSubObject):
1785         """
1786         Return errors of hypotheses definition.
1787         The list of errors is empty if everything is OK.
1788
1789         Parameters:
1790                 theSubObject: a sub-shape of a mesh shape
1791
1792         Returns:
1793                 a list of errors
1794         """
1795
1796         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1797
1798     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1799         """
1800         Return a geometrical object on which the given element was built.
1801         The returned geometrical object, if not nil, is either found in the
1802         study or published by this method with the given name
1803
1804         Parameters:
1805             theElementID: the id of the mesh element
1806             theGeomName: the user-defined name of the geometrical object
1807
1808         Returns:
1809             GEOM.GEOM_Object instance
1810         """
1811
1812         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1813
1814     def MeshDimension(self):
1815         """
1816         Return the mesh dimension depending on the dimension of the underlying shape
1817         or, if the mesh is not based on any shape, basing on deimension of elements
1818
1819         Returns:
1820                 mesh dimension as an integer value [0,3]
1821         """
1822
1823         if self.mesh.HasShapeToMesh():
1824             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1825             if len( shells ) > 0 :
1826                 return 3
1827             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1828                 return 2
1829             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1830                 return 1
1831             else:
1832                 return 0;
1833         else:
1834             if self.NbVolumes() > 0: return 3
1835             if self.NbFaces()   > 0: return 2
1836             if self.NbEdges()   > 0: return 1
1837         return 0
1838
1839     def Evaluate(self, geom=0):
1840         """
1841         Evaluate size of prospective mesh on a shape
1842
1843         Returns:
1844                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1845                 To know predicted number of e.g. edges, inquire it this way::
1846
1847                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1848         """
1849
1850         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1851             if self.geom == 0:
1852                 geom = self.mesh.GetShapeToMesh()
1853             else:
1854                 geom = self.geom
1855         return self.smeshpyD.Evaluate(self.mesh, geom)
1856
1857
1858     def Compute(self, geom=0, discardModifs=False, refresh=False):
1859         """
1860         Compute the mesh and return the status of the computation
1861
1862         Parameters:
1863                 geom: geomtrical shape on which mesh data should be computed
1864                 discardModifs: if True and the mesh has been edited since
1865                         a last total re-compute and that may prevent successful partial re-compute,
1866                         then the mesh is cleaned before Compute()
1867                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1868
1869         Returns:
1870                 True or False
1871         """
1872
1873         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1874             geom = self.mesh.GetShapeToMesh()
1875         ok = False
1876         try:
1877             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1878                 self.mesh.Clear()
1879             ok = self.smeshpyD.Compute(self.mesh, geom)
1880         except SALOME.SALOME_Exception as ex:
1881             print("Mesh computation failed, exception caught:")
1882             print("    ", ex.details.text)
1883         except:
1884             import traceback
1885             print("Mesh computation failed, exception caught:")
1886             traceback.print_exc()
1887         if True:#not ok:
1888             allReasons = ""
1889
1890             # Treat compute errors
1891             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1892             shapeText = ""
1893             for err in computeErrors:
1894                 if self.mesh.HasShapeToMesh():
1895                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1896                 errText = ""
1897                 stdErrors = ["OK",                   #COMPERR_OK
1898                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1899                              "std::exception",       #COMPERR_STD_EXCEPTION
1900                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1901                              "..",                   #COMPERR_SLM_EXCEPTION
1902                              "Unknown exception",    #COMPERR_EXCEPTION
1903                              "Memory allocation problem", #COMPERR_MEMORY_PB
1904                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1905                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1906                              "Warning",              #COMPERR_WARNING
1907                              "Computation cancelled",#COMPERR_CANCELED
1908                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1909                 if err.code > 0:
1910                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1911                 else:
1912                     errText = "code %s" % -err.code
1913                 if errText: errText += ". "
1914                 errText += err.comment
1915                 if allReasons: allReasons += "\n"
1916                 if ok:
1917                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1918                 else:
1919                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1920                 pass
1921
1922             # Treat hyp errors
1923             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1924             for err in errors:
1925                 if err.isGlobalAlgo:
1926                     glob = "global"
1927                 else:
1928                     glob = "local"
1929                     pass
1930                 dim = err.algoDim
1931                 name = err.algoName
1932                 if len(name) == 0:
1933                     reason = '%s %sD algorithm is missing' % (glob, dim)
1934                 elif err.state == HYP_MISSING:
1935                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1936                               % (glob, dim, name, dim))
1937                 elif err.state == HYP_NOTCONFORM:
1938                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1939                 elif err.state == HYP_BAD_PARAMETER:
1940                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1941                               % ( glob, dim, name ))
1942                 elif err.state == HYP_BAD_GEOMETRY:
1943                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1944                               'geometry' % ( glob, dim, name ))
1945                 elif err.state == HYP_HIDDEN_ALGO:
1946                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1947                               'algorithm of upper dimension generating %sD mesh'
1948                               % ( glob, dim, name, glob, dim ))
1949                 else:
1950                     reason = ("For unknown reason. "
1951                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1952                     pass
1953                 if allReasons: allReasons += "\n"
1954                 allReasons += "-  " + reason
1955                 pass
1956             if not ok or allReasons != "":
1957                 msg = '"' + GetName(self.mesh) + '"'
1958                 if ok: msg += " has been computed with warnings"
1959                 else:  msg += " has not been computed"
1960                 if allReasons != "": msg += ":"
1961                 else:                msg += "."
1962                 print(msg)
1963                 print(allReasons)
1964             pass
1965         if salome.sg:
1966             if salome.sg.hasDesktop():
1967                 if not isinstance( refresh, list): # not a call from subMesh.Compute()
1968                     if refresh: salome.sg.updateObjBrowser()
1969
1970         return ok
1971
1972     def GetComputeErrors(self, shape=0 ):
1973         """
1974         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1975         """
1976
1977         if shape == 0:
1978             shape = self.mesh.GetShapeToMesh()
1979         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1980
1981     def GetSubShapeName(self, subShapeID ):
1982         """
1983         Return a name of a sub-shape by its ID.
1984         Possible variants (for *subShapeID* == 3):
1985
1986                 - **"Face_12"** - published sub-shape
1987                 - **FACE #3** - not published sub-shape
1988                 - **sub-shape #3** - invalid sub-shape ID
1989                 - **#3** - error in this function
1990
1991         Parameters:
1992                 subShapeID: a unique ID of a sub-shape
1993
1994         Returns:
1995                 a string describing the sub-shape
1996
1997         """
1998
1999         if not self.mesh.HasShapeToMesh():
2000             return ""
2001         try:
2002             shapeText = ""
2003             mainIOR  = salome.orb.object_to_string( self.GetShape() )
2004             s = salome.myStudy
2005             mainSO = s.FindObjectIOR(mainIOR)
2006             if mainSO:
2007                 if subShapeID == 1:
2008                     shapeText = '"%s"' % mainSO.GetName()
2009                 subIt = s.NewChildIterator(mainSO)
2010                 while subIt.More():
2011                     subSO = subIt.Value()
2012                     subIt.Next()
2013                     obj = subSO.GetObject()
2014                     if not obj: continue
2015                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
2016                     if not go: continue
2017                     try:
2018                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
2019                     except:
2020                         continue
2021                     if ids == subShapeID:
2022                         shapeText = '"%s"' % subSO.GetName()
2023                         break
2024             if not shapeText:
2025                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
2026                 if shape:
2027                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
2028                 else:
2029                     shapeText = 'sub-shape #%s' % (subShapeID)
2030         except:
2031             shapeText = "#%s" % (subShapeID)
2032         return shapeText
2033
2034     def GetFailedShapes(self, publish=False):
2035         """
2036         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
2037         error of an algorithm
2038
2039         Parameters:
2040                 publish: if *True*, the returned groups will be published in the study
2041
2042         Returns:
2043                 a list of GEOM groups each named after a failed algorithm
2044         """
2045
2046
2047         algo2shapes = {}
2048         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
2049         for err in computeErrors:
2050             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
2051             if not shape: continue
2052             if err.algoName in algo2shapes:
2053                 algo2shapes[ err.algoName ].append( shape )
2054             else:
2055                 algo2shapes[ err.algoName ] = [ shape ]
2056             pass
2057
2058         groups = []
2059         for algoName, shapes in list(algo2shapes.items()):
2060             while shapes:
2061                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
2062                 otherTypeShapes = []
2063                 sameTypeShapes  = []
2064                 group = self.geompyD.CreateGroup( self.geom, groupType )
2065                 for shape in shapes:
2066                     if shape.GetShapeType() == shapes[0].GetShapeType():
2067                         sameTypeShapes.append( shape )
2068                     else:
2069                         otherTypeShapes.append( shape )
2070                 self.geompyD.UnionList( group, sameTypeShapes )
2071                 if otherTypeShapes:
2072                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
2073                 else:
2074                     group.SetName( algoName )
2075                 groups.append( group )
2076                 shapes = otherTypeShapes
2077             pass
2078         if publish:
2079             for group in groups:
2080                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
2081         return groups
2082
2083     def GetMeshOrder(self):
2084         """
2085         Return sub-mesh objects list in meshing order
2086
2087         Returns:
2088                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2089         """
2090
2091         return self.mesh.GetMeshOrder()
2092
2093     def SetMeshOrder(self, submeshes):
2094         """
2095         Set priority of sub-meshes. It works in two ways:
2096         
2097         * For sub-meshes with assigned algorithms of same dimension generating mesh of
2098           *several dimensions*, it sets the order in which the sub-meshes are computed.
2099         * For the rest sub-meshes, it sets the order in which the sub-meshes are checked
2100           when looking for meshing parameters to apply to a sub-shape. To impose the 
2101           order in which sub-meshes with uni-dimensional algorithms are computed, 
2102           call **submesh.Compute()** in a desired order.
2103
2104         Parameters:
2105                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2106
2107         Warning: the method is for setting the order for all sub-meshes at once:
2108                  SetMeshOrder( [ [sm1, sm2, sm3], [sm4, sm5] ] )
2109         """
2110
2111         return self.mesh.SetMeshOrder(submeshes)
2112
2113     def Clear(self, refresh=False):
2114         """
2115         Remove all nodes and elements generated on geometry. Imported elements remain.
2116
2117         Parameters:
2118                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2119         """
2120
2121         self.mesh.Clear()
2122         if ( salome.sg.hasDesktop() ):
2123             if refresh: salome.sg.updateObjBrowser()
2124
2125     def ClearSubMesh(self, geomId, refresh=False):
2126         """
2127         Remove all nodes and elements of indicated shape
2128
2129         Parameters:
2130                 geomId: the ID of a sub-shape to remove elements on
2131                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2132         """
2133
2134         self.mesh.ClearSubMesh(geomId)
2135         if salome.sg.hasDesktop():
2136             if refresh: salome.sg.updateObjBrowser()
2137
2138     def AutomaticTetrahedralization(self, fineness=0):
2139         """
2140         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
2141
2142         Parameters:
2143                 fineness: [0.0,1.0] defines mesh fineness
2144
2145         Returns:
2146                 True or False
2147         """
2148
2149         dim = self.MeshDimension()
2150         # assign hypotheses
2151         self.RemoveGlobalHypotheses()
2152         self.Segment().AutomaticLength(fineness)
2153         if dim > 1 :
2154             self.Triangle().LengthFromEdges()
2155             pass
2156         if dim > 2 :
2157             self.Tetrahedron()
2158             pass
2159         return self.Compute()
2160
2161     def AutomaticHexahedralization(self, fineness=0):
2162         """
2163         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2164
2165         Parameters:
2166                 fineness: [0.0, 1.0] defines mesh fineness
2167
2168         Returns:
2169                 True or False
2170         """
2171
2172         dim = self.MeshDimension()
2173         # assign the hypotheses
2174         self.RemoveGlobalHypotheses()
2175         self.Segment().AutomaticLength(fineness)
2176         if dim > 1 :
2177             self.Quadrangle()
2178             pass
2179         if dim > 2 :
2180             self.Hexahedron()
2181             pass
2182         return self.Compute()
2183
2184     def AddHypothesis(self, hyp, geom=0):
2185         """
2186         Assign a hypothesis
2187
2188         Parameters:
2189                 hyp: a hypothesis to assign
2190                 geom: a subhape of mesh geometry
2191
2192         Returns:
2193                 :class:`SMESH.Hypothesis_Status`
2194         """
2195
2196         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2197             hyp, geom = geom, hyp
2198         if isinstance( hyp, Mesh_Algorithm ):
2199             hyp = hyp.GetAlgorithm()
2200             pass
2201         if not geom:
2202             geom = self.geom
2203             if not geom:
2204                 geom = self.mesh.GetShapeToMesh()
2205             pass
2206         isApplicable = True
2207         if self.mesh.HasShapeToMesh():
2208             hyp_type     = hyp.GetName()
2209             lib_name     = hyp.GetLibName()
2210             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2211             # if checkAll and geom:
2212             #     checkAll = geom.GetType() == 37
2213             checkAll     = False
2214             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2215         if isApplicable:
2216             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2217             status = self.mesh.AddHypothesis(geom, hyp)
2218         else:
2219             status = HYP_BAD_GEOMETRY, ""
2220         hyp_name = GetName( hyp )
2221         geom_name = ""
2222         if geom:
2223             geom_name = geom.GetName()
2224         isAlgo = hyp._narrow( SMESH_Algo )
2225         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2226         return status
2227
2228     def IsUsedHypothesis(self, hyp, geom):
2229         """
2230         Return True if an algorithm or hypothesis is assigned to a given shape
2231
2232         Parameters:
2233                 hyp: an algorithm or hypothesis to check
2234                 geom: a subhape of mesh geometry
2235
2236         Returns:
2237                 True of False
2238         """
2239
2240         if not hyp: # or not geom
2241             return False
2242         if isinstance( hyp, Mesh_Algorithm ):
2243             hyp = hyp.GetAlgorithm()
2244             pass
2245         hyps = self.GetHypothesisList(geom)
2246         for h in hyps:
2247             if h.GetId() == hyp.GetId():
2248                 return True
2249         return False
2250
2251     def RemoveHypothesis(self, hyp, geom=0):
2252         """
2253         Unassign a hypothesis
2254
2255         Parameters:
2256                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2257                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2258
2259         Returns:
2260                 :class:`SMESH.Hypothesis_Status`
2261         """
2262
2263         if not hyp:
2264             return None
2265         if isinstance( hyp, Mesh_Algorithm ):
2266             hyp = hyp.GetAlgorithm()
2267             pass
2268         shape = geom
2269         if not shape:
2270             shape = self.geom
2271             pass
2272         if self.IsUsedHypothesis( hyp, shape ):
2273             return self.mesh.RemoveHypothesis( shape, hyp )
2274         hypName = GetName( hyp )
2275         geoName = GetName( shape )
2276         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2277         return None
2278
2279     def GetHypothesisList(self, geom):
2280         """
2281         Get the list of hypotheses added on a geometry
2282
2283         Parameters:
2284                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2285
2286         Returns:
2287                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2288         """
2289
2290         return self.mesh.GetHypothesisList( geom )
2291
2292     def RemoveGlobalHypotheses(self):
2293         """
2294         Remove all global hypotheses
2295         """
2296
2297         current_hyps = self.mesh.GetHypothesisList( self.geom )
2298         for hyp in current_hyps:
2299             self.mesh.RemoveHypothesis( self.geom, hyp )
2300             pass
2301         pass
2302
2303     def ExportMEDCoupling(self, *args, **kwargs):
2304         """
2305         Export the mesh in a memory representation.
2306
2307         Parameters:
2308         auto_groups (boolean): parameter for creating/not creating
2309                 the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2310                 the typical use is auto_groups=False.
2311         overwrite (boolean): parameter for overwriting/not overwriting the file
2312         meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2313         autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2314
2315                 - 1D if all mesh nodes lie on OX coordinate axis, or
2316                 - 2D if all mesh nodes lie on XOY coordinate plane, or
2317                 - 3D in the rest cases.
2318
2319                 If *autoDimension* is *False*, the space dimension is always 3.
2320         fields: list of GEOM fields defined on the shape to mesh.
2321         geomAssocFields: each character of this string means a need to export a 
2322                 corresponding field; correspondence between fields and characters 
2323                 is following:
2324
2325                 - 'v' stands for "_vertices_" field;
2326                 - 'e' stands for "_edges_" field;
2327                 - 'f' stands for "_faces_" field;
2328                 - 's' stands for "_solids_" field.
2329
2330         zTolerance (float): tolerance in Z direction. If Z coordinate of a node is 
2331                         close to zero within a given tolerance, the coordinate is set to zero.
2332                         If *ZTolerance* is negative (default), the node coordinates are kept as is.
2333         """
2334         auto_groups     = args[0] if len(args) > 0 else False
2335         meshPart        = args[1] if len(args) > 1 else None
2336         autoDimension   = args[2] if len(args) > 2 else True
2337         fields          = args[3] if len(args) > 3 else []
2338         geomAssocFields = args[4] if len(args) > 4 else ''
2339         z_tolerance     = args[5] if len(args) > 5 else -1.
2340         # process keywords arguments
2341         auto_groups     = kwargs.get("auto_groups", auto_groups)
2342         meshPart        = kwargs.get("meshPart", meshPart)
2343         autoDimension   = kwargs.get("autoDimension", autoDimension)
2344         fields          = kwargs.get("fields", fields)
2345         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2346         z_tolerance     = kwargs.get("zTolerance", z_tolerance)
2347
2348         # invoke engine's function
2349         if meshPart or fields or geomAssocFields or z_tolerance > 0:
2350             unRegister = genObjUnRegister()
2351             if isinstance( meshPart, list ):
2352                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2353                 unRegister.set( meshPart )
2354
2355             z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
2356             self.mesh.SetParameters(Parameters)
2357
2358             return self.mesh.ExportPartToMEDCoupling(meshPart, auto_groups, autoDimension, fields, geomAssocFields, z_tolerance)
2359         else:
2360             intPtr = self.mesh.ExportMEDCoupling(auto_groups, autoDimension)
2361             import medcoupling
2362             dab = medcoupling.FromPyIntPtrToDataArrayByte(intPtr)
2363             return medcoupling.MEDFileMesh.New(dab)
2364
2365     def ExportMED(self, *args, **kwargs):
2366         """
2367         Export the mesh in a file in MED format
2368         allowing to overwrite the file if it exists or add the exported data to its contents
2369
2370         Parameters:
2371                 fileName: is the file name
2372                 auto_groups (boolean): parameter for creating/not creating
2373                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2374                         the typical use is auto_groups=False.
2375                 version (int): define the version (xy, where version is x.y.z) of MED file format.
2376                         For instance med 3.2.1 is coded 3*10+2 = 32, med 4.0.0 is coded 4*10+0 = 40.
2377                         The rules of compatibility to write a mesh in an older version than 
2378                         the current version depend on the current version. For instance, 
2379                         with med 4.0 it is possible to write/append med files in 4.0.0 (default)
2380                         or 3.2.1 or 3.3.1 formats.
2381                         If the version is equal to -1, the version is not changed (default).
2382                 overwrite (boolean): parameter for overwriting/not overwriting the file
2383                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2384                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2385
2386                         - 1D if all mesh nodes lie on OX coordinate axis, or
2387                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2388                         - 3D in the rest cases.
2389
2390                         If *autoDimension* is *False*, the space dimension is always 3.
2391                 fields: list of GEOM fields defined on the shape to mesh.
2392                 geomAssocFields: each character of this string means a need to export a 
2393                         corresponding field; correspondence between fields and characters 
2394                         is following:
2395
2396                         - 'v' stands for "_vertices_" field;
2397                         - 'e' stands for "_edges_" field;
2398                         - 'f' stands for "_faces_" field;
2399                         - 's' stands for "_solids_" field.
2400
2401                 zTolerance (float): tolerance in Z direction. If Z coordinate of a node is 
2402                              close to zero within a given tolerance, the coordinate is set to zero.
2403                              If *ZTolerance* is negative (default), the node coordinates are kept as is.
2404         """
2405         # process positional arguments
2406         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2407         fileName        = args[0]
2408         auto_groups     = args[1] if len(args) > 1 else False
2409         version         = args[2] if len(args) > 2 else -1
2410         overwrite       = args[3] if len(args) > 3 else True
2411         meshPart        = args[4] if len(args) > 4 else None
2412         autoDimension   = args[5] if len(args) > 5 else True
2413         fields          = args[6] if len(args) > 6 else []
2414         geomAssocFields = args[7] if len(args) > 7 else ''
2415         z_tolerance     = args[8] if len(args) > 8 else -1.
2416         # process keywords arguments
2417         auto_groups     = kwargs.get("auto_groups", auto_groups)
2418         version         = kwargs.get("version", version)
2419         version         = kwargs.get("minor", version)
2420         overwrite       = kwargs.get("overwrite", overwrite)
2421         meshPart        = kwargs.get("meshPart", meshPart)
2422         autoDimension   = kwargs.get("autoDimension", autoDimension)
2423         fields          = kwargs.get("fields", fields)
2424         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2425         z_tolerance     = kwargs.get("zTolerance", z_tolerance)
2426
2427         # invoke engine's function
2428         if meshPart or fields or geomAssocFields or z_tolerance > 0:
2429             unRegister = genObjUnRegister()
2430             if isinstance( meshPart, list ):
2431                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2432                 unRegister.set( meshPart )
2433
2434             z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
2435             self.mesh.SetParameters(Parameters)
2436
2437             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups,
2438                                        version, overwrite, autoDimension,
2439                                        fields, geomAssocFields, z_tolerance)
2440         else:
2441             self.mesh.ExportMED(fileName, auto_groups, version, overwrite, autoDimension)
2442
2443     def ExportSAUV(self, f, auto_groups=0):
2444         """
2445         Export the mesh in a file in SAUV format
2446
2447
2448         Parameters:
2449                 f: is the file name
2450                 auto_groups: boolean parameter for creating/not creating
2451                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2452                         the typical use is auto_groups=False.
2453         """
2454
2455         self.mesh.ExportSAUV(f, auto_groups)
2456
2457     def ExportDAT(self, f, meshPart=None):
2458         """
2459         Export the mesh in a file in DAT format
2460
2461         Parameters:
2462                 f: the file name
2463                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2464         """
2465
2466         if meshPart:
2467             unRegister = genObjUnRegister()
2468             if isinstance( meshPart, list ):
2469                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2470                 unRegister.set( meshPart )
2471             self.mesh.ExportPartToDAT( meshPart, f )
2472         else:
2473             self.mesh.ExportDAT(f)
2474
2475     def ExportUNV(self, f, meshPart=None):
2476         """
2477         Export the mesh in a file in UNV format
2478
2479         Parameters:
2480                 f: the file name
2481                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2482         """
2483
2484         if meshPart:
2485             unRegister = genObjUnRegister()
2486             if isinstance( meshPart, list ):
2487                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2488                 unRegister.set( meshPart )
2489             self.mesh.ExportPartToUNV( meshPart, f )
2490         else:
2491             self.mesh.ExportUNV(f)
2492
2493     def ExportSTL(self, f, ascii=1, meshPart=None):
2494         """
2495         Export the mesh in a file in STL format
2496
2497         Parameters:
2498                 f: the file name
2499                 ascii: defines the file encoding
2500                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2501         """
2502
2503         if meshPart:
2504             unRegister = genObjUnRegister()
2505             if isinstance( meshPart, list ):
2506                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2507                 unRegister.set( meshPart )
2508             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2509         else:
2510             self.mesh.ExportSTL(f, ascii)
2511
2512     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2513         """
2514         Export the mesh in a file in CGNS format
2515
2516         Parameters:
2517                 f: is the file name
2518                 overwrite: boolean parameter for overwriting/not overwriting the file
2519                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2520                 groupElemsByType: if True all elements of same entity type are exported at ones,
2521                         else elements are exported in order of their IDs which can cause creation
2522                         of multiple cgns sections
2523         """
2524
2525         unRegister = genObjUnRegister()
2526         if isinstance( meshPart, list ):
2527             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2528             unRegister.set( meshPart )
2529         if isinstance( meshPart, Mesh ):
2530             meshPart = meshPart.mesh
2531         elif not meshPart:
2532             meshPart = self.mesh
2533         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2534
2535     def ExportGMF(self, f, meshPart=None):
2536         """
2537         Export the mesh in a file in GMF format.
2538         GMF files must have .mesh extension for the ASCII format and .meshb for
2539         the bynary format. Other extensions are not allowed.
2540
2541         Parameters:
2542                 f: is the file name
2543                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2544         """
2545
2546         unRegister = genObjUnRegister()
2547         if isinstance( meshPart, list ):
2548             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2549             unRegister.set( meshPart )
2550         if isinstance( meshPart, Mesh ):
2551             meshPart = meshPart.mesh
2552         elif not meshPart:
2553             meshPart = self.mesh
2554         self.mesh.ExportGMF(meshPart, f, True)
2555
2556     def ExportToMED(self, *args, **kwargs):
2557         """
2558         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2559         Export the mesh in a file in MED format
2560         allowing to overwrite the file if it exists or add the exported data to its contents
2561
2562         Parameters:
2563                 fileName: the file name
2564                 opt (boolean): parameter for creating/not creating
2565                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2566                 overwrite: boolean parameter for overwriting/not overwriting the file
2567                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2568
2569                         - 1D if all mesh nodes lie on OX coordinate axis, or
2570                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2571                         - 3D in the rest cases.
2572
2573                         If **autoDimension** is *False*, the space dimension is always 3.
2574         """
2575     
2576         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2577         # process positional arguments
2578         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2579         fileName      = args[0]
2580         auto_groups   = args[1] if len(args) > 1 else False
2581         overwrite     = args[2] if len(args) > 2 else True
2582         autoDimension = args[3] if len(args) > 3 else True
2583         # process keywords arguments
2584         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2585         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2586         overwrite     = kwargs.get("overwrite", overwrite)
2587         autoDimension = kwargs.get("autoDimension", autoDimension)
2588         minor = -1
2589         # invoke engine's function
2590         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2591
2592     def ExportToMEDX(self, *args, **kwargs):
2593         """
2594         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2595         Export the mesh in a file in MED format
2596
2597         Parameters:
2598                 fileName: the file name
2599                 opt (boolean): parameter for creating/not creating
2600                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2601                 overwrite: boolean parameter for overwriting/not overwriting the file
2602                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2603
2604                         - 1D if all mesh nodes lie on OX coordinate axis, or
2605                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2606                         - 3D in the rest cases.
2607
2608                         If **autoDimension** is *False*, the space dimension is always 3.
2609                 """
2610
2611         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2612         # process positional arguments
2613         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2614         fileName      = args[0]
2615         auto_groups   = args[1] if len(args) > 1 else False
2616         overwrite     = args[2] if len(args) > 2 else True
2617         autoDimension = args[3] if len(args) > 3 else True
2618         # process keywords arguments
2619         auto_groups   = kwargs.get("auto_groups", auto_groups)
2620         overwrite     = kwargs.get("overwrite", overwrite)
2621         autoDimension = kwargs.get("autoDimension", autoDimension)
2622         minor = -1
2623         # invoke engine's function
2624         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2625         return
2626
2627
2628     def Append(self, meshes, uniteIdenticalGroups = True,
2629                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
2630         """
2631         Append given meshes into this mesh.
2632         All groups of input meshes will be created in this mesh.
2633
2634         Parameters:
2635                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to append
2636                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
2637                 mergeNodesAndElements: if True, equal nodes and elements are merged
2638                 mergeTolerance: tolerance for merging nodes
2639                 allGroups: forces creation of groups corresponding to every input mesh
2640         """
2641         self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups,
2642                                    mergeNodesAndElements, mergeTolerance, allGroups,
2643                                    meshToAppendTo = self.GetMesh() )
2644
2645     # Operations with groups:
2646     # ----------------------
2647     def CreateEmptyGroup(self, elementType, name):
2648         """
2649         Create an empty standalone mesh group
2650
2651         Parameters:
2652                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2653                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2654                 name: the name of the mesh group
2655
2656         Returns:
2657                 :class:`SMESH.SMESH_Group`
2658         """
2659
2660         return self.mesh.CreateGroup(elementType, name)
2661
2662     def Group(self, grp, name=""):
2663         """
2664         Create a mesh group based on the geometric object *grp*
2665         and give it a *name*.
2666         If *name* is not defined the name of the geometric group is used
2667
2668         Note:
2669                 Works like :meth:`GroupOnGeom`.
2670
2671         Parameters:
2672                 grp:  a geometric group, a vertex, an edge, a face or a solid
2673                 name: the name of the mesh group
2674
2675         Returns:
2676                 :class:`SMESH.SMESH_GroupOnGeom`
2677         """
2678
2679         return self.GroupOnGeom(grp, name)
2680
2681     def GroupOnGeom(self, grp, name="", typ=None):
2682         """
2683         Create a mesh group based on the geometrical object *grp*
2684         and give it a *name*.
2685         if *name* is not defined the name of the geometric group is used
2686
2687         Parameters:
2688                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2689                 name: the name of the mesh group
2690                 typ:  the type of elements in the group; either of
2691                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2692                         automatically detected by the type of the geometry
2693
2694         Returns:
2695                 :class:`SMESH.SMESH_GroupOnGeom`
2696         """
2697
2698         AssureGeomPublished( self, grp, name )
2699         if name == "":
2700             name = grp.GetName()
2701         if not typ:
2702             typ = self._groupTypeFromShape( grp )
2703         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2704
2705     def _groupTypeFromShape( self, shape ):
2706         """
2707         Pivate method to get a type of group on geometry
2708         """
2709         tgeo = str(shape.GetShapeType())
2710         if tgeo == "VERTEX":
2711             typ = NODE
2712         elif tgeo == "EDGE" or tgeo == "WIRE":
2713             typ = EDGE
2714         elif tgeo == "FACE" or tgeo == "SHELL":
2715             typ = FACE
2716         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2717             typ = VOLUME
2718         elif tgeo == "COMPOUND":
2719             try:
2720               sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2721             except:
2722               # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of
2723               # simplification of access in geomBuilder: omniORB.registerObjref
2724               from SHAPERSTUDY_utils import getEngine
2725               gen = getEngine()
2726               if gen:
2727                 sub = gen.GetIShapesOperations().ExtractSubShapes(shape, self.geompyD.ShapeType["SHAPE"], False)
2728             if not sub:
2729                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2730             return self._groupTypeFromShape( sub[0] )
2731         else:
2732             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2733         return typ
2734
2735     def GroupOnFilter(self, typ, name, filter):
2736         """
2737         Create a mesh group with given *name* based on the *filter*.
2738         It is a special type of group dynamically updating it's contents during
2739         mesh modification
2740
2741         Parameters:
2742                 typ: the type of elements in the group; either of
2743                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2744                 name: the name of the mesh group
2745                 filter (SMESH.Filter): the filter defining group contents
2746
2747         Returns:
2748                 :class:`SMESH.SMESH_GroupOnFilter`
2749         """
2750
2751         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2752
2753     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2754         """
2755         Create a mesh group by the given ids of elements
2756
2757         Parameters:
2758                 groupName: the name of the mesh group
2759                 elementType: the type of elements in the group; either of
2760                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2761                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2762
2763         Returns:
2764                 :class:`SMESH.SMESH_Group`
2765         """
2766
2767         group = self.mesh.CreateGroup(elementType, groupName)
2768         if isinstance( elemIDs, Mesh ):
2769             elemIDs = elemIDs.GetMesh()
2770         if hasattr( elemIDs, "GetIDs" ):
2771             if hasattr( elemIDs, "SetMesh" ):
2772                 elemIDs.SetMesh( self.GetMesh() )
2773             group.AddFrom( elemIDs )
2774         else:
2775             group.Add(elemIDs)
2776         return group
2777
2778     def MakeGroup(self,
2779                   groupName,
2780                   elementType,
2781                   CritType=FT_Undefined,
2782                   Compare=FT_EqualTo,
2783                   Threshold="",
2784                   UnaryOp=FT_Undefined,
2785                   Tolerance=1e-07):
2786         """
2787         Create a mesh group by the given conditions
2788
2789         Parameters:
2790                 groupName: the name of the mesh group
2791                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2792                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2793                         Note that the items starting from FT_LessThan are not suitable for CritType.
2794                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2795                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2796                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2797                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2798                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2799
2800         Returns:
2801                 :class:`SMESH.SMESH_GroupOnFilter`
2802         """
2803
2804         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2805         group = self.MakeGroupByCriterion(groupName, aCriterion)
2806         return group
2807
2808     def MakeGroupByCriterion(self, groupName, Criterion):
2809         """
2810         Create a mesh group by the given criterion
2811
2812         Parameters:
2813                 groupName: the name of the mesh group
2814                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2815
2816         Returns:
2817                 :class:`SMESH.SMESH_GroupOnFilter`
2818
2819         See Also:
2820                 :meth:`smeshBuilder.GetCriterion`
2821         """
2822
2823         return self.MakeGroupByCriteria( groupName, [Criterion] )
2824
2825     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2826         """
2827         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2828
2829         Parameters:
2830                 groupName: the name of the mesh group
2831                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2832                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2833
2834         Returns:
2835                 :class:`SMESH.SMESH_GroupOnFilter`
2836
2837         See Also:
2838                 :meth:`smeshBuilder.GetCriterion`
2839         """
2840
2841         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2842         group = self.MakeGroupByFilter(groupName, aFilter)
2843         return group
2844
2845     def MakeGroupByFilter(self, groupName, theFilter):
2846         """
2847         Create a mesh group by the given filter
2848
2849         Parameters:
2850                 groupName (string): the name of the mesh group
2851                 theFilter (SMESH.Filter): the filter
2852
2853         Returns:
2854                 :class:`SMESH.SMESH_GroupOnFilter`
2855
2856         See Also:
2857                 :meth:`smeshBuilder.GetFilter`
2858         """
2859
2860         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2861         #theFilter.SetMesh( self.mesh )
2862         #group.AddFrom( theFilter )
2863         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2864         return group
2865
2866     def RemoveGroup(self, group):
2867         """
2868         Remove a group
2869
2870         Parameters:
2871                 group (SMESH.SMESH_GroupBase): group to remove
2872         """
2873
2874         self.mesh.RemoveGroup(group)
2875
2876     def RemoveGroupWithContents(self, group):
2877         """
2878         Remove a group with its contents
2879
2880         Parameters:
2881                 group (SMESH.SMESH_GroupBase): group to remove
2882
2883         Note:
2884                 This operation can create gaps in numeration of nodes or elements.
2885                 Call :meth:`RenumberElements` to remove the gaps.
2886         """
2887
2888         self.mesh.RemoveGroupWithContents(group)
2889
2890     def GetGroups(self, elemType = SMESH.ALL):
2891         """
2892         Get the list of groups existing in the mesh in the order of creation 
2893         (starting from the oldest one)
2894
2895         Parameters:
2896                 elemType (SMESH.ElementType): type of elements the groups contain;
2897                         by default groups of elements of all types are returned
2898
2899         Returns:
2900                 a list of :class:`SMESH.SMESH_GroupBase`
2901         """
2902
2903         groups = self.mesh.GetGroups()
2904         if elemType == SMESH.ALL:
2905             return groups
2906         typedGroups = []
2907         for g in groups:
2908             if g.GetType() == elemType:
2909                 typedGroups.append( g )
2910                 pass
2911             pass
2912         return typedGroups
2913
2914     def NbGroups(self):
2915         """
2916         Get the number of groups existing in the mesh
2917
2918         Returns:
2919                 the quantity of groups as an integer value
2920         """
2921
2922         return self.mesh.NbGroups()
2923
2924     def GetGroupNames(self):
2925         """
2926         Get the list of names of groups existing in the mesh
2927
2928         Returns:
2929                 list of strings
2930         """
2931
2932         groups = self.GetGroups()
2933         names = []
2934         for group in groups:
2935             names.append(group.GetName())
2936         return names
2937
2938     def GetGroupByName(self, name, elemType = None):
2939         """
2940         Find groups by name and type
2941
2942         Parameters:
2943                 name (string): name of the group of interest
2944                 elemType (SMESH.ElementType): type of elements the groups contain;
2945                         by default one group of any type is returned;
2946                         if elemType == SMESH.ALL then all groups of any type are returned
2947
2948         Returns:
2949                 a list of :class:`SMESH.SMESH_GroupBase`
2950         """
2951
2952         groups = []
2953         for group in self.GetGroups():
2954             if group.GetName() == name:
2955                 if elemType is None:
2956                     return [group]
2957                 if ( elemType == SMESH.ALL or
2958                      group.GetType() == elemType ):
2959                     groups.append( group )
2960         return groups
2961
2962     def UnionGroups(self, group1, group2, name):
2963         """
2964         Produce a union of two groups.
2965         A new group is created. All mesh elements that are
2966         present in the initial groups are added to the new one
2967
2968         Parameters:
2969            group1 (SMESH.SMESH_GroupBase): a group
2970            group2 (SMESH.SMESH_GroupBase): another group
2971
2972         Returns:
2973                 instance of :class:`SMESH.SMESH_Group`
2974         """
2975
2976         return self.mesh.UnionGroups(group1, group2, name)
2977
2978     def UnionListOfGroups(self, groups, name):
2979         """
2980         Produce a union list of groups.
2981         New group is created. All mesh elements that are present in
2982         initial groups are added to the new one
2983
2984         Parameters:
2985            groups: list of :class:`SMESH.SMESH_GroupBase`
2986
2987         Returns:
2988                 instance of :class:`SMESH.SMESH_Group`
2989         """
2990         return self.mesh.UnionListOfGroups(groups, name)
2991
2992     def IntersectGroups(self, group1, group2, name):
2993         """
2994         Prodice an intersection of two groups.
2995         A new group is created. All mesh elements that are common
2996         for the two initial groups are added to the new one.
2997
2998         Parameters:
2999            group1 (SMESH.SMESH_GroupBase): a group
3000            group2 (SMESH.SMESH_GroupBase): another group
3001
3002         Returns:
3003                 instance of :class:`SMESH.SMESH_Group`
3004         """
3005
3006         return self.mesh.IntersectGroups(group1, group2, name)
3007
3008     def IntersectListOfGroups(self, groups, name):
3009         """
3010         Produce an intersection of groups.
3011         New group is created. All mesh elements that are present in all
3012         initial groups simultaneously are added to the new one
3013
3014         Parameters:
3015            groups: a list of :class:`SMESH.SMESH_GroupBase`
3016
3017         Returns:
3018                 instance of :class:`SMESH.SMESH_Group`
3019         """
3020         return self.mesh.IntersectListOfGroups(groups, name)
3021
3022     def CutGroups(self, main_group, tool_group, name):
3023         """
3024         Produce a cut of two groups.
3025         A new group is created. All mesh elements that are present in
3026         the main group but are not present in the tool group are added to the new one
3027
3028         Parameters:
3029            main_group (SMESH.SMESH_GroupBase): a group to cut from
3030            tool_group (SMESH.SMESH_GroupBase): a group to cut by
3031
3032         Returns:
3033                 an instance of :class:`SMESH.SMESH_Group`
3034         """
3035
3036         return self.mesh.CutGroups(main_group, tool_group, name)
3037
3038     def CutListOfGroups(self, main_groups, tool_groups, name):
3039         """
3040         Produce a cut of groups.
3041         A new group is created. All mesh elements that are present in main groups
3042         but do not present in tool groups are added to the new one
3043
3044         Parameters:
3045            main_group: groups to cut from  (list of :class:`SMESH.SMESH_GroupBase`)
3046            tool_group: groups to cut by    (list of :class:`SMESH.SMESH_GroupBase`)
3047
3048         Returns:
3049                 an instance of :class:`SMESH.SMESH_Group`
3050         """
3051
3052         return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
3053
3054     def CreateDimGroup(self, groups, elemType, name,
3055                        nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
3056         """
3057         Create a standalone group of entities basing on nodes of other groups.
3058
3059         Parameters:
3060                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
3061                 elemType: a type of elements to include to the new group; either of
3062                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
3063                 name: a name of the new group.
3064                 nbCommonNodes: a criterion of inclusion of an element to the new group
3065                         basing on number of element nodes common with reference *groups*.
3066                         Meaning of possible values are:
3067
3068                                 - SMESH.ALL_NODES - include if all nodes are common,
3069                                 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
3070                                 - SMESH.AT_LEAST_ONE - include if one or more node is common,
3071                                 - SMEHS.MAJORITY - include if half of nodes or more are common.
3072                 underlyingOnly: if *True* (default), an element is included to the
3073                         new group provided that it is based on nodes of an element of *groups*;
3074                         in this case the reference *groups* are supposed to be of higher dimension
3075                         than *elemType*, which can be useful for example to get all faces lying on
3076                         volumes of the reference *groups*.
3077
3078         Returns:
3079                 an instance of :class:`SMESH.SMESH_Group`
3080         """
3081
3082         if isinstance( groups, SMESH._objref_SMESH_IDSource ):
3083             groups = [groups]
3084         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
3085
3086     def FaceGroupsSeparatedByEdges( self, sharpAngle, createEdges=False, useExistingEdges=False ):
3087         """
3088         Distribute all faces of the mesh among groups using sharp edges and optionally
3089         existing 1D elements as group boundaries.
3090
3091         Parameters:
3092                 sharpAngle: edge is considered sharp if an angle between normals of
3093                             adjacent faces is more than \a sharpAngle in degrees.
3094                 createEdges (boolean): to create 1D elements for detected sharp edges.
3095                 useExistingEdges (boolean): to use existing edges as group boundaries
3096         Returns:
3097                 ListOfGroups - the created :class:`groups <SMESH.SMESH_Group>`
3098         """
3099         sharpAngle,Parameters,hasVars = ParseParameters( sharpAngle )
3100         self.mesh.SetParameters(Parameters)
3101         return self.mesh.FaceGroupsSeparatedByEdges( sharpAngle, createEdges, useExistingEdges );
3102
3103     def ConvertToStandalone(self, group):
3104         """
3105         Convert group on geom into standalone group
3106         """
3107
3108         return self.mesh.ConvertToStandalone(group)
3109
3110     # Get some info about mesh:
3111     # ------------------------
3112
3113     def GetLog(self, clearAfterGet):
3114         """
3115         Return the log of nodes and elements added or removed
3116         since the previous clear of the log.
3117
3118         Parameters:
3119                 clearAfterGet: log is emptied after Get (safe if concurrents access)
3120
3121         Returns:
3122                 list of SMESH.log_block structures { commandType, number, coords, indexes }
3123         """
3124
3125         return self.mesh.GetLog(clearAfterGet)
3126
3127     def ClearLog(self):
3128         """
3129         Clear the log of nodes and elements added or removed since the previous
3130         clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
3131         """
3132
3133         self.mesh.ClearLog()
3134
3135     def SetAutoColor(self, theAutoColor):
3136         """
3137         Toggle auto color mode on the object.
3138         If switched on, a default color of a new group in Create Group dialog is chosen randomly.
3139
3140         Parameters:
3141                 theAutoColor (boolean): the flag which toggles auto color mode.
3142         """
3143
3144         self.mesh.SetAutoColor(theAutoColor)
3145
3146     def GetAutoColor(self):
3147         """
3148         Get flag of object auto color mode.
3149
3150         Returns:
3151                 True or False
3152         """
3153
3154         return self.mesh.GetAutoColor()
3155
3156     def GetId(self):
3157         """
3158         Get the internal ID
3159
3160         Returns:
3161             integer value, which is the internal Id of the mesh
3162         """
3163
3164         return self.mesh.GetId()
3165
3166     def HasDuplicatedGroupNamesMED(self):
3167         """
3168         Check the group names for duplications.
3169         Consider the maximum group name length stored in MED file.
3170
3171         Returns:
3172             True or False
3173         """
3174
3175         return self.mesh.HasDuplicatedGroupNamesMED()
3176
3177     def GetMeshEditor(self):
3178         """
3179         Obtain the mesh editor tool
3180
3181         Returns:
3182             an instance of :class:`SMESH.SMESH_MeshEditor`
3183         """
3184
3185         return self.editor
3186
3187     def GetIDSource(self, ids, elemType = SMESH.ALL):
3188         """
3189         Wrap a list of IDs of elements or nodes into :class:`SMESH.SMESH_IDSource` which
3190         can be passed as argument to a method accepting :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
3191
3192         Parameters:
3193                 ids: list of IDs
3194                 elemType: type of elements; this parameter is used to distinguish
3195                         IDs of nodes from IDs of elements; by default ids are treated as
3196                         IDs of elements; use SMESH.NODE if ids are IDs of nodes.
3197
3198         Returns:
3199             an instance of :class:`SMESH.SMESH_IDSource`
3200
3201         Warning:
3202                 call UnRegister() for the returned object as soon as it is no more useful::
3203
3204                         idSrc = mesh.GetIDSource( [1,3,5], SMESH.NODE )
3205                         mesh.DoSomething( idSrc )
3206                         idSrc.UnRegister()
3207         """
3208
3209         if isinstance( ids, int ):
3210             ids = [ids]
3211         return self.editor.MakeIDSource(ids, elemType)
3212
3213
3214     # Get information about mesh contents:
3215     # ------------------------------------
3216
3217     def GetMeshInfo(self, obj = None):
3218         """
3219         Get the mesh statistic.
3220
3221         Returns:
3222                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
3223         """
3224
3225         if not obj: obj = self.mesh
3226         return self.smeshpyD.GetMeshInfo(obj)
3227
3228     def NbNodes(self):
3229         """
3230         Return the number of nodes in the mesh
3231
3232         Returns:
3233             an integer value
3234         """
3235
3236         return self.mesh.NbNodes()
3237
3238     def NbElements(self):
3239         """
3240         Return the number of elements in the mesh
3241
3242         Returns:
3243             an integer value
3244         """
3245
3246         return self.mesh.NbElements()
3247
3248     def Nb0DElements(self):
3249         """
3250         Return the number of 0d elements in the mesh
3251
3252         Returns:
3253             an integer value
3254         """
3255
3256         return self.mesh.Nb0DElements()
3257
3258     def NbBalls(self):
3259         """
3260         Return the number of ball discrete elements in the mesh
3261
3262         Returns:
3263             an integer value
3264         """
3265
3266         return self.mesh.NbBalls()
3267
3268     def NbEdges(self):
3269         """
3270         Return the number of edges in the mesh
3271
3272         Returns:
3273             an integer value
3274         """
3275
3276         return self.mesh.NbEdges()
3277
3278     def NbEdgesOfOrder(self, elementOrder):
3279         """
3280         Return the number of edges with the given order in the mesh
3281
3282         Parameters:
3283                 elementOrder: the order of elements
3284                      (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3285
3286         Returns:
3287             an integer value
3288         """
3289
3290         return self.mesh.NbEdgesOfOrder(elementOrder)
3291
3292     def NbFaces(self):
3293         """
3294         Return the number of faces in the mesh
3295
3296         Returns:
3297             an integer value
3298         """
3299
3300         return self.mesh.NbFaces()
3301
3302     def NbFacesOfOrder(self, elementOrder):
3303         """
3304         Return the number of faces with the given order in the mesh
3305
3306         Parameters:
3307                 elementOrder: the order of elements
3308                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3309
3310         Returns:
3311             an integer value
3312         """
3313
3314         return self.mesh.NbFacesOfOrder(elementOrder)
3315
3316     def NbTriangles(self):
3317         """
3318         Return the number of triangles in the mesh
3319
3320         Returns:
3321             an integer value
3322         """
3323
3324         return self.mesh.NbTriangles()
3325
3326     def NbTrianglesOfOrder(self, elementOrder):
3327         """
3328         Return the number of triangles with the given order in the mesh
3329
3330         Parameters:
3331                 elementOrder: is the order of elements
3332                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3333
3334         Returns:
3335             an integer value
3336         """
3337
3338         return self.mesh.NbTrianglesOfOrder(elementOrder)
3339
3340     def NbBiQuadTriangles(self):
3341         """
3342         Return the number of biquadratic triangles in the mesh
3343
3344         Returns:
3345             an integer value
3346         """
3347
3348         return self.mesh.NbBiQuadTriangles()
3349
3350     def NbQuadrangles(self):
3351         """
3352         Return the number of quadrangles in the mesh
3353
3354         Returns:
3355             an integer value
3356         """
3357
3358         return self.mesh.NbQuadrangles()
3359
3360     def NbQuadranglesOfOrder(self, elementOrder):
3361         """
3362         Return the number of quadrangles with the given order in the mesh
3363
3364         Parameters:
3365                 elementOrder: the order of elements
3366                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3367
3368         Returns:
3369             an integer value
3370         """
3371
3372         return self.mesh.NbQuadranglesOfOrder(elementOrder)
3373
3374     def NbBiQuadQuadrangles(self):
3375         """
3376         Return the number of biquadratic quadrangles in the mesh
3377
3378         Returns:
3379             an integer value
3380         """
3381
3382         return self.mesh.NbBiQuadQuadrangles()
3383
3384     def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
3385         """
3386         Return the number of polygons of given order in the mesh
3387
3388         Parameters:
3389                 elementOrder: the order of elements
3390                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3391
3392         Returns:
3393             an integer value
3394         """
3395
3396         return self.mesh.NbPolygonsOfOrder(elementOrder)
3397
3398     def NbVolumes(self):
3399         """
3400         Return the number of volumes in the mesh
3401
3402         Returns:
3403             an integer value
3404         """
3405
3406         return self.mesh.NbVolumes()
3407
3408
3409     def NbVolumesOfOrder(self, elementOrder):
3410         """
3411         Return the number of volumes with the given order in the mesh
3412
3413         Parameters:
3414                 elementOrder:  the order of elements
3415                     (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3416
3417         Returns:
3418             an integer value
3419         """
3420
3421         return self.mesh.NbVolumesOfOrder(elementOrder)
3422
3423     def NbTetras(self):
3424         """
3425         Return the number of tetrahedrons in the mesh
3426
3427         Returns:
3428             an integer value
3429         """
3430
3431         return self.mesh.NbTetras()
3432
3433     def NbTetrasOfOrder(self, elementOrder):
3434         """
3435         Return the number of tetrahedrons with the given order in the mesh
3436
3437         Parameters:
3438                 elementOrder:  the order of elements
3439                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3440
3441         Returns:
3442             an integer value
3443         """
3444
3445         return self.mesh.NbTetrasOfOrder(elementOrder)
3446
3447     def NbHexas(self):
3448         """
3449         Return the number of hexahedrons in the mesh
3450
3451         Returns:
3452             an integer value
3453         """
3454
3455         return self.mesh.NbHexas()
3456
3457     def NbHexasOfOrder(self, elementOrder):
3458         """
3459         Return the number of hexahedrons with the given order in the mesh
3460
3461         Parameters:
3462                 elementOrder:  the order of elements
3463                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3464
3465         Returns:
3466             an integer value
3467         """
3468
3469         return self.mesh.NbHexasOfOrder(elementOrder)
3470
3471     def NbTriQuadraticHexas(self):
3472         """
3473         Return the number of triquadratic hexahedrons in the mesh
3474
3475         Returns:
3476             an integer value
3477         """
3478
3479         return self.mesh.NbTriQuadraticHexas()
3480
3481     def NbPyramids(self):
3482         """
3483         Return the number of pyramids in the mesh
3484
3485         Returns:
3486             an integer value
3487         """
3488
3489         return self.mesh.NbPyramids()
3490
3491     def NbPyramidsOfOrder(self, elementOrder):
3492         """
3493         Return the number of pyramids with the given order in the mesh
3494
3495         Parameters:
3496                 elementOrder:  the order of elements
3497                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3498
3499         Returns:
3500             an integer value
3501         """
3502
3503         return self.mesh.NbPyramidsOfOrder(elementOrder)
3504
3505     def NbPrisms(self):
3506         """
3507         Return the number of prisms in the mesh
3508
3509         Returns:
3510             an integer value
3511         """
3512
3513         return self.mesh.NbPrisms()
3514
3515     def NbPrismsOfOrder(self, elementOrder):
3516         """
3517         Return the number of prisms with the given order in the mesh
3518
3519         Parameters:
3520                 elementOrder:  the order of elements
3521                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3522
3523         Returns:
3524             an integer value
3525         """
3526
3527         return self.mesh.NbPrismsOfOrder(elementOrder)
3528
3529     def NbHexagonalPrisms(self):
3530         """
3531         Return the number of hexagonal prisms in the mesh
3532
3533         Returns:
3534             an integer value
3535         """
3536
3537         return self.mesh.NbHexagonalPrisms()
3538
3539     def NbPolyhedrons(self):
3540         """
3541         Return the number of polyhedrons in the mesh
3542
3543         Returns:
3544             an integer value
3545         """
3546
3547         return self.mesh.NbPolyhedrons()
3548
3549     def NbSubMesh(self):
3550         """
3551         Return the number of submeshes in the mesh
3552
3553         Returns:
3554             an integer value
3555         """
3556
3557         return self.mesh.NbSubMesh()
3558
3559     def GetElementsId(self):
3560         """
3561         Return the list of all mesh elements IDs
3562
3563         Returns:
3564             the list of integer values
3565
3566         See Also:
3567             :meth:`GetElementsByType`
3568         """
3569
3570         return self.mesh.GetElementsId()
3571
3572     def GetElementsByType(self, elementType):
3573         """
3574         Return the list of IDs of mesh elements with the given type
3575
3576         Parameters:
3577                 elementType (SMESH.ElementType):  the required type of elements
3578
3579         Returns:
3580             list of integer values
3581         """
3582
3583         return self.mesh.GetElementsByType(elementType)
3584
3585     def GetNodesId(self):
3586         """
3587         Return the list of mesh nodes IDs
3588
3589         Returns:
3590             the list of integer values
3591         """
3592
3593         return self.mesh.GetNodesId()
3594
3595     # Get the information about mesh elements:
3596     # ------------------------------------
3597
3598     def GetElementType(self, id, iselem=True):
3599         """
3600         Return the type of mesh element or node
3601
3602         Returns:
3603             the value from :class:`SMESH.ElementType` enumeration. 
3604             Return SMESH.ALL if element or node with the given ID does not exist
3605         """
3606
3607         return self.mesh.GetElementType(id, iselem)
3608
3609     def GetElementGeomType(self, id):
3610         """
3611         Return the geometric type of mesh element
3612
3613         Returns:
3614             the value from :class:`SMESH.EntityType` enumeration.
3615         """
3616
3617         return self.mesh.GetElementGeomType(id)
3618
3619     def GetElementShape(self, id):
3620         """
3621         Return the shape type of mesh element
3622
3623         Returns:
3624             the value from :class:`SMESH.GeometryType` enumeration.
3625         """
3626
3627         return self.mesh.GetElementShape(id)
3628
3629     def GetSubMeshElementsId(self, Shape):
3630         """
3631         Return the list of sub-mesh elements IDs
3632
3633         Parameters:
3634                 Shape (GEOM.GEOM_Object): a geom object (sub-shape).
3635                        *Shape* must be the sub-shape of the :meth:`main shape <GetShape>`
3636
3637         Returns:
3638             list of integer values
3639         """
3640
3641         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3642             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3643         else:
3644             ShapeID = Shape
3645         return self.mesh.GetSubMeshElementsId(ShapeID)
3646
3647     def GetSubMeshNodesId(self, Shape, all):
3648         """
3649         Return the list of sub-mesh nodes IDs
3650
3651         Parameters:
3652                 Shape: a geom object (sub-shape).
3653                        *Shape* must be the sub-shape of a :meth:`GetShape`
3654                 all: If True, gives all nodes of sub-mesh elements, otherwise gives only sub-mesh nodes
3655
3656         Returns:
3657             list of integer values
3658         """
3659
3660         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3661             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3662         else:
3663             ShapeID = Shape
3664         return self.mesh.GetSubMeshNodesId(ShapeID, all)
3665
3666     def GetSubMeshElementType(self, Shape):
3667         """
3668         Return type of elements on given shape
3669
3670         Parameters:
3671                 Shape: a geom object (sub-shape).
3672                        *Shape* must be a sub-shape of a ShapeToMesh()
3673
3674         Returns:
3675             :class:`SMESH.ElementType`
3676         """
3677
3678         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3679             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3680         else:
3681             ShapeID = Shape
3682         return self.mesh.GetSubMeshElementType(ShapeID)
3683
3684     def Dump(self):
3685         """
3686         Get the mesh description
3687
3688         Returns:
3689             string value
3690         """
3691
3692         return self.mesh.Dump()
3693
3694
3695     # Get the information about nodes and elements of a mesh by its IDs:
3696     # -----------------------------------------------------------
3697
3698     def GetNodeXYZ(self, id):
3699         """
3700         Get XYZ coordinates of a node.
3701         If there is no node for the given ID - return an empty list
3702
3703         Returns:
3704             list of float values
3705         """
3706
3707         return self.mesh.GetNodeXYZ(id)
3708
3709     def GetNodeInverseElements(self, id, elemType=SMESH.ALL):
3710         """
3711         Return list of IDs of inverse elements for the given node.
3712         If there is no node for the given ID - return an empty list
3713
3714         Parameters:
3715                 id: node ID
3716                 elementType: :class:`type of elements <SMESH.ElementType>` (SMESH.EDGE, SMESH.FACE, SMESH.VOLUME, etc.)
3717
3718         Returns:
3719             list of integer values
3720         """
3721
3722         return self.mesh.GetNodeInverseElements(id,elemType)
3723
3724     def GetNodePosition(self,NodeID):
3725         """
3726         Return the position of a node on the shape
3727
3728         Returns:
3729             :class:`SMESH.NodePosition`
3730         """
3731
3732         return self.mesh.GetNodePosition(NodeID)
3733
3734     def GetElementPosition(self,ElemID):
3735         """
3736         Return the position of an element on the shape
3737
3738         Returns:
3739             :class:`SMESH.ElementPosition`
3740         """
3741
3742         return self.mesh.GetElementPosition(ElemID)
3743
3744     def GetShapeID(self, id):
3745         """
3746         Return the ID of the shape, on which the given node was generated.
3747
3748         Returns:
3749             an integer value > 0 or -1 if there is no node for the given
3750             ID or the node is not assigned to any geometry
3751         """
3752
3753         return self.mesh.GetShapeID(id)
3754
3755     def GetShapeIDForElem(self,id):
3756         """
3757         Return the ID of the shape, on which the given element was generated.
3758
3759         Returns:
3760             an integer value > 0 or -1 if there is no element for the given
3761             ID or the element is not assigned to any geometry
3762         """
3763
3764         return self.mesh.GetShapeIDForElem(id)
3765
3766     def GetElemNbNodes(self, id):
3767         """
3768         Return the number of nodes of the given element
3769
3770         Returns:
3771             an integer value > 0 or -1 if there is no element for the given ID
3772         """
3773
3774         return self.mesh.GetElemNbNodes(id)
3775
3776     def GetElemNode(self, id, index):
3777         """
3778         Return the node ID the given (zero based) index for the given element.
3779
3780         * If there is no element for the given ID - return -1.
3781         * If there is no node for the given index - return -2.
3782
3783         Parameters:
3784             id (int): element ID
3785             index (int): node index within the element
3786
3787         Returns:
3788             an integer value (ID)
3789
3790         See Also:
3791             :meth:`GetElemNodes`
3792         """
3793
3794         return self.mesh.GetElemNode(id, index)
3795
3796     def GetElemNodes(self, id):
3797         """
3798         Return the IDs of nodes of the given element
3799
3800         Returns:
3801             a list of integer values
3802         """
3803
3804         return self.mesh.GetElemNodes(id)
3805
3806     def IsMediumNode(self, elementID, nodeID):
3807         """
3808         Return true if the given node is the medium node in the given quadratic element
3809         """
3810
3811         return self.mesh.IsMediumNode(elementID, nodeID)
3812
3813     def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
3814         """
3815         Return true if the given node is the medium node in one of quadratic elements
3816
3817         Parameters:
3818                 nodeID: ID of the node
3819                 elementType:  the type of elements to check a state of the node, either of
3820                         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
3821         """
3822
3823         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
3824
3825     def ElemNbEdges(self, id):
3826         """
3827         Return the number of edges for the given element
3828         """
3829
3830         return self.mesh.ElemNbEdges(id)
3831
3832     def ElemNbFaces(self, id):
3833         """
3834         Return the number of faces for the given element
3835         """
3836
3837         return self.mesh.ElemNbFaces(id)
3838
3839     def GetElemFaceNodes(self,elemId, faceIndex):
3840         """
3841         Return nodes of given face (counted from zero) for given volumic element.
3842         """
3843
3844         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
3845
3846     def GetFaceNormal(self, faceId, normalized=False):
3847         """
3848         Return three components of normal of given mesh face
3849         (or an empty array in KO case)
3850         """
3851
3852         return self.mesh.GetFaceNormal(faceId,normalized)
3853
3854     def FindElementByNodes(self, nodes):
3855         """
3856         Return an element based on all given nodes.
3857         """
3858
3859         return self.mesh.FindElementByNodes(nodes)
3860
3861     def GetElementsByNodes(self, nodes, elemType=SMESH.ALL):
3862         """
3863         Return elements including all given nodes.
3864         """
3865
3866         return self.mesh.GetElementsByNodes( nodes, elemType )
3867
3868     def IsPoly(self, id):
3869         """
3870         Return true if the given element is a polygon
3871         """
3872
3873         return self.mesh.IsPoly(id)
3874
3875     def IsQuadratic(self, id):
3876         """
3877         Return true if the given element is quadratic
3878         """
3879
3880         return self.mesh.IsQuadratic(id)
3881
3882     def GetBallDiameter(self, id):
3883         """
3884         Return diameter of a ball discrete element or zero in case of an invalid *id*
3885         """
3886
3887         return self.mesh.GetBallDiameter(id)
3888
3889     def BaryCenter(self, id):
3890         """
3891         Return XYZ coordinates of the barycenter of the given element.
3892         If there is no element for the given ID - return an empty list
3893
3894         Returns:
3895             a list of three double values
3896
3897         See also: 
3898                 :meth:`smeshBuilder.GetGravityCenter`
3899         """
3900
3901         return self.mesh.BaryCenter(id)
3902
3903     def GetIdsFromFilter(self, filter, meshParts=[] ):
3904         """
3905         Pass mesh elements through the given filter and return IDs of fitting elements
3906
3907         Parameters:
3908                 filter: :class:`SMESH.Filter`
3909                 meshParts: list of mesh parts (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to filter
3910
3911         Returns:
3912             a list of ids
3913
3914         See Also:
3915             :meth:`SMESH.Filter.GetIDs`
3916             :meth:`SMESH.Filter.GetElementsIdFromParts`
3917         """
3918
3919         filter.SetMesh( self.mesh )
3920
3921         if meshParts:
3922             if isinstance( meshParts, Mesh ):
3923                 filter.SetMesh( meshParts.GetMesh() )
3924                 return theFilter.GetIDs()
3925             if isinstance( meshParts, SMESH._objref_SMESH_IDSource ):
3926                 meshParts = [ meshParts ]
3927             return filter.GetElementsIdFromParts( meshParts )
3928
3929         return filter.GetIDs()
3930
3931     # Get mesh measurements information:
3932     # ------------------------------------
3933
3934     def GetFreeBorders(self):
3935         """
3936         Verify whether a 2D mesh element has free edges (edges connected to one face only).
3937         Return a list of special structures (borders).
3938
3939         Returns:
3940             a list of :class:`SMESH.FreeEdges.Border`
3941         """
3942
3943         aFilterMgr = self.smeshpyD.CreateFilterManager()
3944         aPredicate = aFilterMgr.CreateFreeEdges()
3945         aPredicate.SetMesh(self.mesh)
3946         aBorders = aPredicate.GetBorders()
3947         aFilterMgr.UnRegister()
3948         return aBorders
3949
3950     def MinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3951         """
3952         Get minimum distance between two nodes, elements or distance to the origin
3953
3954         Parameters:
3955                 id1: first node/element id
3956                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3957                 isElem1: *True* if *id1* is element id, *False* if it is node id
3958                 isElem2: *True* if *id2* is element id, *False* if it is node id
3959
3960         Returns:
3961             minimum distance value
3962         See Also:
3963             :meth:`GetMinDistance`
3964         """
3965
3966         aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
3967         return aMeasure.value
3968
3969     def GetMinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3970         """
3971         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
3972
3973         Parameters:
3974                 id1: first node/element id
3975                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3976                 isElem1: *True* if *id1* is element id, *False* if it is node id
3977                 isElem2: *True* if *id2* is element id, *False* if it is node id
3978
3979         Returns:
3980             :class:`SMESH.Measure` structure
3981         See Also:
3982             :meth:`MinDistance`
3983         """
3984
3985         if isElem1:
3986             id1 = self.editor.MakeIDSource([id1], SMESH.FACE)
3987         else:
3988             id1 = self.editor.MakeIDSource([id1], SMESH.NODE)
3989         if id2 != 0:
3990             if isElem2:
3991                 id2 = self.editor.MakeIDSource([id2], SMESH.FACE)
3992             else:
3993                 id2 = self.editor.MakeIDSource([id2], SMESH.NODE)
3994             pass
3995         else:
3996             id2 = None
3997
3998         aMeasurements = self.smeshpyD.CreateMeasurements()
3999         aMeasure = aMeasurements.MinDistance(id1, id2)
4000         genObjUnRegister([aMeasurements,id1, id2])
4001         return aMeasure
4002
4003     def BoundingBox(self, objects=None, isElem=False):
4004         """
4005         Get bounding box of the specified object(s)
4006
4007         Parameters:
4008                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
4009                 isElem: if *objects* is a list of IDs, *True* value in this parameters specifies that *objects* are elements,
4010                         *False* specifies that *objects* are nodes
4011
4012         Returns:
4013             tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
4014
4015         See Also: 
4016             :meth:`GetBoundingBox()`
4017         """
4018
4019         result = self.GetBoundingBox(objects, isElem)
4020         if result is None:
4021             result = (0.0,)*6
4022         else:
4023             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
4024         return result
4025
4026     def GetBoundingBox(self, objects=None, isElem=False):
4027         """
4028         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
4029
4030         Parameters:
4031                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
4032                 isElem: if *objects* is a list of IDs, True means that *objects* are elements,
4033                         False means that *objects* are nodes
4034
4035         Returns:
4036             :class:`SMESH.Measure` structure
4037
4038         See Also: 
4039             :meth:`BoundingBox()`
4040         """
4041
4042         if objects is None:
4043             objects = [self.mesh]
4044         elif isinstance(objects, tuple):
4045             objects = list(objects)
4046         if not isinstance(objects, list):
4047             objects = [objects]
4048         if len(objects) > 0 and isinstance(objects[0], int):
4049             objects = [objects]
4050         srclist = []
4051         unRegister = genObjUnRegister()
4052         for o in objects:
4053             if isinstance(o, Mesh):
4054                 srclist.append(o.mesh)
4055             elif hasattr(o, "_narrow"):
4056                 src = o._narrow(SMESH.SMESH_IDSource)
4057                 if src: srclist.append(src)
4058                 pass
4059             elif isinstance(o, list):
4060                 if isElem:
4061                     srclist.append(self.editor.MakeIDSource(o, SMESH.FACE))
4062                 else:
4063                     srclist.append(self.editor.MakeIDSource(o, SMESH.NODE))
4064                 unRegister.set( srclist[-1] )
4065                 pass
4066             pass
4067         aMeasurements = self.smeshpyD.CreateMeasurements()
4068         unRegister.set( aMeasurements )
4069         aMeasure = aMeasurements.BoundingBox(srclist)
4070         return aMeasure
4071
4072     # Mesh edition (SMESH_MeshEditor functionality):
4073     # ---------------------------------------------
4074
4075     def RemoveElements(self, IDsOfElements):
4076         """
4077         Remove the elements from the mesh by ids
4078
4079         Parameters:
4080                 IDsOfElements: is a list of ids of elements to remove
4081
4082         Returns:
4083             True or False
4084
4085         Note:
4086                 This operation can create gaps in numeration of elements.
4087                 Call :meth:`RenumberElements` to remove the gaps.
4088         """
4089
4090         return self.editor.RemoveElements(IDsOfElements)
4091
4092     def RemoveNodes(self, IDsOfNodes):
4093         """
4094         Remove nodes from mesh by ids
4095
4096         Parameters:
4097                 IDsOfNodes: is a list of ids of nodes to remove
4098
4099         Returns:
4100             True or False
4101
4102         Note:
4103                 This operation can create gaps in numeration of nodes.
4104                 Call :meth:`RenumberElements` to remove the gaps.
4105         """
4106
4107         return self.editor.RemoveNodes(IDsOfNodes)
4108
4109     def RemoveOrphanNodes(self):
4110         """
4111         Remove all orphan (free) nodes from mesh
4112
4113         Returns:
4114             number of the removed nodes
4115
4116         Note:
4117                 This operation can create gaps in numeration of nodes.
4118                 Call :meth:`RenumberElements` to remove the gaps.
4119         """
4120
4121         return self.editor.RemoveOrphanNodes()
4122
4123     def AddNode(self, x, y, z):
4124         """
4125         Add a node to the mesh by coordinates
4126
4127         Returns:
4128             ID of the new node
4129         """
4130
4131         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4132         if hasVars: self.mesh.SetParameters(Parameters)
4133         return self.editor.AddNode( x, y, z)
4134
4135     def Add0DElement( self, IDOfNode, DuplicateElements=True ):
4136         """
4137         Create a 0D element on a node with given number.
4138
4139         Parameters:
4140                 IDOfNode: the ID of node for creation of the element.
4141                 DuplicateElements: to add one more 0D element to a node or not
4142
4143         Returns:
4144             ID of the new 0D element
4145         """
4146
4147         return self.editor.Add0DElement( IDOfNode, DuplicateElements )
4148
4149     def Add0DElementsToAllNodes(self, theObject, theGroupName="", DuplicateElements=False):
4150         """
4151         Create 0D elements on all nodes of the given elements except those
4152         nodes on which a 0D element already exists.
4153
4154         Parameters:
4155                 theObject: an object on whose nodes 0D elements will be created.
4156                         It can be list of element IDs, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4157                 theGroupName: optional name of a group to add 0D elements created
4158                         and/or found on nodes of *theObject*.
4159                 DuplicateElements: to add one more 0D element to a node or not
4160
4161         Returns:
4162             an object (a new group or a temporary :class:`SMESH.SMESH_IDSource`) holding
4163             IDs of new and/or found 0D elements. IDs of 0D elements
4164             can be retrieved from the returned object by 
4165             calling :meth:`GetIDs() <SMESH.SMESH_IDSource.GetIDs>`
4166         """
4167
4168         unRegister = genObjUnRegister()
4169         if isinstance( theObject, Mesh ):
4170             theObject = theObject.GetMesh()
4171         elif isinstance( theObject, list ):
4172             theObject = self.GetIDSource( theObject, SMESH.ALL )
4173             unRegister.set( theObject )
4174         return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName, DuplicateElements )
4175
4176     def AddBall(self, IDOfNode, diameter):
4177         """
4178         Create a ball element on a node with given ID.
4179
4180         Parameters:
4181                 IDOfNode: the ID of node for creation of the element.
4182                 diameter: the bal diameter.
4183
4184         Returns:
4185             ID of the new ball element
4186         """
4187
4188         return self.editor.AddBall( IDOfNode, diameter )
4189
4190     def AddEdge(self, IDsOfNodes):
4191         """
4192         Create a linear or quadratic edge (this is determined
4193         by the number of given nodes).
4194
4195         Parameters:
4196                 IDsOfNodes: list of node IDs for creation of the element.
4197                         The order of nodes in this list should correspond to
4198                         the :ref:`connectivity convention <connectivity_page>`.
4199
4200         Returns:
4201             ID of the new edge
4202         """
4203
4204         return self.editor.AddEdge(IDsOfNodes)
4205
4206     def AddFace(self, IDsOfNodes):
4207         """
4208         Create a linear or quadratic face (this is determined
4209         by the number of given nodes).
4210
4211         Parameters:
4212                 IDsOfNodes: list of node IDs for creation of the element.
4213                         The order of nodes in this list should correspond to
4214                         the :ref:`connectivity convention <connectivity_page>`.
4215
4216         Returns:
4217             ID of the new face
4218         """
4219
4220         return self.editor.AddFace(IDsOfNodes)
4221
4222     def AddPolygonalFace(self, IdsOfNodes):
4223         """
4224         Add a polygonal face defined by a list of node IDs
4225
4226         Parameters:
4227                 IdsOfNodes: the list of node IDs for creation of the element.
4228
4229         Returns:
4230             ID of the new face
4231         """
4232
4233         return self.editor.AddPolygonalFace(IdsOfNodes)
4234
4235     def AddQuadPolygonalFace(self, IdsOfNodes):
4236         """
4237         Add a quadratic polygonal face defined by a list of node IDs
4238
4239         Parameters:
4240                 IdsOfNodes: the list of node IDs for creation of the element;
4241                         corner nodes follow first.
4242
4243         Returns:
4244             ID of the new face
4245         """
4246
4247         return self.editor.AddQuadPolygonalFace(IdsOfNodes)
4248
4249     def AddVolume(self, IDsOfNodes):
4250         """
4251         Create both simple and quadratic volume (this is determined
4252         by the number of given nodes).
4253
4254         Parameters:
4255                 IDsOfNodes: list of node IDs for creation of the element.
4256                         The order of nodes in this list should correspond to
4257                         the :ref:`connectivity convention <connectivity_page>`.
4258
4259         Returns:
4260             ID of the new volumic element
4261         """
4262
4263         return self.editor.AddVolume(IDsOfNodes)
4264
4265     def AddPolyhedralVolume (self, IdsOfNodes, Quantities):
4266         """
4267         Create a volume of many faces, giving nodes for each face.
4268
4269         Parameters:
4270                 IdsOfNodes: list of node IDs for volume creation, face by face.
4271                 Quantities: list of integer values, Quantities[i]
4272                         gives the quantity of nodes in face number i.
4273
4274         Returns:
4275             ID of the new volumic element
4276         """
4277
4278         return self.editor.AddPolyhedralVolume(IdsOfNodes, Quantities)
4279
4280     def AddPolyhedralVolumeByFaces (self, IdsOfFaces):
4281         """
4282         Create a volume of many faces, giving the IDs of the existing faces.
4283
4284         Note:
4285                 The created volume will refer only to the nodes
4286                 of the given faces, not to the faces themselves.
4287
4288         Parameters:
4289                 IdsOfFaces: the list of face IDs for volume creation.
4290
4291         Returns:
4292             ID of the new volumic element
4293         """
4294
4295         return self.editor.AddPolyhedralVolumeByFaces(IdsOfFaces)
4296
4297
4298     def SetNodeOnVertex(self, NodeID, Vertex):
4299         """
4300         Bind a node to a vertex
4301
4302         Parameters:
4303                 NodeID: a node ID
4304                 Vertex: a vertex (GEOM.GEOM_Object) or vertex ID
4305
4306         Returns:
4307             True if succeed else raises an exception
4308         """
4309
4310         if ( isinstance( Vertex, geomBuilder.GEOM._objref_GEOM_Object)):
4311             VertexID = self.geompyD.GetSubShapeID( self.geom, Vertex )
4312         else:
4313             VertexID = Vertex
4314         try:
4315             self.editor.SetNodeOnVertex(NodeID, VertexID)
4316         except SALOME.SALOME_Exception as inst:
4317             raise ValueError(inst.details.text)
4318         return True
4319
4320
4321     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
4322         """
4323         Store the node position on an edge
4324
4325         Parameters:
4326                 NodeID: a node ID
4327                 Edge: an edge (GEOM.GEOM_Object) or edge ID
4328                 paramOnEdge: a parameter on the edge where the node is located
4329
4330         Returns:
4331             True if succeed else raises an exception
4332         """
4333
4334         if ( isinstance( Edge, geomBuilder.GEOM._objref_GEOM_Object)):
4335             EdgeID = self.geompyD.GetSubShapeID( self.geom, Edge )
4336         else:
4337             EdgeID = Edge
4338         try:
4339             self.editor.SetNodeOnEdge(NodeID, EdgeID, paramOnEdge)
4340         except SALOME.SALOME_Exception as inst:
4341             raise ValueError(inst.details.text)
4342         return True
4343
4344     def SetNodeOnFace(self, NodeID, Face, u, v):
4345         """
4346         Store node position on a face
4347
4348         Parameters:
4349                 NodeID: a node ID
4350                 Face: a face (GEOM.GEOM_Object) or face ID
4351                 u: U parameter on the face where the node is located
4352                 v: V parameter on the face where the node is located
4353
4354         Returns:
4355             True if succeed else raises an exception
4356         """
4357
4358         if ( isinstance( Face, geomBuilder.GEOM._objref_GEOM_Object)):
4359             FaceID = self.geompyD.GetSubShapeID( self.geom, Face )
4360         else:
4361             FaceID = Face
4362         try:
4363             self.editor.SetNodeOnFace(NodeID, FaceID, u, v)
4364         except SALOME.SALOME_Exception as inst:
4365             raise ValueError(inst.details.text)
4366         return True
4367
4368     def SetNodeInVolume(self, NodeID, Solid):
4369         """
4370         Bind a node to a solid
4371
4372         Parameters:
4373                 NodeID: a node ID
4374                 Solid:  a solid (GEOM.GEOM_Object) or solid ID
4375
4376         Returns:
4377             True if succeed else raises an exception
4378         """
4379
4380         if ( isinstance( Solid, geomBuilder.GEOM._objref_GEOM_Object)):
4381             SolidID = self.geompyD.GetSubShapeID( self.geom, Solid )
4382         else:
4383             SolidID = Solid
4384         try:
4385             self.editor.SetNodeInVolume(NodeID, SolidID)
4386         except SALOME.SALOME_Exception as inst:
4387             raise ValueError(inst.details.text)
4388         return True
4389
4390     def SetMeshElementOnShape(self, ElementID, Shape):
4391         """
4392         Bind an element to a shape
4393
4394         Parameters:
4395                 ElementID: an element ID
4396                 Shape: a shape (GEOM.GEOM_Object) or shape ID
4397
4398         Returns:
4399             True if succeed else raises an exception
4400         """
4401
4402         if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
4403             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
4404         else:
4405             ShapeID = Shape
4406         try:
4407             self.editor.SetMeshElementOnShape(ElementID, ShapeID)
4408         except SALOME.SALOME_Exception as inst:
4409             raise ValueError(inst.details.text)
4410         return True
4411
4412
4413     def MoveNode(self, NodeID, x, y, z):
4414         """
4415         Move the node with the given id
4416
4417         Parameters:
4418                 NodeID: the id of the node
4419                 x:  a new X coordinate
4420                 y:  a new Y coordinate
4421                 z:  a new Z coordinate
4422
4423         Returns:
4424             True if succeed else False
4425         """
4426
4427         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4428         if hasVars: self.mesh.SetParameters(Parameters)
4429         return self.editor.MoveNode(NodeID, x, y, z)
4430
4431     def MoveClosestNodeToPoint(self, x, y, z, NodeID):
4432         """
4433         Find the node closest to a point and moves it to a point location
4434
4435         Parameters:
4436                 x:  the X coordinate of a point
4437                 y:  the Y coordinate of a point
4438                 z:  the Z coordinate of a point
4439                 NodeID: if specified (>0), the node with this ID is moved,
4440                         otherwise, the node closest to point (*x*, *y*, *z*) is moved
4441
4442         Returns:
4443             the ID of a moved node
4444         """
4445
4446         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4447         if hasVars: self.mesh.SetParameters(Parameters)
4448         return self.editor.MoveClosestNodeToPoint(x, y, z, NodeID)
4449
4450     def FindNodeClosestTo(self, x, y, z):
4451         """
4452         Find the node closest to a point
4453
4454         Parameters:
4455                 x:  the X coordinate of a point
4456                 y:  the Y coordinate of a point
4457                 z:  the Z coordinate of a point
4458
4459         Returns:
4460             the ID of a node
4461         """
4462
4463         return self.editor.FindNodeClosestTo(x, y, z)
4464
4465     def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL, meshPart=None):
4466         """
4467         Find the elements where a point lays IN or ON
4468
4469         Parameters:
4470                 x,y,z (float): coordinates of the point
4471                 elementType (SMESH.ElementType): type of elements to find; SMESH.ALL type
4472                         means elements of any type excluding nodes, discrete and 0D elements.
4473                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to search within
4474
4475         Returns:
4476             list of IDs of found elements
4477         """
4478         if meshPart:
4479             return self.editor.FindAmongElementsByPoint( meshPart, x, y, z, elementType );
4480         else:
4481             return self.editor.FindElementsByPoint(x, y, z, elementType)
4482
4483     def ProjectPoint(self, x,y,z, elementType, meshObject=None):
4484         """
4485         Project a point to a mesh object.
4486         Return ID of an element of given type where the given point is projected
4487         and coordinates of the projection point.
4488         In the case if nothing found, return -1 and []
4489         """
4490         if isinstance( meshObject, Mesh ):
4491             meshObject = meshObject.GetMesh()
4492         if not meshObject:
4493             meshObject = self.GetMesh()
4494         return self.editor.ProjectPoint( x,y,z, elementType, meshObject )
4495
4496     def GetPointState(self, x, y, z):
4497         """
4498         Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
4499         smesh.TopAbs_IN, smesh.TopAbs_OUT, smesh.TopAbs_ON and smesh.TopAbs_UNKNOWN.
4500         UNKNOWN state means that either mesh is wrong or the analysis fails.
4501         """
4502
4503         return self.editor.GetPointState(x, y, z)
4504
4505     def IsManifold(self):
4506         """
4507         Check if a 2D mesh is manifold
4508         """
4509
4510         return self.editor.IsManifold()
4511
4512     def IsCoherentOrientation2D(self):
4513         """
4514         Check if orientation of 2D elements is coherent
4515         """
4516
4517         return self.editor.IsCoherentOrientation2D()
4518
4519     def Get1DBranches( self, edges, startNode = 0 ):
4520         """
4521         Partition given 1D elements into groups of contiguous edges.
4522         A node where number of meeting edges != 2 is a group end.
4523         An optional startNode is used to orient groups it belongs to.
4524
4525         Returns:
4526              A list of edge groups and a list of corresponding node groups,
4527              where the group is a list of IDs of edges or nodes, like follows
4528              [[[branch_edges_1],[branch_edges_2]], [[branch_nodes_1],[branch_nodes_2]]].
4529              If a group is closed, the first and last nodes of the group are same.
4530         """
4531         if isinstance( edges, Mesh ):
4532             edges = edges.GetMesh()
4533         unRegister = genObjUnRegister()
4534         if isinstance( edges, list ):
4535             edges = self.GetIDSource( edges, SMESH.EDGE )
4536             unRegister.set( edges )
4537         return self.editor.Get1DBranches( edges, startNode )
4538     
4539     def FindSharpEdges( self, angle, addExisting=False ):
4540         """
4541         Return sharp edges of faces and non-manifold ones.
4542         Optionally add existing edges.
4543
4544         Parameters:
4545                 angle: angle (in degrees) between normals of adjacent faces to detect sharp edges
4546                 addExisting: to return existing edges (1D elements) as well
4547
4548         Returns:
4549             list of FaceEdge structures
4550         """
4551         angle = ParseParameters( angle )[0]
4552         return self.editor.FindSharpEdges( angle, addExisting )
4553
4554     def MeshToPassThroughAPoint(self, x, y, z):
4555         """
4556         Find the node closest to a point and moves it to a point location
4557
4558         Parameters:
4559                 x:  the X coordinate of a point
4560                 y:  the Y coordinate of a point
4561                 z:  the Z coordinate of a point
4562
4563         Returns:
4564             the ID of a moved node
4565         """
4566
4567         return self.editor.MoveClosestNodeToPoint(x, y, z, -1)
4568
4569     def InverseDiag(self, NodeID1, NodeID2):
4570         """
4571         Replace two neighbour triangles sharing Node1-Node2 link
4572         with the triangles built on the same 4 nodes but having other common link.
4573
4574         Parameters:
4575                 NodeID1:  the ID of the first node
4576                 NodeID2:  the ID of the second node
4577
4578         Returns:
4579             False if proper faces were not found
4580         """
4581         return self.editor.InverseDiag(NodeID1, NodeID2)
4582
4583     def DeleteDiag(self, NodeID1, NodeID2):
4584         """
4585         Replace two neighbour triangles sharing *Node1-Node2* link
4586         with a quadrangle built on the same 4 nodes.
4587
4588         Parameters:
4589                 NodeID1: ID of the first node
4590                 NodeID2: ID of the second node
4591
4592         Returns:
4593             False if proper faces were not found
4594
4595         Note:
4596                 This operation can create gaps in numeration of elements.
4597                 Call :meth:`RenumberElements` to remove the gaps.
4598         """
4599
4600         return self.editor.DeleteDiag(NodeID1, NodeID2)
4601
4602     def Reorient(self, IDsOfElements=None):
4603         """
4604         Reorient elements by ids
4605
4606         Parameters:
4607                 IDsOfElements: if undefined reorients all mesh elements
4608
4609         Returns:
4610             True if succeed else False
4611         """
4612
4613         if IDsOfElements == None:
4614             IDsOfElements = self.GetElementsId()
4615         return self.editor.Reorient(IDsOfElements)
4616
4617     def ReorientObject(self, theObject):
4618         """
4619         Reorient all elements of the object
4620
4621         Parameters:
4622                 theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4623
4624         Returns:
4625             True if succeed else False
4626         """
4627
4628         if ( isinstance( theObject, Mesh )):
4629             theObject = theObject.GetMesh()
4630         return self.editor.ReorientObject(theObject)
4631
4632     def Reorient2D(self, the2DObject, theDirection, theFaceOrPoint ):
4633         """
4634         Reorient faces contained in *the2DObject*.
4635
4636         Parameters:
4637                 the2DObject: a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` or list of IDs of 2D elements
4638                 theDirection: a desired direction of normal of *theFace*.
4639                         It can be either a GEOM vector or a list of coordinates [x,y,z].
4640                 theFaceOrPoint: defines a face of *the2DObject* whose normal will be
4641                         compared with theDirection. It can be either ID of face or a point
4642                         by which the face will be found. The point can be given as either
4643                         a GEOM vertex or a list of point coordinates.
4644
4645         Returns:
4646             number of reoriented faces
4647         """
4648
4649         unRegister = genObjUnRegister()
4650         # check the2DObject
4651         if isinstance( the2DObject, Mesh ):
4652             the2DObject = the2DObject.GetMesh()
4653         if isinstance( the2DObject, list ):
4654             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4655             unRegister.set( the2DObject )
4656         # check theDirection
4657         if isinstance( theDirection, geomBuilder.GEOM._objref_GEOM_Object):
4658             theDirection = self.smeshpyD.GetDirStruct( theDirection )
4659         if isinstance( theDirection, list ):
4660             theDirection = self.smeshpyD.MakeDirStruct( *theDirection  )
4661         # prepare theFace and thePoint
4662         theFace = theFaceOrPoint
4663         thePoint = PointStruct(0,0,0)
4664         if isinstance( theFaceOrPoint, geomBuilder.GEOM._objref_GEOM_Object):
4665             thePoint = self.smeshpyD.GetPointStruct( theFaceOrPoint )
4666             theFace = -1
4667         if isinstance( theFaceOrPoint, list ):
4668             thePoint = PointStruct( *theFaceOrPoint )
4669             theFace = -1
4670         if isinstance( theFaceOrPoint, PointStruct ):
4671             thePoint = theFaceOrPoint
4672             theFace = -1
4673         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
4674
4675     def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
4676         """
4677         Reorient faces according to adjacent volumes.
4678
4679         Parameters:
4680                 the2DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of
4681                         either IDs of faces or face groups.
4682                 the3DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of IDs of volumes.
4683                 theOutsideNormal: to orient faces to have their normals
4684                         pointing either *outside* or *inside* the adjacent volumes.
4685
4686         Returns:
4687             number of reoriented faces.
4688         """
4689
4690         unRegister = genObjUnRegister()
4691         # check the2DObject
4692         if not isinstance( the2DObject, list ):
4693             the2DObject = [ the2DObject ]
4694         elif the2DObject and isinstance( the2DObject[0], int ):
4695             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4696             unRegister.set( the2DObject )
4697             the2DObject = [ the2DObject ]
4698         for i,obj2D in enumerate( the2DObject ):
4699             if isinstance( obj2D, Mesh ):
4700                 the2DObject[i] = obj2D.GetMesh()
4701             if isinstance( obj2D, list ):
4702                 the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
4703                 unRegister.set( the2DObject[i] )
4704         # check the3DObject
4705         if isinstance( the3DObject, Mesh ):
4706             the3DObject = the3DObject.GetMesh()
4707         if isinstance( the3DObject, list ):
4708             the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
4709             unRegister.set( the3DObject )
4710         return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
4711
4712     def TriToQuad(self, IDsOfElements, theCriterion, MaxAngle):
4713         """
4714         Fuse the neighbouring triangles into quadrangles.
4715
4716         Parameters:
4717                 IDsOfElements: The triangles to be fused.
4718                 theCriterion:  a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4719                         applied to possible quadrangles to choose a neighbour to fuse with.
4720                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4721                         to numerical functors.
4722                 MaxAngle: is the maximum angle between element normals at which the fusion
4723                         is still performed; theMaxAngle is measured in radians.
4724                         Also it could be a name of variable which defines angle in degrees.
4725
4726         Returns:
4727             True in case of success, False otherwise.
4728
4729         Note:
4730                 This operation can create gaps in numeration of elements.
4731                 Call :meth:`RenumberElements` to remove the gaps.
4732         """
4733
4734         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4735         self.mesh.SetParameters(Parameters)
4736         if not IDsOfElements:
4737             IDsOfElements = self.GetElementsId()
4738         Functor = self.smeshpyD.GetFunctor(theCriterion)
4739         return self.editor.TriToQuad(IDsOfElements, Functor, MaxAngle)
4740
4741     def TriToQuadObject (self, theObject, theCriterion, MaxAngle):
4742         """
4743         Fuse the neighbouring triangles of the object into quadrangles
4744
4745         Parameters:
4746                 theObject: is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4747                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`,
4748                         applied to possible quadrangles to choose a neighbour to fuse with.
4749                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4750                         to numerical functors.
4751                 MaxAngle: a max angle between element normals at which the fusion
4752                         is still performed; theMaxAngle is measured in radians.
4753
4754         Returns:
4755             True in case of success, False otherwise.
4756
4757         Note:
4758                 This operation can create gaps in numeration of elements.
4759                 Call :meth:`RenumberElements` to remove the gaps.
4760         """
4761
4762         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4763         self.mesh.SetParameters(Parameters)
4764         if isinstance( theObject, Mesh ):
4765             theObject = theObject.GetMesh()
4766         Functor = self.smeshpyD.GetFunctor(theCriterion)
4767         return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
4768
4769     def QuadToTri (self, IDsOfElements, theCriterion = None):
4770         """
4771         Split quadrangles into triangles.
4772
4773         Parameters:
4774                 IDsOfElements: the faces to be splitted.
4775                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4776                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4777                         value, then quadrangles will be split by the smallest diagonal.
4778                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4779                         to numerical functors.
4780
4781         Returns:
4782             True in case of success, False otherwise.
4783
4784         Note:
4785                 This operation can create gaps in numeration of elements.
4786                 Call :meth:`RenumberElements` to remove the gaps.
4787         """
4788         if IDsOfElements == []:
4789             IDsOfElements = self.GetElementsId()
4790         if theCriterion is None:
4791             theCriterion = FT_MaxElementLength2D
4792         Functor = self.smeshpyD.GetFunctor(theCriterion)
4793         return self.editor.QuadToTri(IDsOfElements, Functor)
4794
4795     def QuadToTriObject (self, theObject, theCriterion = None):
4796         """
4797         Split quadrangles into triangles.
4798
4799         Parameters:
4800                 theObject: the object from which the list of elements is taken,
4801                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4802                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4803                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4804                         value, then quadrangles will be split by the smallest diagonal.
4805                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4806                         to numerical functors.
4807
4808         Returns:
4809             True in case of success, False otherwise.
4810
4811         Note:
4812                 This operation can create gaps in numeration of elements.
4813                 Call :meth:`RenumberElements` to remove the gaps.
4814         """
4815         if ( isinstance( theObject, Mesh )):
4816             theObject = theObject.GetMesh()
4817         if theCriterion is None:
4818             theCriterion = FT_MaxElementLength2D
4819         Functor = self.smeshpyD.GetFunctor(theCriterion)
4820         return self.editor.QuadToTriObject(theObject, Functor)
4821
4822     def QuadTo4Tri (self, theElements=[]):
4823         """
4824         Split each of given quadrangles into 4 triangles. A node is added at the center of
4825         a quadrangle.
4826
4827         Parameters:
4828                 theElements: the faces to be splitted. This can be either 
4829                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
4830                         or a list of face IDs. By default all quadrangles are split
4831
4832         Note:
4833                 This operation can create gaps in numeration of elements.
4834                 Call :meth:`RenumberElements` to remove the gaps.
4835         """
4836         unRegister = genObjUnRegister()
4837         if isinstance( theElements, Mesh ):
4838             theElements = theElements.mesh
4839         elif not theElements:
4840             theElements = self.mesh
4841         elif isinstance( theElements, list ):
4842             theElements = self.GetIDSource( theElements, SMESH.FACE )
4843             unRegister.set( theElements )
4844         return self.editor.QuadTo4Tri( theElements )
4845
4846     def SplitQuad (self, IDsOfElements, Diag13):
4847         """
4848         Split quadrangles into triangles.
4849
4850         Parameters:
4851                 IDsOfElements: the faces to be splitted
4852                 Diag13 (boolean):        is used to choose a diagonal for splitting.
4853
4854         Returns:
4855             True in case of success, False otherwise.
4856
4857         Note:
4858                 This operation can create gaps in numeration of elements.
4859                 Call :meth:`RenumberElements` to remove the gaps.
4860         """
4861         if IDsOfElements == []:
4862             IDsOfElements = self.GetElementsId()
4863         return self.editor.SplitQuad(IDsOfElements, Diag13)
4864
4865     def SplitQuadObject (self, theObject, Diag13):
4866         """
4867         Split quadrangles into triangles.
4868
4869         Parameters:
4870                 theObject: the object from which the list of elements is taken,
4871                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4872                 Diag13 (boolean):    is used to choose a diagonal for splitting.
4873
4874         Returns:
4875             True in case of success, False otherwise.
4876
4877         Note:
4878                 This operation can create gaps in numeration of elements.
4879                 Call :meth:`RenumberElements` to remove the gaps.
4880         """
4881         if ( isinstance( theObject, Mesh )):
4882             theObject = theObject.GetMesh()
4883         return self.editor.SplitQuadObject(theObject, Diag13)
4884
4885     def BestSplit (self, IDOfQuad, theCriterion):
4886         """
4887         Find a better splitting of the given quadrangle.
4888
4889         Parameters:
4890                 IDOfQuad:   the ID of the quadrangle to be splitted.
4891                 theCriterion:  is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4892                         choose a diagonal for splitting.
4893                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4894                         to numerical functors.
4895
4896         Returns:
4897             * 1 if 1-3 diagonal is better, 
4898             * 2 if 2-4 diagonal is better, 
4899             * 0 if error occurs.
4900
4901         Note:
4902                 This operation can create gaps in numeration of elements.
4903                 Call :meth:`RenumberElements` to remove the gaps.
4904         """
4905         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
4906
4907     def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
4908         """
4909         Split volumic elements into tetrahedrons
4910
4911         Parameters:
4912                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4913                 method:  flags passing splitting method:
4914                         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
4915                         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
4916
4917         Note:
4918                 This operation can create gaps in numeration of elements.
4919                 Call :meth:`RenumberElements` to remove the gaps.
4920         """
4921         unRegister = genObjUnRegister()
4922         if isinstance( elems, Mesh ):
4923             elems = elems.GetMesh()
4924         if ( isinstance( elems, list )):
4925             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4926             unRegister.set( elems )
4927         self.editor.SplitVolumesIntoTetra(elems, method)
4928         return
4929
4930     def SplitBiQuadraticIntoLinear(self, elems=None):
4931         """
4932         Split bi-quadratic elements into linear ones without creation of additional nodes:
4933
4934             - bi-quadratic triangle will be split into 3 linear quadrangles;
4935             - bi-quadratic quadrangle will be split into 4 linear quadrangles;
4936             - tri-quadratic hexahedron will be split into 8 linear hexahedra.
4937
4938         Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
4939         will be split in order to keep the mesh conformal.
4940
4941         Parameters:
4942             elems: elements to split\: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or element IDs;
4943                 if None (default), all bi-quadratic elements will be split
4944
4945         Note:
4946                 This operation can create gaps in numeration of elements.
4947                 Call :meth:`RenumberElements` to remove the gaps.
4948         """
4949         unRegister = genObjUnRegister()
4950         if elems and isinstance( elems, list ) and isinstance( elems[0], int ):
4951             elems = self.editor.MakeIDSource(elems, SMESH.ALL)
4952             unRegister.set( elems )
4953         if elems is None:
4954             elems = [ self.GetMesh() ]
4955         if isinstance( elems, Mesh ):
4956             elems = [ elems.GetMesh() ]
4957         if not isinstance( elems, list ):
4958             elems = [elems]
4959         self.editor.SplitBiQuadraticIntoLinear( elems )
4960
4961     def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
4962                                  method=smeshBuilder.Hex_2Prisms, allDomains=False ):
4963         """
4964         Split hexahedra into prisms
4965
4966         Parameters:
4967                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4968                 startHexPoint: a point used to find a hexahedron for which *facetNormal*
4969                         gives a normal vector defining facets to split into triangles.
4970                         *startHexPoint* can be either a triple of coordinates or a vertex.
4971                 facetNormal: a normal to a facet to split into triangles of a
4972                         hexahedron found by *startHexPoint*.
4973                         *facetNormal* can be either a triple of coordinates or an edge.
4974                 method:  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
4975                         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
4976                 allDomains: if :code:`False`, only hexahedra adjacent to one closest
4977                         to *startHexPoint* are split, else *startHexPoint*
4978                         is used to find the facet to split in all domains present in *elems*.
4979
4980         Note:
4981                 This operation can create gaps in numeration of elements.
4982                 Call :meth:`RenumberElements` to remove the gaps.
4983         """
4984         # IDSource
4985         unRegister = genObjUnRegister()
4986         if isinstance( elems, Mesh ):
4987             elems = elems.GetMesh()
4988         if ( isinstance( elems, list )):
4989             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4990             unRegister.set( elems )
4991             pass
4992         # axis
4993         if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
4994             startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
4995         elif isinstance( startHexPoint, list ):
4996             startHexPoint = SMESH.PointStruct( startHexPoint[0],
4997                                                startHexPoint[1],
4998                                                startHexPoint[2])
4999         if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
5000             facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
5001         elif isinstance( facetNormal, list ):
5002             facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
5003                                                        facetNormal[1],
5004                                                        facetNormal[2])
5005         self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
5006
5007         self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
5008
5009     def SplitQuadsNearTriangularFacets(self):
5010         """
5011         Split quadrangle faces near triangular facets of volumes
5012
5013         Note:
5014                 This operation can create gaps in numeration of elements.
5015                 Call :meth:`RenumberElements` to remove the gaps.
5016         """
5017         faces_array = self.GetElementsByType(SMESH.FACE)
5018         for face_id in faces_array:
5019             if self.GetElemNbNodes(face_id) == 4: # quadrangle
5020                 quad_nodes = self.mesh.GetElemNodes(face_id)
5021                 node1_elems = self.GetNodeInverseElements(quad_nodes[1 -1])
5022                 isVolumeFound = False
5023                 for node1_elem in node1_elems:
5024                     if not isVolumeFound:
5025                         if self.GetElementType(node1_elem, True) == SMESH.VOLUME:
5026                             nb_nodes = self.GetElemNbNodes(node1_elem)
5027                             if 3 < nb_nodes and nb_nodes < 7: # tetra or penta, or prism
5028                                 volume_elem = node1_elem
5029                                 volume_nodes = self.mesh.GetElemNodes(volume_elem)
5030                                 if volume_nodes.count(quad_nodes[2 -1]) > 0: # 1,2
5031                                     if volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,2,4
5032                                         isVolumeFound = True
5033                                         if volume_nodes.count(quad_nodes[3 -1]) == 0: # 1,2,4 & !3
5034                                             self.SplitQuad([face_id], False) # diagonal 2-4
5035                                     elif volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,2,3 & !4
5036                                         isVolumeFound = True
5037                                         self.SplitQuad([face_id], True) # diagonal 1-3
5038                                 elif volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,4 & !2
5039                                     if volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,4,3 & !2
5040                                         isVolumeFound = True
5041                                         self.SplitQuad([face_id], True) # diagonal 1-3
5042
5043     def SplitHexaToTetras (self, theObject, theNode000, theNode001):
5044         """
5045         Split hexahedrons into tetrahedrons.
5046
5047         This operation uses :doc:`pattern_mapping` functionality for splitting.
5048
5049         Parameters:
5050                 theObject: the object from which the list of hexahedrons is taken; 
5051                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
5052                 theNode000,theNode001: within the range [0,7]; gives the orientation of the
5053                         pattern relatively each hexahedron: the (0,0,0) key-point of the pattern
5054                         will be mapped into *theNode000*-th node of each volume, the (0,0,1)
5055                         key-point will be mapped into *theNode001*-th node of each volume.
5056                         The (0,0,0) key-point of the used pattern corresponds to a non-split corner.
5057
5058         Returns:
5059             True in case of success, False otherwise.
5060
5061         Note:
5062                 This operation can create gaps in numeration of elements.
5063                 Call :meth:`RenumberElements` to remove the gaps.
5064         """
5065 #    Pattern:
5066 #                     5.---------.6
5067 #                    /|#*      /|
5068 #                   / | #*    / |
5069 #                  /  |  # * /  |
5070 #                 /   |   # /*  |
5071 #       (0,0,1) 4.---------.7 * |
5072 #                |#*  |1   | # *|
5073 #                | # *.----|---#.2
5074 #                |  #/ *   |   /
5075 #                |  /#  *  |  /
5076 #                | /   # * | /
5077 #                |/      #*|/
5078 #        (0,0,0) 0.---------.3
5079         pattern_tetra = "!!! Nb of points: \n 8 \n\
5080         !!! Points: \n\
5081         0 0 0  !- 0 \n\
5082         0 1 0  !- 1 \n\
5083         1 1 0  !- 2 \n\
5084         1 0 0  !- 3 \n\
5085         0 0 1  !- 4 \n\
5086         0 1 1  !- 5 \n\
5087         1 1 1  !- 6 \n\
5088         1 0 1  !- 7 \n\
5089         !!! Indices of points of 6 tetras: \n\
5090         0 3 4 1 \n\
5091         7 4 3 1 \n\
5092         4 7 5 1 \n\
5093         6 2 5 7 \n\
5094         1 5 2 7 \n\
5095         2 3 1 7 \n"
5096
5097         pattern = self.smeshpyD.GetPattern()
5098         isDone  = pattern.LoadFromFile(pattern_tetra)
5099         if not isDone:
5100             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
5101             return isDone
5102
5103         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
5104         isDone = pattern.MakeMesh(self.mesh, False, False)
5105         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
5106
5107         # split quafrangle faces near triangular facets of volumes
5108         self.SplitQuadsNearTriangularFacets()
5109
5110         return isDone
5111
5112     def SplitHexaToPrisms (self, theObject, theNode000, theNode001):
5113         """
5114         Split hexahedrons into prisms.
5115
5116         Uses the :doc:`pattern_mapping` functionality for splitting.
5117
5118         Parameters:
5119                 theObject: the object (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`) from where the list of hexahedrons is taken;
5120                 theNode000,theNode001: (within the range [0,7]) gives the orientation of the
5121                         pattern relatively each hexahedron: keypoint (0,0,0) of the pattern
5122                         will be mapped into the *theNode000* -th node of each volume, keypoint (0,0,1)
5123                         will be mapped into the *theNode001* -th node of each volume.
5124                         Edge (0,0,0)-(0,0,1) of used pattern connects two not split corners.
5125
5126         Returns:
5127             True in case of success, False otherwise.
5128
5129         Note:
5130                 This operation can create gaps in numeration of elements.
5131                 Call :meth:`RenumberElements` to remove the gaps.
5132         """
5133 #        Pattern:     5.---------.6
5134 #                     /|#       /|
5135 #                    / | #     / |
5136 #                   /  |  #   /  |
5137 #                  /   |   # /   |
5138 #        (0,0,1) 4.---------.7   |
5139 #                 |    |    |    |
5140 #                 |   1.----|----.2
5141 #                 |   / *   |   /
5142 #                 |  /   *  |  /
5143 #                 | /     * | /
5144 #                 |/       *|/
5145 #        (0,0,0) 0.---------.3
5146         pattern_prism = "!!! Nb of points: \n 8 \n\
5147         !!! Points: \n\
5148         0 0 0  !- 0 \n\
5149         0 1 0  !- 1 \n\
5150         1 1 0  !- 2 \n\
5151         1 0 0  !- 3 \n\
5152         0 0 1  !- 4 \n\
5153         0 1 1  !- 5 \n\
5154         1 1 1  !- 6 \n\
5155         1 0 1  !- 7 \n\
5156         !!! Indices of points of 2 prisms: \n\
5157         0 1 3 4 5 7 \n\
5158         2 3 1 6 7 5 \n"
5159
5160         pattern = self.smeshpyD.GetPattern()
5161         isDone  = pattern.LoadFromFile(pattern_prism)
5162         if not isDone:
5163             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
5164             return isDone
5165
5166         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
5167         isDone = pattern.MakeMesh(self.mesh, False, False)
5168         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
5169
5170         # Split quafrangle faces near triangular facets of volumes
5171         self.SplitQuadsNearTriangularFacets()
5172
5173         return isDone
5174
5175     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
5176                MaxNbOfIterations, MaxAspectRatio, Method):
5177         """
5178         Smooth elements
5179
5180         Parameters:
5181                 IDsOfElements: the list if ids of elements to smooth
5182                 IDsOfFixedNodes: the list of ids of fixed nodes.
5183                         Note that nodes built on edges and boundary nodes are always fixed.
5184                 MaxNbOfIterations: the maximum number of iterations
5185                 MaxAspectRatio: varies in range [1.0, inf]
5186                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5187                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5188
5189         Returns:
5190             True in case of success, False otherwise.
5191         """
5192
5193         if IDsOfElements == []:
5194             IDsOfElements = self.GetElementsId()
5195         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
5196         self.mesh.SetParameters(Parameters)
5197         return self.editor.Smooth(IDsOfElements, IDsOfFixedNodes,
5198                                   MaxNbOfIterations, MaxAspectRatio, Method)
5199
5200     def SmoothObject(self, theObject, IDsOfFixedNodes,
5201                      MaxNbOfIterations, MaxAspectRatio, Method):
5202         """
5203         Smooth elements which belong to the given object
5204
5205         Parameters:
5206                 theObject: the object to smooth
5207                 IDsOfFixedNodes: the list of ids of fixed nodes.
5208                         Note that nodes built on edges and boundary nodes are always fixed.
5209                 MaxNbOfIterations: the maximum number of iterations
5210                 MaxAspectRatio: varies in range [1.0, inf]
5211                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5212                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5213
5214         Returns:
5215             True in case of success, False otherwise.
5216         """
5217
5218         if ( isinstance( theObject, Mesh )):
5219             theObject = theObject.GetMesh()
5220         return self.editor.SmoothObject(theObject, IDsOfFixedNodes,
5221                                         MaxNbOfIterations, MaxAspectRatio, Method)
5222
5223     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
5224                          MaxNbOfIterations, MaxAspectRatio, Method):
5225         """
5226         Parametrically smooth the given elements
5227
5228         Parameters:
5229                 IDsOfElements: the list if ids of elements to smooth
5230                 IDsOfFixedNodes: the list of ids of fixed nodes.
5231                         Note that nodes built on edges and boundary nodes are always fixed.
5232                 MaxNbOfIterations: the maximum number of iterations
5233                 MaxAspectRatio: varies in range [1.0, inf]
5234                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5235                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5236
5237         Returns:
5238             True in case of success, False otherwise.
5239         """
5240
5241         if IDsOfElements == []:
5242             IDsOfElements = self.GetElementsId()
5243         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
5244         self.mesh.SetParameters(Parameters)
5245         return self.editor.SmoothParametric(IDsOfElements, IDsOfFixedNodes,
5246                                             MaxNbOfIterations, MaxAspectRatio, Method)
5247
5248     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
5249                                MaxNbOfIterations, MaxAspectRatio, Method):
5250         """
5251         Parametrically smooth the elements which belong to the given object
5252
5253         Parameters:
5254                 theObject: the object to smooth
5255                 IDsOfFixedNodes: the list of ids of fixed nodes.
5256                         Note that nodes built on edges and boundary nodes are always fixed.
5257                 MaxNbOfIterations: the maximum number of iterations
5258                 MaxAspectRatio: varies in range [1.0, inf]
5259                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5260                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5261
5262         Returns:
5263             True in case of success, False otherwise.
5264         """
5265
5266         if ( isinstance( theObject, Mesh )):
5267             theObject = theObject.GetMesh()
5268         return self.editor.SmoothParametricObject(theObject, IDsOfFixedNodes,
5269                                                   MaxNbOfIterations, MaxAspectRatio, Method)
5270
5271     def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
5272         """
5273         Convert the mesh to quadratic or bi-quadratic, deletes old elements, replacing
5274         them with quadratic with the same id.
5275
5276         Parameters:
5277                 theForce3d: method of new node creation:
5278
5279                   * False - the medium node lies at the geometrical entity from which the mesh element is built
5280                   * True - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
5281                 theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
5282                 theToBiQuad: If True, converts the mesh to bi-quadratic
5283
5284         Returns:
5285             :class:`SMESH.ComputeError` which can hold a warning
5286
5287         Warning:
5288             If *theSubMesh* is provided, the mesh can become non-conformal
5289
5290         Note:
5291                 This operation can create gaps in numeration of nodes or elements.
5292                 Call :meth:`RenumberElements` to remove the gaps.
5293         """
5294
5295         if isinstance( theSubMesh, Mesh ):
5296             theSubMesh = theSubMesh.mesh
5297         if theToBiQuad:
5298             self.editor.ConvertToBiQuadratic(theForce3d,theSubMesh)
5299         else:
5300             if theSubMesh:
5301                 self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
5302             else:
5303                 self.editor.ConvertToQuadratic(theForce3d)
5304         error = self.editor.GetLastError()
5305         if error and error.comment:
5306             print(error.comment)
5307         return error
5308
5309     def ConvertFromQuadratic(self, theSubMesh=None):
5310         """
5311         Convert the mesh from quadratic to ordinary,
5312         deletes old quadratic elements,
5313         replacing them with ordinary mesh elements with the same id.
5314
5315         Parameters:
5316             theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
5317
5318         Warning:
5319             If *theSubMesh* is provided, the mesh can become non-conformal
5320
5321         Note:
5322                 This operation can create gaps in numeration of nodes or elements.
5323                 Call :meth:`RenumberElements` to remove the gaps.
5324         """
5325
5326         if theSubMesh:
5327             self.editor.ConvertFromQuadraticObject(theSubMesh)
5328         else:
5329             return self.editor.ConvertFromQuadratic()
5330
5331     def Make2DMeshFrom3D(self):
5332         """
5333         Create 2D mesh as skin on boundary faces of a 3D mesh
5334
5335         Returns:
5336             True if operation has been completed successfully, False otherwise
5337         """
5338
5339         return self.editor.Make2DMeshFrom3D()
5340
5341     def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
5342                          toCopyElements=False, toCopyExistingBondary=False):
5343         """
5344         Create missing boundary elements
5345
5346         Parameters:
5347                 elements: elements whose boundary is to be checked:
5348                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of elements.
5349                         If *elements* is mesh, it must be the mesh whose MakeBoundaryMesh() is called
5350                 dimension: defines type of boundary elements to create, either of
5351                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }.
5352                         SMESH.BND_1DFROM3D create mesh edges on all borders of free facets of 3D cells
5353                 groupName: a name of group to store created boundary elements in,
5354                         "" means not to create the group
5355                 meshName: a name of new mesh to store created boundary elements in,
5356                         "" means not to create the new mesh
5357                 toCopyElements: if True, the checked elements will be copied into
5358                         the new mesh else only boundary elements will be copied into the new mesh
5359                 toCopyExistingBondary: if True, not only new but also pre-existing
5360                         boundary elements will be copied into the new mesh
5361
5362         Returns:
5363             tuple (:class:`Mesh`, :class:`group <SMESH.SMESH_Group>`) where boundary elements were added to
5364         """
5365
5366         unRegister = genObjUnRegister()
5367         if isinstance( elements, Mesh ):
5368             elements = elements.GetMesh()
5369         if ( isinstance( elements, list )):
5370             elemType = SMESH.ALL
5371             if elements: elemType = self.GetElementType( elements[0], iselem=True)
5372             elements = self.editor.MakeIDSource(elements, elemType)
5373             unRegister.set( elements )
5374         mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName,
5375                                                    toCopyElements,toCopyExistingBondary)
5376         if mesh: mesh = self.smeshpyD.Mesh(mesh)
5377         return mesh, group
5378
5379     def MakeBoundaryElements(self, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
5380                              toCopyAll=False, groups=[]):
5381         """
5382         Create missing boundary elements around either the whole mesh or
5383         groups of elements
5384
5385         Parameters:
5386                 dimension: defines type of boundary elements to create, either of
5387                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
5388                 groupName: a name of group to store all boundary elements in,
5389                         "" means not to create the group
5390                 meshName: a name of a new mesh, which is a copy of the initial
5391                         mesh + created boundary elements; "" means not to create the new mesh
5392                 toCopyAll: if True, the whole initial mesh will be copied into
5393                         the new mesh else only boundary elements will be copied into the new mesh
5394                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` of elements to make boundary around
5395
5396         Returns:
5397                 tuple( long, mesh, group )
5398                        - long - number of added boundary elements
5399                        - mesh - the :class:`Mesh` where elements were added to
5400                        - group - the :class:`group <SMESH.SMESH_Group>` of boundary elements or None
5401         """
5402
5403         nb, mesh, group = self.editor.MakeBoundaryElements(dimension,groupName,meshName,
5404                                                            toCopyAll,groups)
5405         if mesh: mesh = self.smeshpyD.Mesh(mesh)
5406         return nb, mesh, group
5407
5408     def RenumberNodes(self):
5409         """
5410         Renumber mesh nodes to remove unused node IDs
5411         """
5412         self.editor.RenumberNodes()
5413
5414     def RenumberElements(self):
5415         """
5416         Renumber mesh elements to remove unused element IDs
5417         """
5418         self.editor.RenumberElements()
5419
5420     def _getIdSourceList(self, arg, idType, unRegister):
5421         """
5422         Private method converting *arg* into a list of :class:`SMESH.SMESH_IDSource`
5423         """
5424         if arg and isinstance( arg, list ):
5425             if isinstance( arg[0], int ):
5426                 arg = self.GetIDSource( arg, idType )
5427                 unRegister.set( arg )
5428             elif isinstance( arg[0], Mesh ):
5429                 arg[0] = arg[0].GetMesh()
5430         elif isinstance( arg, Mesh ):
5431             arg = arg.GetMesh()
5432         if arg and isinstance( arg, SMESH._objref_SMESH_IDSource ):
5433             arg = [arg]
5434         return arg
5435
5436     def RotationSweepObjects(self, nodes, edges, faces, Axis, AngleInRadians, NbOfSteps, Tolerance,
5437                              MakeGroups=False, TotalAngle=False):
5438         """
5439         Generate new elements by rotation of the given elements and nodes around the axis
5440
5441         Parameters:
5442                 nodes: nodes to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5443                 edges: edges to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5444                 faces: faces to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5445                 Axis: the axis of rotation: :class:`SMESH.AxisStruct`, line (geom object) or [x,y,z,dx,dy,dz]
5446                 AngleInRadians: the angle of Rotation (in radians) or a name of variable
5447                         which defines angle in degrees
5448                 NbOfSteps: the number of steps
5449                 Tolerance: tolerance
5450                 MakeGroups: forces the generation of new groups from existing ones
5451                 TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5452                         of all steps, else - size of each step
5453
5454         Returns:
5455             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5456         """
5457
5458         unRegister = genObjUnRegister()
5459         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5460         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5461         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5462
5463         if isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object):
5464             Axis = self.smeshpyD.GetAxisStruct( Axis )
5465         if isinstance( Axis, list ):
5466             Axis = SMESH.AxisStruct( *Axis )
5467
5468         AngleInRadians,AngleParameters,hasVars = ParseAngles(AngleInRadians)
5469         NbOfSteps,Tolerance,Parameters,hasVars = ParseParameters(NbOfSteps,Tolerance)
5470         Parameters = Axis.parameters + var_separator + AngleParameters + var_separator + Parameters
5471         self.mesh.SetParameters(Parameters)
5472         if TotalAngle and NbOfSteps:
5473             AngleInRadians /= NbOfSteps
5474         return self.editor.RotationSweepObjects( nodes, edges, faces,
5475                                                  Axis, AngleInRadians,
5476                                                  NbOfSteps, Tolerance, MakeGroups)
5477
5478     def RotationSweep(self, IDsOfElements, Axis, AngleInRadians, NbOfSteps, Tolerance,
5479                       MakeGroups=False, TotalAngle=False):
5480         """
5481         Generate new elements by rotation of the elements around the axis
5482
5483         Parameters:
5484             IDsOfElements: the list of ids of elements to sweep
5485             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5486             AngleInRadians: the angle of Rotation (in radians) or a name of variable which defines angle in degrees
5487             NbOfSteps: the number of steps
5488             Tolerance: tolerance
5489             MakeGroups: forces the generation of new groups from existing ones
5490             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5491                 of all steps, else - size of each step
5492
5493         Returns:
5494             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5495         """
5496
5497         return self.RotationSweepObjects([], IDsOfElements, IDsOfElements, Axis,
5498                                          AngleInRadians, NbOfSteps, Tolerance,
5499                                          MakeGroups, TotalAngle)
5500
5501     def RotationSweepObject(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5502                             MakeGroups=False, TotalAngle=False):
5503         """
5504         Generate new elements by rotation of the elements of object around the axis
5505         theObject object which elements should be sweeped.
5506         It can be a mesh, a sub mesh or a group.
5507
5508         Parameters:
5509             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5510             AngleInRadians: the angle of Rotation
5511             NbOfSteps: number of steps
5512             Tolerance: tolerance
5513             MakeGroups: forces the generation of new groups from existing ones
5514             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5515                 of all steps, else - size of each step
5516
5517         Returns:
5518             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5519         """
5520
5521         return self.RotationSweepObjects( [], theObject, theObject, Axis,
5522                                           AngleInRadians, NbOfSteps, Tolerance,
5523                                           MakeGroups, TotalAngle )
5524
5525     def RotationSweepObject1D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5526                               MakeGroups=False, TotalAngle=False):
5527         """
5528         Generate new elements by rotation of the elements of object around the axis
5529         theObject object which elements should be sweeped.
5530         It can be a mesh, a sub mesh or a group.
5531
5532         Parameters:
5533             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5534             AngleInRadians: the angle of Rotation
5535             NbOfSteps: number of steps
5536             Tolerance: tolerance
5537             MakeGroups: forces the generation of new groups from existing ones
5538             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5539                 of all steps, else - size of each step
5540
5541         Returns:
5542             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, 
5543             empty list otherwise
5544         """
5545
5546         return self.RotationSweepObjects([],theObject,[], Axis,
5547                                          AngleInRadians, NbOfSteps, Tolerance,
5548                                          MakeGroups, TotalAngle)
5549
5550     def RotationSweepObject2D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5551                               MakeGroups=False, TotalAngle=False):
5552         """
5553         Generate new elements by rotation of the elements of object around the axis
5554         theObject object which elements should be sweeped.
5555         It can be a mesh, a sub mesh or a group.
5556
5557         Parameters:
5558             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5559             AngleInRadians: the angle of Rotation
5560             NbOfSteps: number of steps
5561             Tolerance: tolerance
5562             MakeGroups: forces the generation of new groups from existing ones
5563             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5564                 of all steps, else - size of each step
5565
5566         Returns:
5567             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5568         """
5569
5570         return self.RotationSweepObjects([],[],theObject, Axis, AngleInRadians,
5571                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
5572
5573     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
5574                               scaleFactors=[], linearVariation=False, basePoint=[],
5575                               angles=[], anglesVariation=False):
5576         """
5577         Generate new elements by extrusion of the given elements and nodes
5578
5579         Parameters:
5580             nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5581             edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5582             faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5583             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5584                 the direction and value of extrusion for one step (the total extrusion
5585                 length will be NbOfSteps * ||StepVector||)
5586             NbOfSteps: the number of steps
5587             MakeGroups: forces the generation of new groups from existing ones
5588             scaleFactors: optional scale factors to apply during extrusion
5589             linearVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
5590                 else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
5591             basePoint: optional scaling and rotation center; if not provided, a gravity center of
5592                 nodes and elements being extruded is used as the scaling center.
5593                 It can be either
5594
5595                         - a list of tree components of the point or
5596                         - a node ID or
5597                         - a GEOM point
5598             angles: list of angles in radians. Nodes at each extrusion step are rotated 
5599                 around *basePoint*, additionally to previous steps.
5600             anglesVariation: forces the computation of rotation angles as linear
5601                 variation of the given *angles* along path steps
5602         Returns:
5603             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5604
5605         Example: :ref:`tui_extrusion`
5606         """
5607         unRegister = genObjUnRegister()
5608         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5609         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5610         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5611
5612         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5613             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5614         if isinstance( StepVector, list ):
5615             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5616
5617         if isinstance( basePoint, int):
5618             xyz = self.GetNodeXYZ( basePoint )
5619             if not xyz:
5620                 raise RuntimeError("Invalid node ID: %s" % basePoint)
5621             basePoint = xyz
5622         if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ):
5623             basePoint = self.geompyD.PointCoordinates( basePoint )
5624
5625         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
5626         scaleFactors,scaleParameters,hasVars = ParseParameters(scaleFactors)
5627         angles,angleParameters,hasVars = ParseAngles(angles)
5628         Parameters = StepVector.PS.parameters + var_separator + \
5629                      Parameters + var_separator + \
5630                      scaleParameters + var_separator + angleParameters
5631         self.mesh.SetParameters(Parameters)
5632
5633         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
5634                                                   StepVector, NbOfSteps, MakeGroups,
5635                                                   scaleFactors, linearVariation, basePoint,
5636                                                   angles, anglesVariation )
5637
5638
5639     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
5640         """
5641         Generate new elements by extrusion of the elements with given ids
5642
5643         Parameters:
5644             IDsOfElements: the list of ids of elements or nodes for extrusion
5645             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5646                 the direction and value of extrusion for one step (the total extrusion
5647                 length will be NbOfSteps * ||StepVector||)
5648             NbOfSteps: the number of steps
5649             MakeGroups: forces the generation of new groups from existing ones
5650             IsNodes: is True if elements with given ids are nodes
5651
5652         Returns:
5653             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5654
5655         Example: :ref:`tui_extrusion`
5656         """
5657         n,e,f = [],[],[]
5658         if IsNodes: n = IDsOfElements
5659         else      : e,f, = IDsOfElements,IDsOfElements
5660         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5661
5662     def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
5663                           ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
5664         """
5665         Generate new elements by extrusion along the normal to a discretized surface or wire
5666
5667         Parameters:
5668             Elements: elements to extrude - a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`.
5669                 Only faces can be extruded so far. A sub-mesh should be a sub-mesh on geom faces.
5670             StepSize: length of one extrusion step (the total extrusion
5671                 length will be *NbOfSteps* *StepSize*).
5672             NbOfSteps: number of extrusion steps.
5673             ByAverageNormal: if True each node is translated by *StepSize*
5674                 along the average of the normal vectors to the faces sharing the node;
5675                 else each node is translated along the same average normal till
5676                 intersection with the plane got by translation of the face sharing
5677                 the node along its own normal by *StepSize*.
5678             UseInputElemsOnly: to use only *Elements* when computing extrusion direction
5679                 for every node of *Elements*.
5680             MakeGroups: forces generation of new groups from existing ones.
5681             Dim: dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
5682                 is not yet implemented. This parameter is used if *Elements* contains
5683                 both faces and edges, i.e. *Elements* is a Mesh.
5684
5685         Returns:
5686             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
5687             empty list otherwise.
5688         Example: :ref:`tui_extrusion`
5689         """
5690
5691         unRegister = genObjUnRegister()
5692         if isinstance( Elements, Mesh ):
5693             Elements = [ Elements.GetMesh() ]
5694         if isinstance( Elements, list ):
5695             if not Elements:
5696                 raise RuntimeError("Elements empty!")
5697             if isinstance( Elements[0], Mesh ):
5698                 Elements = [ Elements[0].GetMesh() ]
5699             if isinstance( Elements[0], int ):
5700                 Elements = self.GetIDSource( Elements, SMESH.ALL )
5701                 unRegister.set( Elements )
5702         if not isinstance( Elements, list ):
5703             Elements = [ Elements ]
5704         StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
5705         self.mesh.SetParameters(Parameters)
5706         return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
5707                                              ByAverageNormal, UseInputElemsOnly, MakeGroups, Dim)
5708
5709     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
5710         """
5711         Generate new elements by extrusion of the elements or nodes which belong to the object
5712
5713         Parameters:
5714             theObject: the object whose elements or nodes should be processed.
5715                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5716             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5717                 the direction and value of extrusion for one step (the total extrusion
5718                 length will be NbOfSteps * ||StepVector||)
5719             NbOfSteps: the number of steps
5720             MakeGroups: forces the generation of new groups from existing ones
5721             IsNodes: is True if elements to extrude are nodes
5722
5723         Returns:
5724             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5725         Example: :ref:`tui_extrusion`
5726         """
5727
5728         n,e,f = [],[],[]
5729         if IsNodes: n    = theObject
5730         else      : e,f, = theObject,theObject
5731         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5732
5733     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5734         """
5735         Generate new elements by extrusion of edges which belong to the object
5736
5737         Parameters:
5738             theObject: object whose 1D elements should be processed.
5739                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5740             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5741                 the direction and value of extrusion for one step (the total extrusion
5742                 length will be NbOfSteps * ||StepVector||)
5743             NbOfSteps: the number of steps
5744             MakeGroups: to generate new groups from existing ones
5745
5746         Returns:
5747             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5748         Example: :ref:`tui_extrusion`
5749         """
5750
5751         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
5752
5753     def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5754         """
5755         Generate new elements by extrusion of faces which belong to the object
5756
5757         Parameters:
5758             theObject: object whose 2D elements should be processed.
5759                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5760             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5761                 the direction and value of extrusion for one step (the total extrusion
5762                 length will be NbOfSteps * ||StepVector||)
5763             NbOfSteps: the number of steps
5764             MakeGroups: forces the generation of new groups from existing ones
5765
5766         Returns:
5767             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5768         Example: :ref:`tui_extrusion`
5769         """
5770
5771         return self.ExtrusionSweepObjects([],[],theObject, StepVector, NbOfSteps, MakeGroups)
5772
5773     def AdvancedExtrusion(self, IDsOfElements, StepVector, NbOfSteps,
5774                           ExtrFlags, SewTolerance, MakeGroups=False):
5775         """
5776         Generate new elements by extrusion of the elements with given ids
5777
5778         Parameters:
5779             IDsOfElements: is ids of elements
5780             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5781                 the direction and value of extrusion for one step (the total extrusion
5782                 length will be NbOfSteps * ||StepVector||)
5783             NbOfSteps: the number of steps
5784             ExtrFlags: sets flags for extrusion
5785             SewTolerance: uses for comparing locations of nodes if flag
5786                 EXTRUSION_FLAG_SEW is set
5787             MakeGroups: forces the generation of new groups from existing ones
5788
5789         Returns:
5790             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5791         """
5792
5793         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5794             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5795         if isinstance( StepVector, list ):
5796             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5797         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
5798                                              ExtrFlags, SewTolerance, MakeGroups)
5799
5800     def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathObject, PathShape=None,
5801                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
5802                                   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
5803                                   ScaleFactors=[], ScalesVariation=False):
5804         """
5805         Generate new elements by extrusion of the given elements and nodes along the path.
5806         The path of extrusion must be a meshed edge.
5807
5808         Parameters:
5809             Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5810             Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5811             Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5812             PathObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` containing edges along which proceeds the extrusion
5813             PathShape: optional shape (edge or wire) which defines the sub-mesh of the mesh defined by *PathObject* if the mesh contains not only path segments, else it can be None
5814             NodeStart: the first or the last node on the path. Defines the direction of extrusion
5815             HasAngles: not used obsolete
5816             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5817                 around *basePoint*, additionally to previous steps.
5818             LinearVariation: forces the computation of rotation angles as linear
5819                 variation of the given Angles along path steps
5820             HasRefPoint: allows using the reference point
5821             RefPoint: optional scaling and rotation center (mass center of the extruded
5822                 elements by default). The User can specify any point as the Reference Point. 
5823                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5824             MakeGroups: forces the generation of new groups from existing ones
5825             ScaleFactors: optional scale factors to apply during extrusion
5826             ScalesVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
5827                 else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
5828
5829         Returns:
5830             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5831             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5832         Example: :ref:`tui_extrusion_along_path`
5833         """
5834
5835         unRegister = genObjUnRegister()
5836         Nodes = self._getIdSourceList( Nodes, SMESH.NODE, unRegister )
5837         Edges = self._getIdSourceList( Edges, SMESH.EDGE, unRegister )
5838         Faces = self._getIdSourceList( Faces, SMESH.FACE, unRegister )
5839
5840         if isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object):
5841             RefPoint = self.smeshpyD.GetPointStruct(RefPoint)
5842         if isinstance( RefPoint, list ):
5843             if not RefPoint: RefPoint = [0,0,0]
5844             RefPoint = SMESH.PointStruct( *RefPoint )
5845         if isinstance( PathObject, Mesh ):
5846             PathObject = PathObject.GetMesh()
5847         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
5848         ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors)
5849         Parameters = AnglesParameters + var_separator + \
5850                      RefPoint.parameters + var_separator + ScalesParameters 
5851         self.mesh.SetParameters(Parameters)
5852         return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces,
5853                                                      PathObject, PathShape, NodeStart,
5854                                                      HasAngles, Angles, LinearVariation,
5855                                                      HasRefPoint, RefPoint, MakeGroups,
5856                                                      ScaleFactors, ScalesVariation)
5857
5858     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
5859                             HasAngles=False, Angles=[], LinearVariation=False,
5860                             HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
5861                             ElemType=SMESH.FACE):
5862         """
5863         Generate new elements by extrusion of the given elements.
5864         The path of extrusion must be a meshed edge.
5865
5866         Parameters:
5867             Base: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`, or list of ids of elements for extrusion
5868             Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
5869             NodeStart: the start node from Path. Defines the direction of extrusion
5870             HasAngles: not used obsolete
5871             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5872                 around *basePoint*, additionally to previous steps.
5873             LinearVariation: forces the computation of rotation angles as linear
5874                 variation of the given Angles along path steps
5875             HasRefPoint: allows using the reference point
5876             RefPoint: the reference point around which the elements are rotated (the mass
5877                 center of the elements by default).
5878                 The User can specify any point as the Reference Point.
5879                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5880             MakeGroups: forces the generation of new groups from existing ones
5881             ElemType: type of elements for extrusion (if param Base is a mesh)
5882
5883         Returns:
5884             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5885             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5886             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5887             otherwise
5888         Example: :ref:`tui_extrusion_along_path`
5889         """
5890
5891         n,e,f = [],[],[]
5892         if ElemType == SMESH.NODE: n = Base
5893         if ElemType == SMESH.EDGE: e = Base
5894         if ElemType == SMESH.FACE: f = Base
5895         gr,er = self.ExtrusionAlongPathObjects(n,e,f, Path, None, NodeStart,
5896                                                HasAngles, Angles, LinearVariation,
5897                                                HasRefPoint, RefPoint, MakeGroups)
5898         if MakeGroups: return gr,er
5899         return er
5900
5901     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
5902                            HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5903                            MakeGroups=False, LinearVariation=False):
5904         """
5905         Generate new elements by extrusion of the given elements.
5906         The path of extrusion must be a meshed edge.
5907
5908         Parameters:
5909             IDsOfElements: ids of elements
5910             PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
5911             PathShape: shape (edge) defines the sub-mesh for the path
5912             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5913             HasAngles: not used obsolete
5914             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5915                 around *basePoint*, additionally to previous steps.
5916             HasRefPoint: allows using the reference point
5917             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5918                 The User can specify any point as the Reference Point.
5919                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5920             MakeGroups: forces the generation of new groups from existing ones
5921             LinearVariation: forces the computation of rotation angles as linear
5922                 variation of the given Angles along path steps
5923
5924         Returns:
5925             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5926             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5927             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5928         Example: :ref:`tui_extrusion_along_path`
5929         """
5930
5931         if not IDsOfElements:
5932             IDsOfElements = [ self.GetMesh() ]
5933         n,e,f = [],IDsOfElements,IDsOfElements
5934         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape,
5935                                                NodeStart, HasAngles, Angles,
5936                                                LinearVariation,
5937                                                HasRefPoint, RefPoint, MakeGroups)
5938         if MakeGroups: return gr,er
5939         return er
5940
5941     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
5942                                  HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5943                                  MakeGroups=False, LinearVariation=False):
5944         """
5945         Generate new elements by extrusion of the elements which belong to the object.
5946         The path of extrusion must be a meshed edge.
5947
5948         Parameters:
5949             theObject: the object whose elements should be processed.
5950                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5951             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5952             PathShape: shape (edge) defines the sub-mesh for the path
5953             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5954             HasAngles: not used obsolete
5955             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5956                 around *basePoint*, additionally to previous steps.
5957             HasRefPoint: allows using the reference point
5958             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5959                 The User can specify any point as the Reference Point.
5960                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5961             MakeGroups: forces the generation of new groups from existing ones
5962             LinearVariation: forces the computation of rotation angles as linear
5963                 variation of the given Angles along path steps
5964
5965         Returns:
5966             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5967             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5968             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5969         Example: :ref:`tui_extrusion_along_path`
5970         """
5971
5972         n,e,f = [],theObject,theObject
5973         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5974                                                HasAngles, Angles, LinearVariation,
5975                                                HasRefPoint, RefPoint, MakeGroups)
5976         if MakeGroups: return gr,er
5977         return er
5978
5979     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
5980                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5981                                    MakeGroups=False, LinearVariation=False):
5982         """
5983         Generate new elements by extrusion of mesh segments which belong to the object.
5984         The path of extrusion must be a meshed edge.
5985
5986         Parameters:
5987             theObject: the object whose 1D elements should be processed.
5988                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5989             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5990             PathShape: shape (edge) defines the sub-mesh for the path
5991             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5992             HasAngles: not used obsolete
5993             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5994                 around *basePoint*, additionally to previous steps.
5995             HasRefPoint: allows using the reference point
5996             RefPoint:  the reference point around which the shape is rotated (the mass center of the shape by default).
5997                 The User can specify any point as the Reference Point.
5998                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5999             MakeGroups: forces the generation of new groups from existing ones
6000             LinearVariation: forces the computation of rotation angles as linear
6001                 variation of the given Angles along path steps
6002
6003         Returns:
6004             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
6005             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
6006             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
6007         Example: :ref:`tui_extrusion_along_path`
6008         """
6009
6010         n,e,f = [],theObject,[]
6011         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
6012                                                HasAngles, Angles, LinearVariation,
6013                                                HasRefPoint, RefPoint, MakeGroups)
6014         if MakeGroups: return gr,er
6015         return er
6016
6017     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
6018                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
6019                                    MakeGroups=False, LinearVariation=False):
6020         """
6021         Generate new elements by extrusion of faces which belong to the object.
6022         The path of extrusion must be a meshed edge.
6023
6024         Parameters:
6025             theObject: the object whose 2D elements should be processed.
6026                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
6027             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
6028             PathShape: shape (edge) defines the sub-mesh for the path
6029             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
6030             HasAngles: not used obsolete
6031             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
6032                 around *basePoint*, additionally to previous steps.
6033             HasRefPoint: allows using the reference point
6034             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
6035                 The User can specify any point as the Reference Point.
6036                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
6037             MakeGroups: forces the generation of new groups from existing ones
6038             LinearVariation: forces the computation of rotation angles as linear
6039                 variation of the given Angles along path steps
6040
6041         Returns:
6042             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
6043             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
6044             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
6045         Example: :ref:`tui_extrusion_along_path`
6046         """
6047
6048         n,e,f = [],[],theObject
6049         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
6050                                                HasAngles, Angles, LinearVariation,
6051                                                HasRefPoint, RefPoint, MakeGroups)
6052         if MakeGroups: return gr,er
6053         return er
6054
6055     def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
6056         """
6057         Create a symmetrical copy of mesh elements
6058
6059         Parameters:
6060             IDsOfElements: list of elements ids
6061             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6062             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6063                 If the *Mirror* is a geom object this parameter is unnecessary
6064             Copy: allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
6065             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6066
6067         Returns:
6068             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6069         """
6070
6071         if IDsOfElements == []:
6072             IDsOfElements = self.GetElementsId()
6073         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6074             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6075             theMirrorType = Mirror._mirrorType
6076         else:
6077             self.mesh.SetParameters(Mirror.parameters)
6078         if Copy and MakeGroups:
6079             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
6080         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
6081         return []
6082
6083     def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
6084         """
6085         Create a new mesh by a symmetrical copy of mesh elements
6086
6087         Parameters:
6088             IDsOfElements: the list of elements ids
6089             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6090             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6091                 If the *Mirror* is a geom object this parameter is unnecessary
6092             MakeGroups: to generate new groups from existing ones
6093             NewMeshName: a name of the new mesh to create
6094
6095         Returns:
6096             instance of class :class:`Mesh`
6097         """
6098
6099         if IDsOfElements == []:
6100             IDsOfElements = self.GetElementsId()
6101         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6102             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6103             theMirrorType = Mirror._mirrorType
6104         else:
6105             self.mesh.SetParameters(Mirror.parameters)
6106         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
6107                                           MakeGroups, NewMeshName)
6108         return Mesh(self.smeshpyD,self.geompyD,mesh)
6109
6110     def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
6111         """
6112         Create a symmetrical copy of the object
6113
6114         Parameters:
6115             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6116             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6117             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6118                 If the *Mirror* is a geom object this parameter is unnecessary
6119             Copy: allows copying the element (Copy==True) or replacing it with its mirror (Copy==False)
6120             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6121
6122         Returns:
6123             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6124         """
6125
6126         if ( isinstance( theObject, Mesh )):
6127             theObject = theObject.GetMesh()
6128         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6129             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6130             theMirrorType = Mirror._mirrorType
6131         else:
6132             self.mesh.SetParameters(Mirror.parameters)
6133         if Copy and MakeGroups:
6134             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
6135         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
6136         return []
6137
6138     def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
6139         """
6140         Create a new mesh by a symmetrical copy of the object
6141
6142         Parameters:
6143             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6144             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6145             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6146                 If the *Mirror* is a geom object this parameter is unnecessary
6147             MakeGroups: forces the generation of new groups from existing ones
6148             NewMeshName: the name of the new mesh to create
6149
6150         Returns:
6151             instance of class :class:`Mesh`
6152         """
6153
6154         if ( isinstance( theObject, Mesh )):
6155             theObject = theObject.GetMesh()
6156         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6157             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6158             theMirrorType = Mirror._mirrorType
6159         else:
6160             self.mesh.SetParameters(Mirror.parameters)
6161         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
6162                                                 MakeGroups, NewMeshName)
6163         return Mesh( self.smeshpyD,self.geompyD,mesh )
6164
6165     def Translate(self, IDsOfElements, Vector, Copy, MakeGroups=False):
6166         """
6167         Translate the elements
6168
6169         Parameters:
6170             IDsOfElements: list of elements ids
6171             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
6172             Copy: allows copying the translated elements
6173             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6174
6175         Returns:
6176             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6177         """
6178
6179         if IDsOfElements == []:
6180             IDsOfElements = self.GetElementsId()
6181         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6182             Vector = self.smeshpyD.GetDirStruct(Vector)
6183         if isinstance( Vector, list ):
6184             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6185         self.mesh.SetParameters(Vector.PS.parameters)
6186         if Copy and MakeGroups:
6187             return self.editor.TranslateMakeGroups(IDsOfElements, Vector)
6188         self.editor.Translate(IDsOfElements, Vector, Copy)
6189         return []
6190
6191     def TranslateMakeMesh(self, IDsOfElements, Vector, MakeGroups=False, NewMeshName=""):
6192         """
6193         Create a new mesh of translated elements
6194
6195         Parameters:
6196             IDsOfElements: list of elements ids
6197             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
6198             MakeGroups: forces the generation of new groups from existing ones
6199             NewMeshName: the name of the newly created mesh
6200
6201         Returns:
6202             instance of class :class:`Mesh`
6203         """
6204
6205         if IDsOfElements == []:
6206             IDsOfElements = self.GetElementsId()
6207         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6208             Vector = self.smeshpyD.GetDirStruct(Vector)
6209         if isinstance( Vector, list ):
6210             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6211         self.mesh.SetParameters(Vector.PS.parameters)
6212         mesh = self.editor.TranslateMakeMesh(IDsOfElements, Vector, MakeGroups, NewMeshName)
6213         return Mesh ( self.smeshpyD, self.geompyD, mesh )
6214
6215     def TranslateObject(self, theObject, Vector, Copy, MakeGroups=False):
6216         """
6217         Translate the object
6218
6219         Parameters:
6220             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6221             Vector: direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
6222             Copy: allows copying the translated elements
6223             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6224
6225         Returns:
6226             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6227         """
6228
6229         if ( isinstance( theObject, Mesh )):
6230             theObject = theObject.GetMesh()
6231         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6232             Vector = self.smeshpyD.GetDirStruct(Vector)
6233         if isinstance( Vector, list ):
6234             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6235         self.mesh.SetParameters(Vector.PS.parameters)
6236         if Copy and MakeGroups:
6237             return self.editor.TranslateObjectMakeGroups(theObject, Vector)
6238         self.editor.TranslateObject(theObject, Vector, Copy)
6239         return []
6240
6241     def TranslateObjectMakeMesh(self, theObject, Vector, MakeGroups=False, NewMeshName=""):
6242         """
6243         Create a new mesh from the translated object
6244
6245         Parameters:
6246             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6247             Vector: the direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
6248             MakeGroups: forces the generation of new groups from existing ones
6249             NewMeshName: the name of the newly created mesh
6250
6251         Returns:
6252             instance of class :class:`Mesh`
6253         """
6254
6255         if isinstance( theObject, Mesh ):
6256             theObject = theObject.GetMesh()
6257         if isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object ):
6258             Vector = self.smeshpyD.GetDirStruct(Vector)
6259         if isinstance( Vector, list ):
6260             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6261         self.mesh.SetParameters(Vector.PS.parameters)
6262         mesh = self.editor.TranslateObjectMakeMesh(theObject, Vector, MakeGroups, NewMeshName)
6263         return Mesh( self.smeshpyD, self.geompyD, mesh )
6264
6265
6266
6267     def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False):
6268         """
6269         Scale the object
6270
6271         Parameters:
6272             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6273             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
6274             theScaleFact: list of 1-3 scale factors for axises
6275             Copy: allows copying the translated elements
6276             MakeGroups: forces the generation of new groups from existing
6277                 ones (if Copy)
6278
6279         Returns:
6280             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
6281             empty list otherwise
6282         """
6283         unRegister = genObjUnRegister()
6284         if ( isinstance( theObject, Mesh )):
6285             theObject = theObject.GetMesh()
6286         if ( isinstance( theObject, list )):
6287             theObject = self.GetIDSource(theObject, SMESH.ALL)
6288             unRegister.set( theObject )
6289         if ( isinstance( thePoint, list )):
6290             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
6291         if ( isinstance( theScaleFact, float )):
6292             theScaleFact = [theScaleFact]
6293         if ( isinstance( theScaleFact, int )):
6294             theScaleFact = [ float(theScaleFact)]
6295
6296         self.mesh.SetParameters(thePoint.parameters)
6297
6298         if Copy and MakeGroups:
6299             return self.editor.ScaleMakeGroups(theObject, thePoint, theScaleFact)
6300         self.editor.Scale(theObject, thePoint, theScaleFact, Copy)
6301         return []
6302
6303     def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""):
6304         """
6305         Create a new mesh from the translated object
6306
6307         Parameters:
6308             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6309             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
6310             theScaleFact: list of 1-3 scale factors for axises
6311             MakeGroups: forces the generation of new groups from existing ones
6312             NewMeshName: the name of the newly created mesh
6313
6314         Returns:
6315             instance of class :class:`Mesh`
6316         """
6317         unRegister = genObjUnRegister()
6318         if (isinstance(theObject, Mesh)):
6319             theObject = theObject.GetMesh()
6320         if ( isinstance( theObject, list )):
6321             theObject = self.GetIDSource(theObject,SMESH.ALL)
6322             unRegister.set( theObject )
6323         if ( isinstance( thePoint, list )):
6324             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
6325         if ( isinstance( theScaleFact, float )):
6326             theScaleFact = [theScaleFact]
6327         if ( isinstance( theScaleFact, int )):
6328             theScaleFact = [ float(theScaleFact)]
6329
6330         self.mesh.SetParameters(thePoint.parameters)
6331         mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact,
6332                                          MakeGroups, NewMeshName)
6333         return Mesh( self.smeshpyD, self.geompyD, mesh )
6334
6335
6336
6337     def Rotate (self, IDsOfElements, Axis, AngleInRadians, Copy, MakeGroups=False):
6338         """
6339         Rotate the elements
6340
6341         Parameters:
6342             IDsOfElements: list of elements ids
6343             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6344             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6345             Copy: allows copying the rotated elements
6346             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6347
6348         Returns:
6349             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6350         """
6351
6352
6353         if IDsOfElements == []:
6354             IDsOfElements = self.GetElementsId()
6355         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6356             Axis = self.smeshpyD.GetAxisStruct(Axis)
6357         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6358         Parameters = Axis.parameters + var_separator + Parameters
6359         self.mesh.SetParameters(Parameters)
6360         if Copy and MakeGroups:
6361             return self.editor.RotateMakeGroups(IDsOfElements, Axis, AngleInRadians)
6362         self.editor.Rotate(IDsOfElements, Axis, AngleInRadians, Copy)
6363         return []
6364
6365     def RotateMakeMesh (self, IDsOfElements, Axis, AngleInRadians, MakeGroups=0, NewMeshName=""):
6366         """
6367         Create a new mesh of rotated elements
6368
6369         Parameters:
6370             IDsOfElements: list of element ids
6371             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6372             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6373             MakeGroups: forces the generation of new groups from existing ones
6374             NewMeshName: the name of the newly created mesh
6375
6376         Returns:
6377             instance of class :class:`Mesh`
6378         """
6379
6380         if IDsOfElements == []:
6381             IDsOfElements = self.GetElementsId()
6382         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6383             Axis = self.smeshpyD.GetAxisStruct(Axis)
6384         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6385         Parameters = Axis.parameters + var_separator + Parameters
6386         self.mesh.SetParameters(Parameters)
6387         mesh = self.editor.RotateMakeMesh(IDsOfElements, Axis, AngleInRadians,
6388                                           MakeGroups, NewMeshName)
6389         return Mesh( self.smeshpyD, self.geompyD, mesh )
6390
6391     def RotateObject (self, theObject, Axis, AngleInRadians, Copy, MakeGroups=False):
6392         """
6393         Rotate the object
6394
6395         Parameters:
6396             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6397             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6398             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6399             Copy: allows copying the rotated elements
6400             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6401
6402         Returns:
6403             list of created :class:`groups <SMESH.SMESH_GroupBase>` if MakeGroups==True, empty list otherwise
6404         """
6405
6406         if (isinstance(theObject, Mesh)):
6407             theObject = theObject.GetMesh()
6408         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6409             Axis = self.smeshpyD.GetAxisStruct(Axis)
6410         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6411         Parameters = Axis.parameters + ":" + Parameters
6412         self.mesh.SetParameters(Parameters)
6413         if Copy and MakeGroups:
6414             return self.editor.RotateObjectMakeGroups(theObject, Axis, AngleInRadians)
6415         self.editor.RotateObject(theObject, Axis, AngleInRadians, Copy)
6416         return []
6417
6418     def RotateObjectMakeMesh(self, theObject, Axis, AngleInRadians, MakeGroups=0,NewMeshName=""):
6419         """
6420         Create a new mesh from the rotated object
6421
6422         Parameters:
6423             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6424             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6425             AngleInRadians: the angle of rotation (in radians)  or a name of variable which defines angle in degrees
6426             MakeGroups: forces the generation of new groups from existing ones
6427             NewMeshName: the name of the newly created mesh
6428
6429         Returns:
6430             instance of class :class:`Mesh`
6431         """
6432
6433         if (isinstance( theObject, Mesh )):
6434             theObject = theObject.GetMesh()
6435         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6436             Axis = self.smeshpyD.GetAxisStruct(Axis)
6437         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6438         Parameters = Axis.parameters + ":" + Parameters
6439         mesh = self.editor.RotateObjectMakeMesh(theObject, Axis, AngleInRadians,
6440                                                        MakeGroups, NewMeshName)
6441         self.mesh.SetParameters(Parameters)
6442         return Mesh( self.smeshpyD, self.geompyD, mesh )
6443
6444     def Offset(self, theObject, Value, MakeGroups=False, CopyElements=False, NewMeshName=''):
6445         """
6446         Create an offset mesh from the given 2D object
6447
6448         Parameters:
6449             theObject (SMESH.SMESH_IDSource): the source object (mesh, sub-mesh, group or filter)
6450             theValue (float): signed offset size
6451             MakeGroups (boolean): forces the generation of new groups from existing ones
6452             CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, 
6453                           False means to remove original elements.
6454             NewMeshName (string): the name of a mesh to create. If empty, offset elements are added to this mesh
6455
6456         Returns:
6457             A tuple (:class:`Mesh`, list of :class:`groups <SMESH.SMESH_Group>`)
6458         """
6459
6460         if isinstance( theObject, Mesh ):
6461             theObject = theObject.GetMesh()
6462         theValue,Parameters,hasVars = ParseParameters(Value)
6463         mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName)
6464         self.mesh.SetParameters(Parameters)
6465         if mesh_groups[0]:
6466             return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
6467         return mesh_groups
6468
6469     def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
6470         """
6471         Find groups of adjacent nodes within Tolerance.
6472
6473         Parameters:
6474             Tolerance (float): the value of tolerance
6475             SeparateCornerAndMediumNodes (boolean): if *True*, in quadratic mesh puts
6476                 corner and medium nodes in separate groups thus preventing
6477                 their further merge.
6478
6479         Returns:
6480             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6481         """
6482
6483         return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
6484
6485     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance,
6486                                    exceptNodes=[], SeparateCornerAndMediumNodes=False):
6487         """
6488         Find groups of adjacent nodes within Tolerance.
6489
6490         Parameters:
6491             Tolerance: the value of tolerance
6492             SubMeshOrGroup: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or of node IDs
6493             exceptNodes: list of either SubMeshes, Groups or node IDs to exclude from search
6494             SeparateCornerAndMediumNodes: if *True*, in quadratic mesh puts
6495                 corner and medium nodes in separate groups thus preventing
6496                 their further merge.
6497
6498         Returns:
6499             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6500         """
6501
6502         unRegister = genObjUnRegister()
6503         if not isinstance( SubMeshOrGroup, list ):
6504             SubMeshOrGroup = [ SubMeshOrGroup ]
6505         for i,obj in enumerate( SubMeshOrGroup ):
6506             if isinstance( obj, Mesh ):
6507                 SubMeshOrGroup = [ obj.GetMesh() ]
6508                 break
6509             if isinstance( obj, int ):
6510                 SubMeshOrGroup = [ self.GetIDSource( SubMeshOrGroup, SMESH.NODE )]
6511                 unRegister.set( SubMeshOrGroup )
6512                 break
6513
6514         if not isinstance( exceptNodes, list ):
6515             exceptNodes = [ exceptNodes ]
6516         if exceptNodes and isinstance( exceptNodes[0], int ):
6517             exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
6518             unRegister.set( exceptNodes )
6519
6520         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
6521                                                         exceptNodes, SeparateCornerAndMediumNodes)
6522
6523     def MergeNodes (self, GroupsOfNodes, NodesToKeep=[], AvoidMakingHoles=False):
6524         """
6525         Merge nodes
6526
6527         Parameters:
6528             GroupsOfNodes: a list of groups of nodes IDs for merging.
6529                 E.g. [[1,12,13],[25,4]] means that nodes 12, 13 and 4 will be removed and replaced
6530                 in all elements and mesh groups by nodes 1 and 25 correspondingly
6531             NodesToKeep: nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
6532                 If *NodesToKeep* does not include a node to keep for some group to merge,
6533                 then the first node in the group is kept.
6534             AvoidMakingHoles: prevent merging nodes which cause removal of elements becoming
6535                 invalid
6536
6537         Note:
6538                 This operation can create gaps in numeration of nodes or elements.
6539                 Call :meth:`RenumberElements` to remove the gaps.
6540         """
6541         self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles )
6542
6543     def FindEqualElements (self, MeshOrSubMeshOrGroup=None, exceptElements=[]):
6544         """
6545         Find the elements built on the same nodes.
6546
6547         Parameters:
6548             MeshOrSubMeshOrGroup: :class:`mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or element IDs to check for equal elements
6549             exceptElements: list of either SubMeshes, Groups or elements IDs to exclude from search
6550
6551
6552         Returns:
6553             the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
6554         """
6555
6556         unRegister = genObjUnRegister()
6557         if MeshOrSubMeshOrGroup is None:
6558             MeshOrSubMeshOrGroup = [ self.mesh ]
6559         elif isinstance( MeshOrSubMeshOrGroup, Mesh ):
6560             MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup.GetMesh() ]
6561         elif not isinstance( MeshOrSubMeshOrGroup, list ):
6562             MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup ]
6563         if isinstance( MeshOrSubMeshOrGroup[0], int ):
6564             MeshOrSubMeshOrGroup = [ self.GetIDSource( MeshOrSubMeshOrGroup, SMESH.ALL )]
6565             unRegister.set( MeshOrSubMeshOrGroup )
6566         for item in MeshOrSubMeshOrGroup:
6567             if isinstance( item, Mesh ):
6568                 MeshOrSubMeshOrGroup = [ item.GetMesh() ]
6569
6570         if not isinstance( exceptElements, list ):
6571             exceptElements = [ exceptElements ]
6572         if exceptElements and isinstance( exceptElements[0], int ):
6573             exceptElements = [ self.GetIDSource( exceptElements, SMESH.ALL )]
6574             unRegister.set( exceptElements )
6575
6576         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup, exceptElements )
6577
6578     def MergeElements(self, GroupsOfElementsID, ElementsToKeep=[]):
6579         """
6580         Merge elements in each given group.
6581
6582         Parameters:
6583             GroupsOfElementsID: a list of groups (lists) of elements IDs for merging
6584                 (e.g. [[1,12,13],[25,4]] means that elements 12, 13 and 4 will be removed and
6585                 replaced in all mesh groups by elements 1 and 25)
6586             ElementsToKeep: elements to keep in the mesh: a list of groups, sub-meshes or node IDs.
6587                 If *ElementsToKeep* does not include an element to keep for some group to merge,
6588                 then the first element in the group is kept.
6589
6590         Note:
6591                 This operation can create gaps in numeration of elements.
6592                 Call :meth:`RenumberElements` to remove the gaps.
6593         """
6594
6595         unRegister = genObjUnRegister()
6596         if ElementsToKeep:
6597             if not isinstance( ElementsToKeep, list ):
6598                 ElementsToKeep = [ ElementsToKeep ]
6599             if isinstance( ElementsToKeep[0], int ):
6600                 ElementsToKeep = [ self.GetIDSource( ElementsToKeep, SMESH.ALL )]
6601                 unRegister.set( ElementsToKeep )
6602
6603         self.editor.MergeElements( GroupsOfElementsID, ElementsToKeep )
6604
6605     def MergeEqualElements(self):
6606         """
6607         Leave one element and remove all other elements built on the same nodes.
6608
6609         Note:
6610                 This operation can create gaps in numeration of elements.
6611                 Call :meth:`RenumberElements` to remove the gaps.
6612         """
6613
6614         self.editor.MergeEqualElements()
6615
6616     def FindFreeBorders(self, ClosedOnly=True):
6617         """
6618         Returns all or only closed free borders
6619
6620         Returns:
6621             list of SMESH.FreeBorder's
6622         """
6623
6624         return self.editor.FindFreeBorders( ClosedOnly )
6625
6626     def FillHole(self, holeNodes, groupName=""):
6627         """
6628         Fill with 2D elements a hole defined by a SMESH.FreeBorder.
6629
6630         Parameters:
6631             holeNodes: either a SMESH.FreeBorder or a list on node IDs. These nodes
6632                 must describe all sequential nodes of the hole border. The first and the last
6633                 nodes must be the same. Use :meth:`FindFreeBorders` to get nodes of holes.
6634             groupName (string): name of a group to add new faces
6635         Returns:
6636             a :class:`group <SMESH.SMESH_GroupBase>` containing the new faces; or :code:`None` if `groupName` == ""
6637         """
6638
6639
6640         if holeNodes and isinstance( holeNodes, list ) and isinstance( holeNodes[0], int ):
6641             holeNodes = SMESH.FreeBorder(nodeIDs=holeNodes)
6642         if not isinstance( holeNodes, SMESH.FreeBorder ):
6643             raise TypeError("holeNodes must be either SMESH.FreeBorder or list of integer and not %s" % holeNodes)
6644         return self.editor.FillHole( holeNodes, groupName )
6645
6646     def FindCoincidentFreeBorders (self, tolerance=0.):
6647         """
6648         Return groups of FreeBorder's coincident within the given tolerance.
6649
6650         Parameters:
6651             tolerance: the tolerance. If the tolerance <= 0.0 then one tenth of an average
6652                 size of elements adjacent to free borders being compared is used.
6653
6654         Returns:
6655             SMESH.CoincidentFreeBorders structure
6656         """
6657
6658         return self.editor.FindCoincidentFreeBorders( tolerance )
6659
6660     def SewCoincidentFreeBorders (self, freeBorders, createPolygons=False, createPolyhedra=False):
6661         """
6662         Sew FreeBorder's of each group
6663
6664         Parameters:
6665             freeBorders: either a SMESH.CoincidentFreeBorders structure or a list of lists
6666                 where each enclosed list contains node IDs of a group of coincident free
6667                 borders such that each consequent triple of IDs within a group describes
6668                 a free border in a usual way: n1, n2, nLast - i.e. 1st node, 2nd node and
6669                 last node of a border.
6670                 For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes two
6671                 groups of coincident free borders, each group including two borders.
6672             createPolygons: if :code:`True` faces adjacent to free borders are converted to
6673                 polygons if a node of opposite border falls on a face edge, else such
6674                 faces are split into several ones.
6675             createPolyhedra: if :code:`True` volumes adjacent to free borders are converted to
6676                 polyhedra if a node of opposite border falls on a volume edge, else such
6677                 volumes, if any, remain intact and the mesh becomes non-conformal.
6678
6679         Returns:
6680             a number of successfully sewed groups
6681
6682         Note:
6683                 This operation can create gaps in numeration of nodes or elements.
6684                 Call :meth:`RenumberElements` to remove the gaps.
6685         """
6686
6687         if freeBorders and isinstance( freeBorders, list ):
6688             # construct SMESH.CoincidentFreeBorders
6689             if isinstance( freeBorders[0], int ):
6690                 freeBorders = [freeBorders]
6691             borders = []
6692             coincidentGroups = []
6693             for nodeList in freeBorders:
6694                 if not nodeList or len( nodeList ) % 3:
6695                     raise ValueError("Wrong number of nodes in this group: %s" % nodeList)
6696                 group = []
6697                 while nodeList:
6698                     group.append  ( SMESH.FreeBorderPart( len(borders), 0, 1, 2 ))
6699                     borders.append( SMESH.FreeBorder( nodeList[:3] ))
6700                     nodeList = nodeList[3:]
6701                     pass
6702                 coincidentGroups.append( group )
6703                 pass
6704             freeBorders = SMESH.CoincidentFreeBorders( borders, coincidentGroups )
6705
6706         return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
6707
6708     def SewFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6709                         FirstNodeID2, SecondNodeID2, LastNodeID2,
6710                         CreatePolygons, CreatePolyedrs):
6711         """
6712         Sew free borders
6713
6714         Returns:
6715             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6716
6717         Note:
6718                 This operation can create gaps in numeration of nodes or elements.
6719                 Call :meth:`RenumberElements` to remove the gaps.
6720         """
6721
6722         return self.editor.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6723                                           FirstNodeID2, SecondNodeID2, LastNodeID2,
6724                                           CreatePolygons, CreatePolyedrs)
6725
6726     def SewConformFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6727                                FirstNodeID2, SecondNodeID2):
6728         """
6729         Sew conform free borders
6730
6731         Returns:
6732             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6733
6734         Note:
6735                 This operation can create gaps in numeration of elements.
6736                 Call :meth:`RenumberElements` to remove the gaps.
6737         """
6738
6739         return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6740                                                  FirstNodeID2, SecondNodeID2)
6741
6742     def SewBorderToSide (self, FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6743                          FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs):
6744         """
6745         Sew border to side
6746
6747         Returns:
6748             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6749
6750         Note:
6751                 This operation can create gaps in numeration of elements.
6752                 Call :meth:`RenumberElements` to remove the gaps.
6753         """
6754
6755         return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6756                                            FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs)
6757
6758     def SewSideElements (self, IDsOfSide1Elements, IDsOfSide2Elements,
6759                          NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6760                          NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge):
6761         """
6762         Sew two sides of a mesh. The nodes belonging to Side1 are
6763         merged with the nodes of elements of Side2.
6764         The number of elements in theSide1 and in theSide2 must be
6765         equal and they should have similar nodal connectivity.
6766         The nodes to merge should belong to side borders and
6767         the first node should be linked to the second.
6768
6769         Returns:
6770             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6771
6772         Note:
6773                 This operation can create gaps in numeration of nodes.
6774                 Call :meth:`RenumberElements` to remove the gaps.
6775         """
6776
6777         return self.editor.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
6778                                            NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6779                                            NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
6780
6781     def ChangeElemNodes(self, ide, newIDs):
6782         """
6783         Set new nodes for the given element. Number of nodes should be kept.
6784
6785         Parameters:
6786             ide: the element ID
6787             newIDs: nodes IDs
6788
6789         Returns:
6790             False if the number of nodes does not correspond to the type of element
6791         """
6792
6793         return self.editor.ChangeElemNodes(ide, newIDs)
6794
6795     def GetLastCreatedNodes(self):
6796         """
6797         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some nodes were
6798         created, this method return the list of their IDs.
6799         If new nodes were not created - return empty list
6800
6801         Returns:
6802             the list of integer values (can be empty)
6803         """
6804
6805         return self.editor.GetLastCreatedNodes()
6806
6807     def GetLastCreatedElems(self):
6808         """
6809         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some elements were
6810         created this method return the list of their IDs.
6811         If new elements were not created - return empty list
6812
6813         Returns:
6814             the list of integer values (can be empty)
6815         """
6816
6817         return self.editor.GetLastCreatedElems()
6818
6819     def ClearLastCreated(self):
6820         """
6821         Forget what nodes and elements were created by the last mesh edition operation
6822         """
6823
6824         self.editor.ClearLastCreated()
6825
6826     def DoubleElements(self, theElements, theGroupName=""):
6827         """
6828         Create duplicates of given elements, i.e. create new elements based on the
6829         same nodes as the given ones.
6830
6831         Parameters:
6832             theElements: container of elements to duplicate. It can be a
6833                 :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` 
6834                 or a list of element IDs. If *theElements* is
6835                 a :class:`Mesh`, elements of highest dimension are duplicated
6836             theGroupName: a name of group to contain the generated elements.
6837                 If a group with such a name already exists, the new elements
6838                 are added to the existing group, else a new group is created.
6839                 If *theGroupName* is empty, new elements are not added
6840                 in any group.
6841
6842         Returns:
6843                 a :class:`group <SMESH.SMESH_Group>` where the new elements are added. 
6844                 None if *theGroupName* == "".
6845         """
6846
6847         unRegister = genObjUnRegister()
6848         if isinstance( theElements, Mesh ):
6849             theElements = theElements.mesh
6850         elif isinstance( theElements, list ):
6851             theElements = self.GetIDSource( theElements, SMESH.ALL )
6852             unRegister.set( theElements )
6853         return self.editor.DoubleElements(theElements, theGroupName)
6854
6855     def DoubleNodes(self, theNodes, theModifiedElems):
6856         """
6857         Create a hole in a mesh by doubling the nodes of some particular elements
6858
6859         Parameters:
6860             theNodes: IDs of nodes to be doubled
6861             theModifiedElems: IDs of elements to be updated by the new (doubled)
6862                 nodes. If list of element identifiers is empty then nodes are doubled but
6863                 they not assigned to elements
6864
6865         Returns:
6866             True if operation has been completed successfully, False otherwise
6867         """
6868
6869         return self.editor.DoubleNodes(theNodes, theModifiedElems)
6870
6871     def DoubleNode(self, theNodeId, theModifiedElems):
6872         """
6873         Create a hole in a mesh by doubling the nodes of some particular elements.
6874         This method provided for convenience works as :meth:`DoubleNodes`.
6875
6876         Parameters:
6877             theNodeId: IDs of node to double
6878             theModifiedElems: IDs of elements to update
6879
6880         Returns:
6881             True if operation has been completed successfully, False otherwise
6882         """
6883
6884         return self.editor.DoubleNode(theNodeId, theModifiedElems)
6885
6886     def DoubleNodeGroup(self, theNodes, theModifiedElems, theMakeGroup=False):
6887         """
6888         Create a hole in a mesh by doubling the nodes of some particular elements.
6889         This method provided for convenience works as :meth:`DoubleNodes`.
6890
6891         Parameters:
6892             theNodes: group of nodes to double.
6893             theModifiedElems: group of elements to update.
6894             theMakeGroup: forces the generation of a group containing new nodes.
6895
6896         Returns:
6897             True or a created group if operation has been completed successfully,
6898             False or None otherwise
6899         """
6900
6901         if theMakeGroup:
6902             return self.editor.DoubleNodeGroupNew(theNodes, theModifiedElems)
6903         return self.editor.DoubleNodeGroup(theNodes, theModifiedElems)
6904
6905     def DoubleNodeGroups(self, theNodes, theModifiedElems, theMakeGroup=False):
6906         """
6907         Create a hole in a mesh by doubling the nodes of some particular elements.
6908         This method provided for convenience works as :meth:`DoubleNodes`.
6909
6910         Parameters:
6911             theNodes: list of groups of nodes to double.
6912             theModifiedElems: list of groups of elements to update.
6913             theMakeGroup: forces the generation of a group containing new nodes.
6914
6915         Returns:
6916             True if operation has been completed successfully, False otherwise
6917         """
6918
6919         if theMakeGroup:
6920             return self.editor.DoubleNodeGroupsNew(theNodes, theModifiedElems)
6921         return self.editor.DoubleNodeGroups(theNodes, theModifiedElems)
6922
6923     def DoubleNodeElem(self, theElems, theNodesNot, theAffectedElems):
6924         """
6925         Create a hole in a mesh by doubling the nodes of some particular elements
6926
6927         Parameters:
6928             theElems: the list of elements (edges or faces) to replicate.
6929                 The nodes for duplication could be found from these elements
6930             theNodesNot: list of nodes NOT to replicate
6931             theAffectedElems: the list of elements (cells and edges) to which the
6932                 replicated nodes should be associated to
6933
6934         Returns:
6935             True if operation has been completed successfully, False otherwise
6936         """
6937
6938         return self.editor.DoubleNodeElem(theElems, theNodesNot, theAffectedElems)
6939
6940     def DoubleNodeElemInRegion(self, theElems, theNodesNot, theShape):
6941         """
6942         Create a hole in a mesh by doubling the nodes of some particular elements
6943
6944         Parameters:
6945             theElems: the list of elements (edges or faces) to replicate.
6946                 The nodes for duplication could be found from these elements
6947             theNodesNot: list of nodes NOT to replicate
6948             theShape: shape to detect affected elements (element which geometric center
6949                 located on or inside shape).
6950                 The replicated nodes should be associated to affected elements.
6951
6952         Returns:
6953             True if operation has been completed successfully, False otherwise
6954         """
6955
6956         return self.editor.DoubleNodeElemInRegion(theElems, theNodesNot, theShape)
6957
6958     def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems,
6959                              theMakeGroup=False, theMakeNodeGroup=False):
6960         """
6961         Create a hole in a mesh by doubling the nodes of some particular elements.
6962         This method provided for convenience works as :meth:`DoubleNodes`.
6963
6964         Parameters:
6965             theElems: group of of elements (edges or faces) to replicate.
6966             theNodesNot: group of nodes NOT to replicate.
6967             theAffectedElems: group of elements to which the replicated nodes
6968                 should be associated to.
6969             theMakeGroup: forces the generation of a group containing new elements.
6970             theMakeNodeGroup: forces the generation of a group containing new nodes.
6971
6972         Returns:
6973             True or created groups (one or two) if operation has been completed successfully,
6974             False or None otherwise
6975         """
6976
6977         if theMakeGroup or theMakeNodeGroup:
6978             twoGroups = self.editor.DoubleNodeElemGroup2New(theElems, theNodesNot,
6979                                                             theAffectedElems,
6980                                                             theMakeGroup, theMakeNodeGroup)
6981             if theMakeGroup and theMakeNodeGroup:
6982                 return twoGroups
6983             else:
6984                 return twoGroups[ int(theMakeNodeGroup) ]
6985         return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems)
6986
6987     def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape):
6988         """
6989         Create a hole in a mesh by doubling the nodes of some particular elements.
6990         This method provided for convenience works as :meth:`DoubleNodes`.
6991
6992         Parameters:
6993             theElems: group of of elements (edges or faces) to replicate
6994             theNodesNot: group of nodes not to replicate
6995             theShape: shape to detect affected elements (element which geometric center
6996                 located on or inside shape).
6997                 The replicated nodes should be associated to affected elements
6998         """
6999
7000         return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape)
7001
7002     def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems,
7003                              theMakeGroup=False, theMakeNodeGroup=False):
7004         """
7005         Create a hole in a mesh by doubling the nodes of some particular elements.
7006         This method provided for convenience works as :meth:`DoubleNodes`.
7007
7008         Parameters:
7009             theElems: list of groups of elements (edges or faces) to replicate
7010             theNodesNot: list of groups of nodes NOT to replicate
7011             theAffectedElems: group of elements to which the replicated nodes
7012                 should be associated to
7013             theMakeGroup: forces generation of a group containing new elements.
7014             theMakeNodeGroup: forces generation of a group containing new nodes
7015
7016         Returns:
7017             True or created groups (one or two) if operation has been completed successfully,
7018             False or None otherwise
7019         """
7020
7021         if theMakeGroup or theMakeNodeGroup:
7022             twoGroups = self.editor.DoubleNodeElemGroups2New(theElems, theNodesNot,
7023                                                              theAffectedElems,
7024                                                              theMakeGroup, theMakeNodeGroup)
7025             if theMakeGroup and theMakeNodeGroup:
7026                 return twoGroups
7027             else:
7028                 return twoGroups[ int(theMakeNodeGroup) ]
7029         return self.editor.DoubleNodeElemGroups(theElems, theNodesNot, theAffectedElems)
7030
7031     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
7032         """
7033         Create a hole in a mesh by doubling the nodes of some particular elements.
7034         This method provided for convenience works as :meth:`DoubleNodes`.
7035
7036         Parameters:
7037             theElems: list of groups of elements (edges or faces) to replicate
7038             theNodesNot: list of groups of nodes NOT to replicate
7039             theShape: shape to detect affected elements (element which geometric center
7040                 located on or inside shape).
7041                 The replicated nodes should be associated to affected elements
7042
7043         Returns:
7044             True if operation has been completed successfully, False otherwise
7045         """
7046
7047         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
7048
7049     def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
7050         """
7051         Identify the elements that will be affected by node duplication (actual duplication is not performed).
7052         This method is the first step of :meth:`DoubleNodeElemGroupsInRegion`.
7053
7054         Parameters:
7055             theElems: list of groups of nodes or elements (edges or faces) to replicate
7056             theNodesNot: list of groups of nodes NOT to replicate
7057             theShape: shape to detect affected elements (element which geometric center
7058                 located on or inside shape).
7059                 The replicated nodes should be associated to affected elements
7060
7061         Returns:
7062             groups of affected elements in order: volumes, faces, edges
7063         """
7064
7065         return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)
7066
7067     def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
7068
7069         """
7070         Double nodes on shared faces between groups of volumes and create flat elements on demand.
7071         The list of groups must describe a partition of the mesh volumes.
7072         The nodes of the internal faces at the boundaries of the groups are doubled.
7073         In option, the internal faces are replaced by flat elements.
7074         Triangles are transformed to prisms, and quadrangles to hexahedrons.
7075
7076         Parameters:
7077             theDomains: list of groups of volumes
7078             createJointElems: if True, create the elements
7079             onAllBoundaries: if True, the nodes and elements are also created on
7080                 the boundary between *theDomains* and the rest mesh
7081
7082         Returns:
7083             True if operation has been completed successfully, False otherwise
7084         """
7085
7086         return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
7087
7088     def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
7089         """
7090         Double nodes on some external faces and create flat elements.
7091         Flat elements are mainly used by some types of mechanic calculations.
7092
7093         Each group of the list must be constituted of faces.
7094         Triangles are transformed in prisms, and quadrangles in hexahedrons.
7095
7096         Parameters:
7097             theGroupsOfFaces: list of groups of faces
7098
7099         Returns:
7100             True if operation has been completed successfully, False otherwise
7101         """
7102
7103         return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
7104
7105     def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
7106         """
7107         Identify all the elements around a geom shape, get the faces delimiting the hole
7108         """
7109         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
7110
7111     def MakePolyLine(self, segments, groupName='', isPreview=False ):
7112         """    
7113         Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7114         the initial triangle mesh. Positions of new nodes are found by cutting the mesh by the
7115         plane passing through pairs of points specified by each :class:`SMESH.PolySegment` structure.
7116         If there are several paths connecting a pair of points, the shortest path is
7117         selected by the module. Position of the cutting plane is defined by the two
7118         points and an optional vector lying on the plane specified by a PolySegment.
7119         By default the vector is defined by Mesh module as following. A middle point
7120         of the two given points is computed. The middle point is projected to the mesh.
7121         The vector goes from the middle point to the projection point. In case of planar
7122         mesh, the vector is normal to the mesh.
7123
7124         In preview mode, *segments* [i].vector returns the used vector which goes from the middle point to its projection.
7125
7126         Parameters:
7127             segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes.
7128             groupName: optional name of a group where created mesh segments will be added.
7129
7130         """    
7131         editor = self.editor
7132         if isPreview:
7133             editor = self.mesh.GetMeshEditPreviewer()
7134         segmentsRes = editor.MakePolyLine( segments, groupName )
7135         for i, seg in enumerate( segmentsRes ):
7136             segments[i].vector = seg.vector
7137         if isPreview:
7138             return editor.GetPreviewData()
7139         return None
7140
7141     def MakeSlot(self, segmentGroup, width ):
7142         """
7143         Create a slot of given width around given 1D elements lying on a triangle mesh.
7144         The slot is constructed by cutting faces by cylindrical surfaces made
7145         around each segment. Segments are expected to be created by MakePolyLine().
7146
7147         Returns:
7148                FaceEdge's located at the slot boundary
7149         """
7150         return self.editor.MakeSlot( segmentGroup, width )
7151
7152     def GetFunctor(self, funcType ):
7153         """
7154         Return a cached numerical functor by its type.
7155
7156         Parameters:
7157             funcType: functor type: an item of :class:`SMESH.FunctorType` enumeration.
7158                 Note that not all items correspond to numerical functors.
7159
7160         Returns:
7161             :class:`SMESH.NumericalFunctor`. The functor is already initialized with a mesh
7162         """
7163
7164         fn = self.functors[ funcType._v ]
7165         if not fn:
7166             fn = self.smeshpyD.GetFunctor(funcType)
7167             fn.SetMesh(self.mesh)
7168             self.functors[ funcType._v ] = fn
7169         return fn
7170
7171     def FunctorValue(self, funcType, elemId, isElem=True):
7172         """
7173         Return value of a functor for a given element
7174
7175         Parameters:
7176             funcType: an item of :class:`SMESH.FunctorType` enum.
7177             elemId: element or node ID
7178             isElem: *elemId* is ID of element or node
7179
7180         Returns:
7181             the functor value or zero in case of invalid arguments
7182         """
7183
7184         fn = self.GetFunctor( funcType )
7185         if fn.GetElementType() == self.GetElementType(elemId, isElem):
7186             val = fn.GetValue(elemId)
7187         else:
7188             val = 0
7189         return val
7190
7191     def GetLength(self, elemId=None):
7192         """
7193         Get length of given 1D elements or of all 1D mesh elements
7194
7195         Parameters:
7196             elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum length of all 1D elements will be calculated.
7197
7198         Returns:
7199             Sum of lengths of given elements
7200         """
7201
7202         length = 0
7203         if elemId == None:
7204             length = self.smeshpyD.GetLength(self)
7205         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7206             length = self.smeshpyD.GetLength(elemId)
7207         elif elemId == []:
7208             length = 0
7209         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7210             for obj in elemId:
7211                 length += self.smeshpyD.GetLength(obj)
7212         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7213             unRegister = genObjUnRegister()
7214             obj = self.GetIDSource( elemId )
7215             unRegister.set( obj )
7216             length = self.smeshpyD.GetLength( obj )
7217         else:
7218             length = self.FunctorValue(SMESH.FT_Length, elemId)
7219         return length
7220
7221     def GetArea(self, elemId=None):
7222         """
7223         Get area of given 2D elements or of all 2D mesh elements
7224
7225         Parameters:
7226             elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum area of all 2D elements will be calculated.
7227
7228         Returns:
7229             Area of given element's if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
7230         """
7231
7232         area = 0
7233         if elemId == None:
7234             area = self.smeshpyD.GetArea(self)
7235         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7236             area = self.smeshpyD.GetArea(elemId)
7237         elif elemId == []:
7238             area = 0
7239         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7240             for obj in elemId:
7241                 area += self.smeshpyD.GetArea(obj)
7242         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7243             unRegister = genObjUnRegister()
7244             obj = self.GetIDSource( elemId )
7245             unRegister.set( obj )
7246             area = self.smeshpyD.GetArea( obj )
7247         else:
7248             area = self.FunctorValue(SMESH.FT_Area, elemId)
7249         return area
7250
7251     def GetVolume(self, elemId=None):
7252         """
7253         Get volume of given 3D elements or of all 3D mesh elements
7254
7255         Parameters:
7256             elemId: either a mesh element ID or a list of IDs or :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`. By default sum volume of all 3D elements will be calculated.
7257
7258         Returns:
7259             Sum element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
7260         """
7261
7262         volume = 0
7263         if elemId == None:
7264             volume= self.smeshpyD.GetVolume(self)
7265         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7266             volume= self.smeshpyD.GetVolume(elemId)
7267         elif elemId == []:
7268             volume = 0
7269         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7270             for obj in elemId:
7271                 volume+= self.smeshpyD.GetVolume(obj)
7272         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7273             unRegister = genObjUnRegister()
7274             obj = self.GetIDSource( elemId )
7275             unRegister.set( obj )
7276             volume= self.smeshpyD.GetVolume( obj )
7277         else:
7278             volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
7279         return volume
7280
7281     def GetAngle(self, node1, node2, node3 ):
7282         """
7283         Computes a radian measure of an angle defined by 3 nodes: <(node1,node2,node3)
7284
7285         Parameters:            
7286                 node1,node2,node3: IDs of the three nodes
7287
7288         Returns:        
7289             Angle in radians [0,PI]. -1 if failure case.
7290         """
7291         p1 = self.GetNodeXYZ( node1 )
7292         p2 = self.GetNodeXYZ( node2 )
7293         p3 = self.GetNodeXYZ( node3 )
7294         if p1 and p2 and p3:
7295             return self.smeshpyD.GetAngle( p1,p2,p3 )
7296         return -1.
7297
7298
7299     def GetMaxElementLength(self, elemId):
7300         """
7301         Get maximum element length.
7302
7303         Parameters:
7304             elemId: mesh element ID
7305
7306         Returns:
7307             element's maximum length value
7308         """
7309
7310         if self.GetElementType(elemId, True) == SMESH.VOLUME:
7311             ftype = SMESH.FT_MaxElementLength3D
7312         else:
7313             ftype = SMESH.FT_MaxElementLength2D
7314         return self.FunctorValue(ftype, elemId)
7315
7316     def GetAspectRatio(self, elemId):
7317         """
7318         Get aspect ratio of 2D or 3D element.
7319
7320         Parameters:
7321             elemId: mesh element ID
7322
7323         Returns:
7324             element's aspect ratio value
7325         """
7326
7327         if self.GetElementType(elemId, True) == SMESH.VOLUME:
7328             ftype = SMESH.FT_AspectRatio3D
7329         else:
7330             ftype = SMESH.FT_AspectRatio
7331         return self.FunctorValue(ftype, elemId)
7332
7333     def GetWarping(self, elemId):
7334         """
7335         Get warping angle of 2D element.
7336
7337         Parameters:
7338             elemId: mesh element ID
7339
7340         Returns:
7341             element's warping angle value
7342         """
7343
7344         return self.FunctorValue(SMESH.FT_Warping, elemId)
7345
7346     def GetMinimumAngle(self, elemId):
7347         """
7348         Get minimum angle of 2D element.
7349
7350         Parameters:
7351             elemId: mesh element ID
7352
7353         Returns:
7354             element's minimum angle value
7355         """
7356
7357         return self.FunctorValue(SMESH.FT_MinimumAngle, elemId)
7358
7359     def GetTaper(self, elemId):
7360         """
7361         Get taper of 2D element.
7362
7363         Parameters:
7364             elemId: mesh element ID
7365
7366         Returns:
7367             element's taper value
7368         """
7369
7370         return self.FunctorValue(SMESH.FT_Taper, elemId)
7371
7372     def GetSkew(self, elemId):
7373         """
7374         Get skew of 2D element.
7375
7376         Parameters:
7377             elemId: mesh element ID
7378
7379         Returns:
7380             element's skew value
7381         """
7382
7383         return self.FunctorValue(SMESH.FT_Skew, elemId)
7384
7385     def GetMinMax(self, funType, meshPart=None):
7386         """
7387         Return minimal and maximal value of a given functor.
7388
7389         Parameters:
7390             funType (SMESH.FunctorType): a functor type.
7391                   Note that not all items of :class:`SMESH.FunctorType` corresponds
7392                   to numerical functors.
7393             meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to treat
7394
7395         Returns:
7396             tuple (min,max)
7397         """
7398
7399         unRegister = genObjUnRegister()
7400         if isinstance( meshPart, list ):
7401             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
7402             unRegister.set( meshPart )
7403         if isinstance( meshPart, Mesh ):
7404             meshPart = meshPart.mesh
7405         fun = self.GetFunctor( funType )
7406         if fun:
7407             if meshPart:
7408                 if hasattr( meshPart, "SetMesh" ):
7409                     meshPart.SetMesh( self.mesh ) # set mesh to filter
7410                 hist = fun.GetLocalHistogram( 1, False, meshPart )
7411             else:
7412                 hist = fun.GetHistogram( 1, False )
7413             if hist:
7414                 return hist[0].min, hist[0].max
7415         return None
7416
7417     pass # end of Mesh class
7418
7419
7420 class meshProxy(SMESH._objref_SMESH_Mesh):
7421     """
7422     Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
7423     with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
7424     """
7425     def __init__(self,*args):
7426         SMESH._objref_SMESH_Mesh.__init__(self,*args)
7427     def __deepcopy__(self, memo=None):
7428         new = self.__class__(self)
7429         return new
7430     def CreateDimGroup(self,*args): # 2 args added: nbCommonNodes, underlyingOnly
7431         if len( args ) == 3:
7432             args += SMESH.ALL_NODES, True
7433         return SMESH._objref_SMESH_Mesh.CreateDimGroup(self, *args)
7434     def ExportToMEDX(self, *args): # function removed
7435         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
7436         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7437         SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
7438     def ExportToMED(self, *args): # function removed
7439         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
7440         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7441         args2 = list(args)
7442         while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
7443             args2.append(True)
7444         SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
7445     def ExportPartToMED(self, *args): # 'version' parameter removed
7446         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7447         SMESH._objref_SMESH_Mesh.ExportPartToMED(self, *args)
7448     def ExportMED(self, *args): # signature of method changed
7449         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7450         args2 = list(args)
7451         while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
7452             args2.append(True)
7453         SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
7454     pass
7455 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
7456
7457
7458 class submeshProxy(SMESH._objref_SMESH_subMesh):
7459
7460     """
7461     Private class wrapping SMESH.SMESH_SubMesh in order to add Compute()
7462     """
7463     def __init__(self,*args):
7464         SMESH._objref_SMESH_subMesh.__init__(self,*args)
7465         self.mesh = None
7466     def __deepcopy__(self, memo=None):
7467         new = self.__class__(self)
7468         return new
7469
7470     def Compute(self,refresh=False):
7471         """
7472         Compute the sub-mesh and return the status of the computation
7473
7474         Parameters:
7475             refresh: if *True*, Object Browser is automatically updated (when running in GUI)
7476
7477         Returns:
7478             True or False
7479
7480         This is a method of SMESH.SMESH_submesh that can be obtained via Mesh.GetSubMesh() or
7481         :meth:`smeshBuilder.Mesh.GetSubMesh`.
7482         """
7483
7484         if not self.mesh:
7485             self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
7486
7487         ok = self.mesh.Compute( self.GetSubShape(),refresh=[] )
7488
7489         if salome.sg.hasDesktop():
7490             if refresh: salome.sg.updateObjBrowser()
7491             pass
7492
7493         return ok
7494     pass
7495 omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
7496
7497
7498 class meshEditor(SMESH._objref_SMESH_MeshEditor):
7499     """
7500     Private class used to compensate change of CORBA API of SMESH_MeshEditor for backward
7501     compatibility with old dump scripts which call SMESH_MeshEditor directly and not via
7502     smeshBuilder.Mesh
7503     """
7504     def __init__(self,*args):
7505         SMESH._objref_SMESH_MeshEditor.__init__( self, *args)
7506         self.mesh = None
7507     def __getattr__(self, name ): # method called if an attribute not found
7508         if not self.mesh:         # look for name() method in Mesh class
7509             self.mesh = Mesh( None, None, SMESH._objref_SMESH_MeshEditor.GetMesh(self))
7510         if hasattr( self.mesh, name ):
7511             return getattr( self.mesh, name )
7512         if name == "ExtrusionAlongPathObjX":
7513             return getattr( self.mesh, "ExtrusionAlongPathX" ) # other method name
7514         print("meshEditor: attribute '%s' NOT FOUND" % name)
7515         return None
7516     def __deepcopy__(self, memo=None):
7517         new = self.__class__(self)
7518         return new
7519     def FindCoincidentNodes(self,*args): # a 2nd arg added (SeparateCornerAndMediumNodes)
7520         if len( args ) == 1: args += False,
7521         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodes( self, *args )
7522     def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
7523         if len( args ) == 2: args += False,
7524         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args )
7525     def MergeNodes(self,*args): # 2 args added (NodesToKeep,AvoidMakingHoles)
7526         if len( args ) == 1:
7527             return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [], False )
7528         NodesToKeep = args[1]
7529         AvoidMakingHoles = args[2] if len( args ) == 3 else False
7530         unRegister  = genObjUnRegister()
7531         if NodesToKeep:
7532             if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
7533                 NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
7534             if not isinstance( NodesToKeep, list ):
7535                 NodesToKeep = [ NodesToKeep ]
7536         return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles )
7537     pass
7538 omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)
7539
7540 class Pattern(SMESH._objref_SMESH_Pattern):
7541     """
7542     Private class wrapping SMESH.SMESH_Pattern CORBA class in order to treat Notebook
7543     variables in some methods
7544     """
7545
7546     def LoadFromFile(self, patternTextOrFile ):
7547         text = patternTextOrFile
7548         if os.path.exists( text ):
7549             text = open( patternTextOrFile ).read()
7550             pass
7551         return SMESH._objref_SMESH_Pattern.LoadFromFile( self, text )
7552
7553     def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse):
7554         decrFun = lambda i: i-1
7555         theNodeIndexOnKeyPoint1,Parameters,hasVars = ParseParameters(theNodeIndexOnKeyPoint1, decrFun)
7556         theMesh.SetParameters(Parameters)
7557         return SMESH._objref_SMESH_Pattern.ApplyToMeshFaces( self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse )
7558
7559     def ApplyToHexahedrons(self, theMesh, theVolumesIDs, theNode000Index, theNode001Index):
7560         decrFun = lambda i: i-1
7561         theNode000Index,theNode001Index,Parameters,hasVars = ParseParameters(theNode000Index,theNode001Index, decrFun)
7562         theMesh.SetParameters(Parameters)
7563         return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index )
7564
7565     def MakeMesh(self, mesh, CreatePolygons=False, CreatePolyhedra=False):
7566         if isinstance( mesh, Mesh ):
7567             mesh = mesh.GetMesh()
7568         return SMESH._objref_SMESH_Pattern.MakeMesh( self, mesh, CreatePolygons, CreatePolyhedra )
7569
7570 omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
7571 """
7572 Registering the new proxy for Pattern
7573 """
7574
7575 class algoCreator:
7576     """
7577     Private class used to bind methods creating algorithms to the class Mesh
7578     """
7579
7580     def __init__(self, method):
7581         self.mesh = None
7582         self.defaultAlgoType = ""
7583         self.algoTypeToClass = {}
7584         self.method = method
7585
7586     def add(self, algoClass):
7587         """
7588         Store a python class of algorithm
7589         """
7590         if inspect.isclass(algoClass) and \
7591            hasattr( algoClass, "algoType"):
7592             self.algoTypeToClass[ algoClass.algoType ] = algoClass
7593             if not self.defaultAlgoType and \
7594                hasattr( algoClass, "isDefault") and algoClass.isDefault:
7595                 self.defaultAlgoType = algoClass.algoType
7596             #print("Add",algoClass.algoType, "dflt",self.defaultAlgoType)
7597
7598     def copy(self, mesh):
7599         """
7600         Create a copy of self and assign mesh to the copy
7601         """
7602
7603         other = algoCreator( self.method )
7604         other.defaultAlgoType = self.defaultAlgoType
7605         other.algoTypeToClass = self.algoTypeToClass
7606         other.mesh = mesh
7607         return other
7608
7609     def __call__(self,algo="",geom=0,*args):
7610         """
7611         Create an instance of algorithm
7612         """
7613         algoType = ""
7614         shape = 0
7615         if isinstance( algo, str ):
7616             algoType = algo
7617         elif ( isinstance( algo, geomBuilder.GEOM._objref_GEOM_Object ) and \
7618                not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object )):
7619             shape = algo
7620         elif algo:
7621             args += (algo,)
7622
7623         if isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
7624             shape = geom
7625         elif not algoType and isinstance( geom, str ):
7626             algoType = geom
7627         elif geom:
7628             args += (geom,)
7629         for arg in args:
7630             if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ) and not shape:
7631                 shape = arg
7632             elif isinstance( arg, str ) and not algoType:
7633                 algoType = arg
7634             else:
7635                 import traceback, sys
7636                 msg = "Warning. Unexpected argument in mesh.%s() --->  %s" % ( self.method, arg )
7637                 sys.stderr.write( msg + '\n' )
7638                 tb = traceback.extract_stack(None,2)
7639                 traceback.print_list( [tb[0]] )
7640         if not algoType:
7641             algoType = self.defaultAlgoType
7642         if not algoType and self.algoTypeToClass:
7643             algoType = sorted( self.algoTypeToClass.keys() )[0]
7644         if algoType in self.algoTypeToClass:
7645             #print("Create algo",algoType)
7646             return self.algoTypeToClass[ algoType ]( self.mesh, shape )
7647         raise RuntimeError( "No class found for algo type %s" % algoType)
7648         return None
7649
7650 class hypMethodWrapper:
7651     """
7652     Private class used to substitute and store variable parameters of hypotheses.
7653     """
7654
7655     def __init__(self, hyp, method):
7656         self.hyp    = hyp
7657         self.method = method
7658         #print("REBIND:", method.__name__)
7659         return
7660
7661     def __call__(self,*args):
7662         """
7663         call a method of hypothesis with calling SetVarParameter() before
7664         """
7665
7666         if not args:
7667             return self.method( self.hyp, *args ) # hypothesis method with no args
7668
7669         #print("MethWrapper.__call__", self.method.__name__, args)
7670         try:
7671             parsed = ParseParameters(*args)     # replace variables with their values
7672             self.hyp.SetVarParameter( parsed[-2], self.method.__name__ )
7673             result = self.method( self.hyp, *parsed[:-2] ) # call hypothesis method
7674         except omniORB.CORBA.BAD_PARAM: # raised by hypothesis method call
7675             # maybe there is a replaced string arg which is not variable
7676             result = self.method( self.hyp, *args )
7677         except ValueError as detail: # raised by ParseParameters()
7678             try:
7679                 result = self.method( self.hyp, *args )
7680             except omniORB.CORBA.BAD_PARAM:
7681                 raise ValueError(detail) # wrong variable name
7682
7683         return result
7684     pass
7685
7686 class genObjUnRegister:
7687     """
7688     A helper class that calls UnRegister() of SALOME.GenericObj'es stored in it
7689     """
7690
7691     def __init__(self, genObj=None):
7692         self.genObjList = []
7693         self.set( genObj )
7694         return
7695
7696     def set(self, genObj):
7697         "Store one or a list of of SALOME.GenericObj'es"
7698         if isinstance( genObj, list ):
7699             self.genObjList.extend( genObj )
7700         else:
7701             self.genObjList.append( genObj )
7702         return
7703
7704     def __del__(self):
7705         for genObj in self.genObjList:
7706             if genObj and hasattr( genObj, "UnRegister" ):
7707                 genObj.UnRegister()
7708
7709 for pluginName in os.environ[ "SMESH_MeshersList" ].split( os.pathsep ):
7710     """
7711     Bind methods creating mesher plug-ins to the Mesh class
7712     """
7713
7714     # print("pluginName: ", pluginName)
7715     pluginBuilderName = pluginName + "Builder"
7716     try:
7717         exec( "from salome.%s.%s import *" % (pluginName, pluginBuilderName))
7718     except Exception as e:
7719         from salome_utils import verbose
7720         if verbose(): print("Exception while loading %s: %s" % ( pluginBuilderName, e ))
7721         continue
7722     exec( "from salome.%s import %s" % (pluginName, pluginBuilderName))
7723     plugin = eval( pluginBuilderName )
7724     # print("  plugin:" , str(plugin))
7725
7726     # add methods creating algorithms to Mesh
7727     for k in dir( plugin ):
7728         if k[0] == '_': continue
7729         algo = getattr( plugin, k )
7730         #print("             algo:", str(algo))
7731         if inspect.isclass(algo) and hasattr(algo, "meshMethod"):
7732             #print("                     meshMethod:" , str(algo.meshMethod))
7733             if not hasattr( Mesh, algo.meshMethod ):
7734                 setattr( Mesh, algo.meshMethod, algoCreator( algo.meshMethod ))
7735                 pass
7736             _mmethod = getattr( Mesh, algo.meshMethod )
7737             if hasattr(  _mmethod, "add" ):
7738                 _mmethod.add(algo)
7739             pass
7740         pass
7741     pass
7742 del pluginName