Salome HOME
Update of CheckDone
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
1 # Copyright (C) 2007-2020  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 = self.geom.GetGen()
1655                 pass
1656         pass
1657
1658     def GetMesh(self):
1659         """
1660         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1661
1662         Returns:
1663                 a :class:`SMESH.SMESH_Mesh` object
1664         """
1665
1666         return self.mesh
1667
1668     def GetEngine(self):
1669         """
1670         Return a smeshBuilder instance created this mesh
1671         """
1672         return self.smeshpyD
1673
1674     def GetGeomEngine(self):
1675         """
1676         Return a geomBuilder instance
1677         """
1678         return self.geompyD
1679
1680     def GetName(self):
1681         """
1682         Get the name of the mesh
1683
1684         Returns:
1685                 the name of the mesh as a string
1686         """
1687
1688         name = GetName(self.GetMesh())
1689         return name
1690
1691     def SetName(self, name):
1692         """
1693         Set a name to the mesh
1694
1695         Parameters:
1696                 name: a new name of the mesh
1697         """
1698
1699         self.smeshpyD.SetName(self.GetMesh(), name)
1700
1701     def GetSubMesh(self, geom, name):
1702         """
1703         Get a sub-mesh object associated to a *geom* geometrical object.
1704
1705         Parameters:
1706                 geom: a geometrical object (shape)
1707                 name: a name for the sub-mesh in the Object Browser
1708
1709         Returns:
1710                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1711                 which lies on the given shape
1712
1713         Note:
1714                 A sub-mesh is implicitly created when a sub-shape is specified at
1715                 creating an algorithm, for example::
1716
1717                    algo1D = mesh.Segment(geom=Edge_1)
1718
1719                 create a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1720                 The created sub-mesh can be retrieved from the algorithm::
1721
1722                    submesh = algo1D.GetSubMesh()
1723         """
1724
1725         AssureGeomPublished( self, geom, name )
1726         submesh = self.mesh.GetSubMesh( geom, name )
1727         return submesh
1728
1729     def GetShape(self):
1730         """
1731         Return the shape associated to the mesh
1732
1733         Returns:
1734                 a GEOM_Object
1735         """
1736
1737         return self.geom
1738
1739     def SetShape(self, geom):
1740         """
1741         Associate the given shape to the mesh (entails the recreation of the mesh)
1742
1743         Parameters:
1744                 geom: the shape to be meshed (GEOM_Object)
1745         """
1746
1747         self.mesh = self.smeshpyD.CreateMesh(geom)
1748
1749     def HasShapeToMesh(self):
1750         """
1751         Return ``True`` if this mesh is based on geometry
1752         """
1753         return self.mesh.HasShapeToMesh()
1754
1755     def Load(self):
1756         """
1757         Load mesh from the study after opening the study
1758         """
1759         self.mesh.Load()
1760
1761     def IsReadyToCompute(self, theSubObject):
1762         """
1763         Return true if the hypotheses are defined well
1764
1765         Parameters:
1766                 theSubObject: a sub-shape of a mesh shape
1767
1768         Returns:
1769                 True or False
1770         """
1771
1772         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1773
1774     def GetAlgoState(self, theSubObject):
1775         """
1776         Return errors of hypotheses definition.
1777         The list of errors is empty if everything is OK.
1778
1779         Parameters:
1780                 theSubObject: a sub-shape of a mesh shape
1781
1782         Returns:
1783                 a list of errors
1784         """
1785
1786         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1787
1788     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1789         """
1790         Return a geometrical object on which the given element was built.
1791         The returned geometrical object, if not nil, is either found in the
1792         study or published by this method with the given name
1793
1794         Parameters:
1795             theElementID: the id of the mesh element
1796             theGeomName: the user-defined name of the geometrical object
1797
1798         Returns:
1799             GEOM.GEOM_Object instance
1800         """
1801
1802         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1803
1804     def MeshDimension(self):
1805         """
1806         Return the mesh dimension depending on the dimension of the underlying shape
1807         or, if the mesh is not based on any shape, basing on deimension of elements
1808
1809         Returns:
1810                 mesh dimension as an integer value [0,3]
1811         """
1812
1813         if self.mesh.HasShapeToMesh():
1814             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1815             if len( shells ) > 0 :
1816                 return 3
1817             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1818                 return 2
1819             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1820                 return 1
1821             else:
1822                 return 0;
1823         else:
1824             if self.NbVolumes() > 0: return 3
1825             if self.NbFaces()   > 0: return 2
1826             if self.NbEdges()   > 0: return 1
1827         return 0
1828
1829     def Evaluate(self, geom=0):
1830         """
1831         Evaluate size of prospective mesh on a shape
1832
1833         Returns:
1834                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1835                 To know predicted number of e.g. edges, inquire it this way::
1836
1837                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1838         """
1839
1840         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1841             if self.geom == 0:
1842                 geom = self.mesh.GetShapeToMesh()
1843             else:
1844                 geom = self.geom
1845         return self.smeshpyD.Evaluate(self.mesh, geom)
1846
1847
1848     def Compute(self, geom=0, discardModifs=False, refresh=False):
1849         """
1850         Compute the mesh and return the status of the computation
1851
1852         Parameters:
1853                 geom: geomtrical shape on which mesh data should be computed
1854                 discardModifs: if True and the mesh has been edited since
1855                         a last total re-compute and that may prevent successful partial re-compute,
1856                         then the mesh is cleaned before Compute()
1857                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1858
1859         Returns:
1860                 True or False
1861         """
1862
1863         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1864             geom = self.mesh.GetShapeToMesh()
1865         ok = False
1866         try:
1867             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1868                 self.mesh.Clear()
1869             ok = self.smeshpyD.Compute(self.mesh, geom)
1870         except SALOME.SALOME_Exception as ex:
1871             print("Mesh computation failed, exception caught:")
1872             print("    ", ex.details.text)
1873         except:
1874             import traceback
1875             print("Mesh computation failed, exception caught:")
1876             traceback.print_exc()
1877         if True:#not ok:
1878             allReasons = ""
1879
1880             # Treat compute errors
1881             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1882             shapeText = ""
1883             for err in computeErrors:
1884                 if self.mesh.HasShapeToMesh():
1885                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1886                 errText = ""
1887                 stdErrors = ["OK",                   #COMPERR_OK
1888                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1889                              "std::exception",       #COMPERR_STD_EXCEPTION
1890                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1891                              "..",                   #COMPERR_SLM_EXCEPTION
1892                              "Unknown exception",    #COMPERR_EXCEPTION
1893                              "Memory allocation problem", #COMPERR_MEMORY_PB
1894                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1895                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1896                              "Warning",              #COMPERR_WARNING
1897                              "Computation cancelled",#COMPERR_CANCELED
1898                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1899                 if err.code > 0:
1900                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1901                 else:
1902                     errText = "code %s" % -err.code
1903                 if errText: errText += ". "
1904                 errText += err.comment
1905                 if allReasons: allReasons += "\n"
1906                 if ok:
1907                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1908                 else:
1909                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1910                 pass
1911
1912             # Treat hyp errors
1913             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1914             for err in errors:
1915                 if err.isGlobalAlgo:
1916                     glob = "global"
1917                 else:
1918                     glob = "local"
1919                     pass
1920                 dim = err.algoDim
1921                 name = err.algoName
1922                 if len(name) == 0:
1923                     reason = '%s %sD algorithm is missing' % (glob, dim)
1924                 elif err.state == HYP_MISSING:
1925                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1926                               % (glob, dim, name, dim))
1927                 elif err.state == HYP_NOTCONFORM:
1928                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1929                 elif err.state == HYP_BAD_PARAMETER:
1930                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1931                               % ( glob, dim, name ))
1932                 elif err.state == HYP_BAD_GEOMETRY:
1933                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1934                               'geometry' % ( glob, dim, name ))
1935                 elif err.state == HYP_HIDDEN_ALGO:
1936                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1937                               'algorithm of upper dimension generating %sD mesh'
1938                               % ( glob, dim, name, glob, dim ))
1939                 else:
1940                     reason = ("For unknown reason. "
1941                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1942                     pass
1943                 if allReasons: allReasons += "\n"
1944                 allReasons += "-  " + reason
1945                 pass
1946             if not ok or allReasons != "":
1947                 msg = '"' + GetName(self.mesh) + '"'
1948                 if ok: msg += " has been computed with warnings"
1949                 else:  msg += " has not been computed"
1950                 if allReasons != "": msg += ":"
1951                 else:                msg += "."
1952                 print(msg)
1953                 print(allReasons)
1954             pass
1955         if salome.sg.hasDesktop():
1956             if not isinstance( refresh, list): # not a call from subMesh.Compute()
1957                 if refresh: salome.sg.updateObjBrowser()
1958
1959         return ok
1960
1961     def GetComputeErrors(self, shape=0 ):
1962         """
1963         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1964         """
1965
1966         if shape == 0:
1967             shape = self.mesh.GetShapeToMesh()
1968         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1969
1970     def GetSubShapeName(self, subShapeID ):
1971         """
1972         Return a name of a sub-shape by its ID.
1973         Possible variants (for *subShapeID* == 3):
1974
1975                 - **"Face_12"** - published sub-shape
1976                 - **FACE #3** - not published sub-shape
1977                 - **sub-shape #3** - invalid sub-shape ID
1978                 - **#3** - error in this function
1979
1980         Parameters:
1981                 subShapeID: a unique ID of a sub-shape
1982
1983         Returns:
1984                 a string describing the sub-shape
1985
1986         """
1987
1988         if not self.mesh.HasShapeToMesh():
1989             return ""
1990         try:
1991             shapeText = ""
1992             mainIOR  = salome.orb.object_to_string( self.GetShape() )
1993             s = salome.myStudy
1994             mainSO = s.FindObjectIOR(mainIOR)
1995             if mainSO:
1996                 if subShapeID == 1:
1997                     shapeText = '"%s"' % mainSO.GetName()
1998                 subIt = s.NewChildIterator(mainSO)
1999                 while subIt.More():
2000                     subSO = subIt.Value()
2001                     subIt.Next()
2002                     obj = subSO.GetObject()
2003                     if not obj: continue
2004                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
2005                     if not go: continue
2006                     try:
2007                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
2008                     except:
2009                         continue
2010                     if ids == subShapeID:
2011                         shapeText = '"%s"' % subSO.GetName()
2012                         break
2013             if not shapeText:
2014                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
2015                 if shape:
2016                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
2017                 else:
2018                     shapeText = 'sub-shape #%s' % (subShapeID)
2019         except:
2020             shapeText = "#%s" % (subShapeID)
2021         return shapeText
2022
2023     def GetFailedShapes(self, publish=False):
2024         """
2025         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
2026         error of an algorithm
2027
2028         Parameters:
2029                 publish: if *True*, the returned groups will be published in the study
2030
2031         Returns:
2032                 a list of GEOM groups each named after a failed algorithm
2033         """
2034
2035
2036         algo2shapes = {}
2037         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
2038         for err in computeErrors:
2039             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
2040             if not shape: continue
2041             if err.algoName in algo2shapes:
2042                 algo2shapes[ err.algoName ].append( shape )
2043             else:
2044                 algo2shapes[ err.algoName ] = [ shape ]
2045             pass
2046
2047         groups = []
2048         for algoName, shapes in list(algo2shapes.items()):
2049             while shapes:
2050                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
2051                 otherTypeShapes = []
2052                 sameTypeShapes  = []
2053                 group = self.geompyD.CreateGroup( self.geom, groupType )
2054                 for shape in shapes:
2055                     if shape.GetShapeType() == shapes[0].GetShapeType():
2056                         sameTypeShapes.append( shape )
2057                     else:
2058                         otherTypeShapes.append( shape )
2059                 self.geompyD.UnionList( group, sameTypeShapes )
2060                 if otherTypeShapes:
2061                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
2062                 else:
2063                     group.SetName( algoName )
2064                 groups.append( group )
2065                 shapes = otherTypeShapes
2066             pass
2067         if publish:
2068             for group in groups:
2069                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
2070         return groups
2071
2072     def GetMeshOrder(self):
2073         """
2074         Return sub-mesh objects list in meshing order
2075
2076         Returns:
2077                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2078         """
2079
2080         return self.mesh.GetMeshOrder()
2081
2082     def SetMeshOrder(self, submeshes):
2083         """
2084         Set priority of sub-meshes. It works in two ways:
2085         
2086         * For sub-meshes with assigned algorithms of same dimension generating mesh of
2087           *several dimensions*, it sets the order in which the sub-meshes are computed.
2088         * For the rest sub-meshes, it sets the order in which the sub-meshes are checked
2089           when looking for meshing parameters to apply to a sub-shape. To impose the 
2090           order in which sub-meshes with uni-dimensional algorithms are computed, 
2091           call **submesh.Compute()** in a desired order.
2092
2093         Parameters:
2094                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
2095
2096         Warning: the method is for setting the order for all sub-meshes at once:
2097                  SetMeshOrder( [ [sm1, sm2, sm3], [sm4, sm5] ] )
2098         """
2099
2100         return self.mesh.SetMeshOrder(submeshes)
2101
2102     def Clear(self, refresh=False):
2103         """
2104         Remove all nodes and elements generated on geometry. Imported elements remain.
2105
2106         Parameters:
2107                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2108         """
2109
2110         self.mesh.Clear()
2111         if ( salome.sg.hasDesktop() ):
2112             if refresh: salome.sg.updateObjBrowser()
2113
2114     def ClearSubMesh(self, geomId, refresh=False):
2115         """
2116         Remove all nodes and elements of indicated shape
2117
2118         Parameters:
2119                 geomId: the ID of a sub-shape to remove elements on
2120                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
2121         """
2122
2123         self.mesh.ClearSubMesh(geomId)
2124         if salome.sg.hasDesktop():
2125             if refresh: salome.sg.updateObjBrowser()
2126
2127     def AutomaticTetrahedralization(self, fineness=0):
2128         """
2129         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
2130
2131         Parameters:
2132                 fineness: [0.0,1.0] defines mesh fineness
2133
2134         Returns:
2135                 True or False
2136         """
2137
2138         dim = self.MeshDimension()
2139         # assign hypotheses
2140         self.RemoveGlobalHypotheses()
2141         self.Segment().AutomaticLength(fineness)
2142         if dim > 1 :
2143             self.Triangle().LengthFromEdges()
2144             pass
2145         if dim > 2 :
2146             self.Tetrahedron()
2147             pass
2148         return self.Compute()
2149
2150     def AutomaticHexahedralization(self, fineness=0):
2151         """
2152         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2153
2154         Parameters:
2155                 fineness: [0.0, 1.0] defines mesh fineness
2156
2157         Returns:
2158                 True or False
2159         """
2160
2161         dim = self.MeshDimension()
2162         # assign the hypotheses
2163         self.RemoveGlobalHypotheses()
2164         self.Segment().AutomaticLength(fineness)
2165         if dim > 1 :
2166             self.Quadrangle()
2167             pass
2168         if dim > 2 :
2169             self.Hexahedron()
2170             pass
2171         return self.Compute()
2172
2173     def AddHypothesis(self, hyp, geom=0):
2174         """
2175         Assign a hypothesis
2176
2177         Parameters:
2178                 hyp: a hypothesis to assign
2179                 geom: a subhape of mesh geometry
2180
2181         Returns:
2182                 :class:`SMESH.Hypothesis_Status`
2183         """
2184
2185         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2186             hyp, geom = geom, hyp
2187         if isinstance( hyp, Mesh_Algorithm ):
2188             hyp = hyp.GetAlgorithm()
2189             pass
2190         if not geom:
2191             geom = self.geom
2192             if not geom:
2193                 geom = self.mesh.GetShapeToMesh()
2194             pass
2195         isApplicable = True
2196         if self.mesh.HasShapeToMesh():
2197             hyp_type     = hyp.GetName()
2198             lib_name     = hyp.GetLibName()
2199             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2200             # if checkAll and geom:
2201             #     checkAll = geom.GetType() == 37
2202             checkAll     = False
2203             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2204         if isApplicable:
2205             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2206             status = self.mesh.AddHypothesis(geom, hyp)
2207         else:
2208             status = HYP_BAD_GEOMETRY, ""
2209         hyp_name = GetName( hyp )
2210         geom_name = ""
2211         if geom:
2212             geom_name = geom.GetName()
2213         isAlgo = hyp._narrow( SMESH_Algo )
2214         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2215         return status
2216
2217     def IsUsedHypothesis(self, hyp, geom):
2218         """
2219         Return True if an algorithm or hypothesis is assigned to a given shape
2220
2221         Parameters:
2222                 hyp: an algorithm or hypothesis to check
2223                 geom: a subhape of mesh geometry
2224
2225         Returns:
2226                 True of False
2227         """
2228
2229         if not hyp: # or not geom
2230             return False
2231         if isinstance( hyp, Mesh_Algorithm ):
2232             hyp = hyp.GetAlgorithm()
2233             pass
2234         hyps = self.GetHypothesisList(geom)
2235         for h in hyps:
2236             if h.GetId() == hyp.GetId():
2237                 return True
2238         return False
2239
2240     def RemoveHypothesis(self, hyp, geom=0):
2241         """
2242         Unassign a hypothesis
2243
2244         Parameters:
2245                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2246                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2247
2248         Returns:
2249                 :class:`SMESH.Hypothesis_Status`
2250         """
2251
2252         if not hyp:
2253             return None
2254         if isinstance( hyp, Mesh_Algorithm ):
2255             hyp = hyp.GetAlgorithm()
2256             pass
2257         shape = geom
2258         if not shape:
2259             shape = self.geom
2260             pass
2261         if self.IsUsedHypothesis( hyp, shape ):
2262             return self.mesh.RemoveHypothesis( shape, hyp )
2263         hypName = GetName( hyp )
2264         geoName = GetName( shape )
2265         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2266         return None
2267
2268     def GetHypothesisList(self, geom):
2269         """
2270         Get the list of hypotheses added on a geometry
2271
2272         Parameters:
2273                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2274
2275         Returns:
2276                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2277         """
2278
2279         return self.mesh.GetHypothesisList( geom )
2280
2281     def RemoveGlobalHypotheses(self):
2282         """
2283         Remove all global hypotheses
2284         """
2285
2286         current_hyps = self.mesh.GetHypothesisList( self.geom )
2287         for hyp in current_hyps:
2288             self.mesh.RemoveHypothesis( self.geom, hyp )
2289             pass
2290         pass
2291     def ExportMED(self, *args, **kwargs):
2292         """
2293         Export the mesh in a file in MED format
2294         allowing to overwrite the file if it exists or add the exported data to its contents
2295
2296         Parameters:
2297                 fileName: is the file name
2298                 auto_groups (boolean): parameter for creating/not creating
2299                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2300                         the typical use is auto_groups=False.
2301                 version (int): define the version (xy, where version is x.y.z) of MED file format.
2302                         For instance med 3.2.1 is coded 3*10+2 = 32, med 4.0.0 is coded 4*10+0 = 40.
2303                         The rules of compatibility to write a mesh in an older version than 
2304                         the current version depend on the current version. For instance, 
2305                         with med 4.0 it is possible to write/append med files in 4.0.0 (default)
2306                         or 3.2.1 or 3.3.1 formats.
2307                         If the version is equal to -1, the version is not changed (default).
2308                 overwrite (boolean): parameter for overwriting/not overwriting the file
2309                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2310                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2311
2312                         - 1D if all mesh nodes lie on OX coordinate axis, or
2313                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2314                         - 3D in the rest cases.
2315
2316                         If *autoDimension* is *False*, the space dimension is always 3.
2317                 fields: list of GEOM fields defined on the shape to mesh.
2318                 geomAssocFields: each character of this string means a need to export a 
2319                         corresponding field; correspondence between fields and characters 
2320                         is following:
2321
2322                         - 'v' stands for "_vertices_" field;
2323                         - 'e' stands for "_edges_" field;
2324                         - 'f' stands for "_faces_" field;
2325                         - 's' stands for "_solids_" field.
2326
2327                 zTolerance (float): tolerance in Z direction. If Z coordinate of a node is 
2328                              close to zero within a given tolerance, the coordinate is set to zero.
2329                              If *ZTolerance* is negative (default), the node coordinates are kept as is.
2330         """
2331         # process positional arguments
2332         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2333         fileName        = args[0]
2334         auto_groups     = args[1] if len(args) > 1 else False
2335         version         = args[2] if len(args) > 2 else -1
2336         overwrite       = args[3] if len(args) > 3 else True
2337         meshPart        = args[4] if len(args) > 4 else None
2338         autoDimension   = args[5] if len(args) > 5 else True
2339         fields          = args[6] if len(args) > 6 else []
2340         geomAssocFields = args[7] if len(args) > 7 else ''
2341         z_tolerance     = args[8] if len(args) > 8 else -1.
2342         # process keywords arguments
2343         auto_groups     = kwargs.get("auto_groups", auto_groups)
2344         version         = kwargs.get("version", version)
2345         version         = kwargs.get("minor", version)
2346         overwrite       = kwargs.get("overwrite", overwrite)
2347         meshPart        = kwargs.get("meshPart", meshPart)
2348         autoDimension   = kwargs.get("autoDimension", autoDimension)
2349         fields          = kwargs.get("fields", fields)
2350         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2351         z_tolerance     = kwargs.get("zTolerance", z_tolerance)
2352
2353         # invoke engine's function
2354         if meshPart or fields or geomAssocFields or z_tolerance > 0:
2355             unRegister = genObjUnRegister()
2356             if isinstance( meshPart, list ):
2357                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2358                 unRegister.set( meshPart )
2359
2360             z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
2361             self.mesh.SetParameters(Parameters)
2362
2363             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups,
2364                                        version, overwrite, autoDimension,
2365                                        fields, geomAssocFields, z_tolerance)
2366         else:
2367             self.mesh.ExportMED(fileName, auto_groups, version, overwrite, autoDimension)
2368
2369     def ExportSAUV(self, f, auto_groups=0):
2370         """
2371         Export the mesh in a file in SAUV format
2372
2373
2374         Parameters:
2375                 f: is the file name
2376                 auto_groups: boolean parameter for creating/not creating
2377                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2378                         the typical use is auto_groups=False.
2379         """
2380
2381         self.mesh.ExportSAUV(f, auto_groups)
2382
2383     def ExportDAT(self, f, meshPart=None):
2384         """
2385         Export the mesh in a file in DAT format
2386
2387         Parameters:
2388                 f: the file name
2389                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2390         """
2391
2392         if meshPart:
2393             unRegister = genObjUnRegister()
2394             if isinstance( meshPart, list ):
2395                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2396                 unRegister.set( meshPart )
2397             self.mesh.ExportPartToDAT( meshPart, f )
2398         else:
2399             self.mesh.ExportDAT(f)
2400
2401     def ExportUNV(self, f, meshPart=None):
2402         """
2403         Export the mesh in a file in UNV format
2404
2405         Parameters:
2406                 f: the file name
2407                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2408         """
2409
2410         if meshPart:
2411             unRegister = genObjUnRegister()
2412             if isinstance( meshPart, list ):
2413                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2414                 unRegister.set( meshPart )
2415             self.mesh.ExportPartToUNV( meshPart, f )
2416         else:
2417             self.mesh.ExportUNV(f)
2418
2419     def ExportSTL(self, f, ascii=1, meshPart=None):
2420         """
2421         Export the mesh in a file in STL format
2422
2423         Parameters:
2424                 f: the file name
2425                 ascii: defines the file encoding
2426                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2427         """
2428
2429         if meshPart:
2430             unRegister = genObjUnRegister()
2431             if isinstance( meshPart, list ):
2432                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2433                 unRegister.set( meshPart )
2434             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2435         else:
2436             self.mesh.ExportSTL(f, ascii)
2437
2438     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2439         """
2440         Export the mesh in a file in CGNS format
2441
2442         Parameters:
2443                 f: is the file name
2444                 overwrite: boolean parameter for overwriting/not overwriting the file
2445                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2446                 groupElemsByType: if True all elements of same entity type are exported at ones,
2447                         else elements are exported in order of their IDs which can cause creation
2448                         of multiple cgns sections
2449         """
2450
2451         unRegister = genObjUnRegister()
2452         if isinstance( meshPart, list ):
2453             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2454             unRegister.set( meshPart )
2455         if isinstance( meshPart, Mesh ):
2456             meshPart = meshPart.mesh
2457         elif not meshPart:
2458             meshPart = self.mesh
2459         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2460
2461     def ExportGMF(self, f, meshPart=None):
2462         """
2463         Export the mesh in a file in GMF format.
2464         GMF files must have .mesh extension for the ASCII format and .meshb for
2465         the bynary format. Other extensions are not allowed.
2466
2467         Parameters:
2468                 f: is the file name
2469                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2470         """
2471
2472         unRegister = genObjUnRegister()
2473         if isinstance( meshPart, list ):
2474             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2475             unRegister.set( meshPart )
2476         if isinstance( meshPart, Mesh ):
2477             meshPart = meshPart.mesh
2478         elif not meshPart:
2479             meshPart = self.mesh
2480         self.mesh.ExportGMF(meshPart, f, True)
2481
2482     def ExportToMED(self, *args, **kwargs):
2483         """
2484         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2485         Export the mesh in a file in MED format
2486         allowing to overwrite the file if it exists or add the exported data to its contents
2487
2488         Parameters:
2489                 fileName: the file name
2490                 opt (boolean): parameter for creating/not creating
2491                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2492                 overwrite: boolean parameter for overwriting/not overwriting the file
2493                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2494
2495                         - 1D if all mesh nodes lie on OX coordinate axis, or
2496                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2497                         - 3D in the rest cases.
2498
2499                         If **autoDimension** is *False*, the space dimension is always 3.
2500         """
2501     
2502         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2503         # process positional arguments
2504         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2505         fileName      = args[0]
2506         auto_groups   = args[1] if len(args) > 1 else False
2507         overwrite     = args[2] if len(args) > 2 else True
2508         autoDimension = args[3] if len(args) > 3 else True
2509         # process keywords arguments
2510         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2511         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2512         overwrite     = kwargs.get("overwrite", overwrite)
2513         autoDimension = kwargs.get("autoDimension", autoDimension)
2514         minor = -1
2515         # invoke engine's function
2516         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2517
2518     def ExportToMEDX(self, *args, **kwargs):
2519         """
2520         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2521         Export the mesh in a file in MED format
2522
2523         Parameters:
2524                 fileName: the file name
2525                 opt (boolean): parameter for creating/not creating
2526                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2527                 overwrite: boolean parameter for overwriting/not overwriting the file
2528                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2529
2530                         - 1D if all mesh nodes lie on OX coordinate axis, or
2531                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2532                         - 3D in the rest cases.
2533
2534                         If **autoDimension** is *False*, the space dimension is always 3.
2535                 """
2536
2537         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2538         # process positional arguments
2539         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2540         fileName      = args[0]
2541         auto_groups   = args[1] if len(args) > 1 else False
2542         overwrite     = args[2] if len(args) > 2 else True
2543         autoDimension = args[3] if len(args) > 3 else True
2544         # process keywords arguments
2545         auto_groups   = kwargs.get("auto_groups", auto_groups)
2546         overwrite     = kwargs.get("overwrite", overwrite)
2547         autoDimension = kwargs.get("autoDimension", autoDimension)
2548         minor = -1
2549         # invoke engine's function
2550         self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
2551         return
2552
2553
2554     def Append(self, meshes, uniteIdenticalGroups = True,
2555                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False):
2556         """
2557         Append given meshes into this mesh.
2558         All groups of input meshes will be created in this mesh.
2559
2560         Parameters:
2561                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to append
2562                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
2563                 mergeNodesAndElements: if True, equal nodes and elements are merged
2564                 mergeTolerance: tolerance for merging nodes
2565                 allGroups: forces creation of groups corresponding to every input mesh
2566         """
2567         self.smeshpyD.Concatenate( meshes, uniteIdenticalGroups,
2568                                    mergeNodesAndElements, mergeTolerance, allGroups,
2569                                    meshToAppendTo = self.GetMesh() )
2570
2571     # Operations with groups:
2572     # ----------------------
2573     def CreateEmptyGroup(self, elementType, name):
2574         """
2575         Create an empty standalone mesh group
2576
2577         Parameters:
2578                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2579                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2580                 name: the name of the mesh group
2581
2582         Returns:
2583                 :class:`SMESH.SMESH_Group`
2584         """
2585
2586         return self.mesh.CreateGroup(elementType, name)
2587
2588     def Group(self, grp, name=""):
2589         """
2590         Create a mesh group based on the geometric object *grp*
2591         and give it a *name*.
2592         If *name* is not defined the name of the geometric group is used
2593
2594         Note:
2595                 Works like :meth:`GroupOnGeom`.
2596
2597         Parameters:
2598                 grp:  a geometric group, a vertex, an edge, a face or a solid
2599                 name: the name of the mesh group
2600
2601         Returns:
2602                 :class:`SMESH.SMESH_GroupOnGeom`
2603         """
2604
2605         return self.GroupOnGeom(grp, name)
2606
2607     def GroupOnGeom(self, grp, name="", typ=None):
2608         """
2609         Create a mesh group based on the geometrical object *grp*
2610         and give it a *name*.
2611         if *name* is not defined the name of the geometric group is used
2612
2613         Parameters:
2614                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2615                 name: the name of the mesh group
2616                 typ:  the type of elements in the group; either of
2617                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2618                         automatically detected by the type of the geometry
2619
2620         Returns:
2621                 :class:`SMESH.SMESH_GroupOnGeom`
2622         """
2623
2624         AssureGeomPublished( self, grp, name )
2625         if name == "":
2626             name = grp.GetName()
2627         if not typ:
2628             typ = self._groupTypeFromShape( grp )
2629         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2630
2631     def _groupTypeFromShape( self, shape ):
2632         """
2633         Pivate method to get a type of group on geometry
2634         """
2635         tgeo = str(shape.GetShapeType())
2636         if tgeo == "VERTEX":
2637             typ = NODE
2638         elif tgeo == "EDGE" or tgeo == "WIRE":
2639             typ = EDGE
2640         elif tgeo == "FACE" or tgeo == "SHELL":
2641             typ = FACE
2642         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2643             typ = VOLUME
2644         elif tgeo == "COMPOUND":
2645             try:
2646               sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2647             except:
2648               # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of
2649               # simplification of access in geomBuilder: omniORB.registerObjref
2650               from SHAPERSTUDY_utils import getEngine
2651               gen = getEngine()
2652               if gen:
2653                 sub = gen.GetIShapesOperations().ExtractSubShapes(shape, self.geompyD.ShapeType["SHAPE"], False)
2654             if not sub:
2655                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2656             return self._groupTypeFromShape( sub[0] )
2657         else:
2658             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2659         return typ
2660
2661     def GroupOnFilter(self, typ, name, filter):
2662         """
2663         Create a mesh group with given *name* based on the *filter*.
2664         It is a special type of group dynamically updating it's contents during
2665         mesh modification
2666
2667         Parameters:
2668                 typ: the type of elements in the group; either of
2669                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2670                 name: the name of the mesh group
2671                 filter (SMESH.Filter): the filter defining group contents
2672
2673         Returns:
2674                 :class:`SMESH.SMESH_GroupOnFilter`
2675         """
2676
2677         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2678
2679     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2680         """
2681         Create a mesh group by the given ids of elements
2682
2683         Parameters:
2684                 groupName: the name of the mesh group
2685                 elementType: the type of elements in the group; either of
2686                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2687                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2688
2689         Returns:
2690                 :class:`SMESH.SMESH_Group`
2691         """
2692
2693         group = self.mesh.CreateGroup(elementType, groupName)
2694         if isinstance( elemIDs, Mesh ):
2695             elemIDs = elemIDs.GetMesh()
2696         if hasattr( elemIDs, "GetIDs" ):
2697             if hasattr( elemIDs, "SetMesh" ):
2698                 elemIDs.SetMesh( self.GetMesh() )
2699             group.AddFrom( elemIDs )
2700         else:
2701             group.Add(elemIDs)
2702         return group
2703
2704     def MakeGroup(self,
2705                   groupName,
2706                   elementType,
2707                   CritType=FT_Undefined,
2708                   Compare=FT_EqualTo,
2709                   Threshold="",
2710                   UnaryOp=FT_Undefined,
2711                   Tolerance=1e-07):
2712         """
2713         Create a mesh group by the given conditions
2714
2715         Parameters:
2716                 groupName: the name of the mesh group
2717                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2718                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2719                         Note that the items starting from FT_LessThan are not suitable for CritType.
2720                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2721                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2722                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2723                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2724                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2725
2726         Returns:
2727                 :class:`SMESH.SMESH_GroupOnFilter`
2728         """
2729
2730         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2731         group = self.MakeGroupByCriterion(groupName, aCriterion)
2732         return group
2733
2734     def MakeGroupByCriterion(self, groupName, Criterion):
2735         """
2736         Create a mesh group by the given criterion
2737
2738         Parameters:
2739                 groupName: the name of the mesh group
2740                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2741
2742         Returns:
2743                 :class:`SMESH.SMESH_GroupOnFilter`
2744
2745         See Also:
2746                 :meth:`smeshBuilder.GetCriterion`
2747         """
2748
2749         return self.MakeGroupByCriteria( groupName, [Criterion] )
2750
2751     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2752         """
2753         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2754
2755         Parameters:
2756                 groupName: the name of the mesh group
2757                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2758                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2759
2760         Returns:
2761                 :class:`SMESH.SMESH_GroupOnFilter`
2762
2763         See Also:
2764                 :meth:`smeshBuilder.GetCriterion`
2765         """
2766
2767         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2768         group = self.MakeGroupByFilter(groupName, aFilter)
2769         return group
2770
2771     def MakeGroupByFilter(self, groupName, theFilter):
2772         """
2773         Create a mesh group by the given filter
2774
2775         Parameters:
2776                 groupName (string): the name of the mesh group
2777                 theFilter (SMESH.Filter): the filter
2778
2779         Returns:
2780                 :class:`SMESH.SMESH_GroupOnFilter`
2781
2782         See Also:
2783                 :meth:`smeshBuilder.GetFilter`
2784         """
2785
2786         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2787         #theFilter.SetMesh( self.mesh )
2788         #group.AddFrom( theFilter )
2789         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2790         return group
2791
2792     def RemoveGroup(self, group):
2793         """
2794         Remove a group
2795
2796         Parameters:
2797                 group (SMESH.SMESH_GroupBase): group to remove
2798         """
2799
2800         self.mesh.RemoveGroup(group)
2801
2802     def RemoveGroupWithContents(self, group):
2803         """
2804         Remove a group with its contents
2805
2806         Parameters:
2807                 group (SMESH.SMESH_GroupBase): group to remove
2808
2809         Note:
2810                 This operation can create gaps in numeration of nodes or elements.
2811                 Call :meth:`RenumberElements` to remove the gaps.
2812         """
2813
2814         self.mesh.RemoveGroupWithContents(group)
2815
2816     def GetGroups(self, elemType = SMESH.ALL):
2817         """
2818         Get the list of groups existing in the mesh in the order of creation 
2819         (starting from the oldest one)
2820
2821         Parameters:
2822                 elemType (SMESH.ElementType): type of elements the groups contain;
2823                         by default groups of elements of all types are returned
2824
2825         Returns:
2826                 a list of :class:`SMESH.SMESH_GroupBase`
2827         """
2828
2829         groups = self.mesh.GetGroups()
2830         if elemType == SMESH.ALL:
2831             return groups
2832         typedGroups = []
2833         for g in groups:
2834             if g.GetType() == elemType:
2835                 typedGroups.append( g )
2836                 pass
2837             pass
2838         return typedGroups
2839
2840     def NbGroups(self):
2841         """
2842         Get the number of groups existing in the mesh
2843
2844         Returns:
2845                 the quantity of groups as an integer value
2846         """
2847
2848         return self.mesh.NbGroups()
2849
2850     def GetGroupNames(self):
2851         """
2852         Get the list of names of groups existing in the mesh
2853
2854         Returns:
2855                 list of strings
2856         """
2857
2858         groups = self.GetGroups()
2859         names = []
2860         for group in groups:
2861             names.append(group.GetName())
2862         return names
2863
2864     def GetGroupByName(self, name, elemType = None):
2865         """
2866         Find groups by name and type
2867
2868         Parameters:
2869                 name (string): name of the group of interest
2870                 elemType (SMESH.ElementType): type of elements the groups contain;
2871                         by default one group of any type is returned;
2872                         if elemType == SMESH.ALL then all groups of any type are returned
2873
2874         Returns:
2875                 a list of :class:`SMESH.SMESH_GroupBase`
2876         """
2877
2878         groups = []
2879         for group in self.GetGroups():
2880             if group.GetName() == name:
2881                 if elemType is None:
2882                     return [group]
2883                 if ( elemType == SMESH.ALL or
2884                      group.GetType() == elemType ):
2885                     groups.append( group )
2886         return groups
2887
2888     def UnionGroups(self, group1, group2, name):
2889         """
2890         Produce a union of two groups.
2891         A new group is created. All mesh elements that are
2892         present in the initial groups are added to the new one
2893
2894         Parameters:
2895            group1 (SMESH.SMESH_GroupBase): a group
2896            group2 (SMESH.SMESH_GroupBase): another group
2897
2898         Returns:
2899                 instance of :class:`SMESH.SMESH_Group`
2900         """
2901
2902         return self.mesh.UnionGroups(group1, group2, name)
2903
2904     def UnionListOfGroups(self, groups, name):
2905         """
2906         Produce a union list of groups.
2907         New group is created. All mesh elements that are present in
2908         initial groups are added to the new one
2909
2910         Parameters:
2911            groups: list of :class:`SMESH.SMESH_GroupBase`
2912
2913         Returns:
2914                 instance of :class:`SMESH.SMESH_Group`
2915         """
2916         return self.mesh.UnionListOfGroups(groups, name)
2917
2918     def IntersectGroups(self, group1, group2, name):
2919         """
2920         Prodice an intersection of two groups.
2921         A new group is created. All mesh elements that are common
2922         for the two initial groups are added to the new one.
2923
2924         Parameters:
2925            group1 (SMESH.SMESH_GroupBase): a group
2926            group2 (SMESH.SMESH_GroupBase): another group
2927
2928         Returns:
2929                 instance of :class:`SMESH.SMESH_Group`
2930         """
2931
2932         return self.mesh.IntersectGroups(group1, group2, name)
2933
2934     def IntersectListOfGroups(self, groups, name):
2935         """
2936         Produce an intersection of groups.
2937         New group is created. All mesh elements that are present in all
2938         initial groups simultaneously are added to the new one
2939
2940         Parameters:
2941            groups: a list of :class:`SMESH.SMESH_GroupBase`
2942
2943         Returns:
2944                 instance of :class:`SMESH.SMESH_Group`
2945         """
2946         return self.mesh.IntersectListOfGroups(groups, name)
2947
2948     def CutGroups(self, main_group, tool_group, name):
2949         """
2950         Produce a cut of two groups.
2951         A new group is created. All mesh elements that are present in
2952         the main group but are not present in the tool group are added to the new one
2953
2954         Parameters:
2955            main_group (SMESH.SMESH_GroupBase): a group to cut from
2956            tool_group (SMESH.SMESH_GroupBase): a group to cut by
2957
2958         Returns:
2959                 an instance of :class:`SMESH.SMESH_Group`
2960         """
2961
2962         return self.mesh.CutGroups(main_group, tool_group, name)
2963
2964     def CutListOfGroups(self, main_groups, tool_groups, name):
2965         """
2966         Produce a cut of groups.
2967         A new group is created. All mesh elements that are present in main groups
2968         but do not present in tool groups are added to the new one
2969
2970         Parameters:
2971            main_group: groups to cut from  (list of :class:`SMESH.SMESH_GroupBase`)
2972            tool_group: groups to cut by    (list of :class:`SMESH.SMESH_GroupBase`)
2973
2974         Returns:
2975                 an instance of :class:`SMESH.SMESH_Group`
2976         """
2977
2978         return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2979
2980     def CreateDimGroup(self, groups, elemType, name,
2981                        nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2982         """
2983         Create a standalone group of entities basing on nodes of other groups.
2984
2985         Parameters:
2986                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
2987                 elemType: a type of elements to include to the new group; either of
2988                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2989                 name: a name of the new group.
2990                 nbCommonNodes: a criterion of inclusion of an element to the new group
2991                         basing on number of element nodes common with reference *groups*.
2992                         Meaning of possible values are:
2993
2994                                 - SMESH.ALL_NODES - include if all nodes are common,
2995                                 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
2996                                 - SMESH.AT_LEAST_ONE - include if one or more node is common,
2997                                 - SMEHS.MAJORITY - include if half of nodes or more are common.
2998                 underlyingOnly: if *True* (default), an element is included to the
2999                         new group provided that it is based on nodes of an element of *groups*;
3000                         in this case the reference *groups* are supposed to be of higher dimension
3001                         than *elemType*, which can be useful for example to get all faces lying on
3002                         volumes of the reference *groups*.
3003
3004         Returns:
3005                 an instance of :class:`SMESH.SMESH_Group`
3006         """
3007
3008         if isinstance( groups, SMESH._objref_SMESH_IDSource ):
3009             groups = [groups]
3010         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
3011
3012     def FaceGroupsSeparatedByEdges( self, sharpAngle, createEdges=False, useExistingEdges=False ):
3013         """
3014         Distribute all faces of the mesh among groups using sharp edges and optionally
3015         existing 1D elements as group boundaries.
3016
3017         Parameters:
3018                 sharpAngle: edge is considered sharp if an angle between normals of
3019                             adjacent faces is more than \a sharpAngle in degrees.
3020                 createEdges (boolean): to create 1D elements for detected sharp edges.
3021                 useExistingEdges (boolean): to use existing edges as group boundaries
3022         Returns:
3023                 ListOfGroups - the created :class:`groups <SMESH.SMESH_Group>`
3024         """
3025         sharpAngle,Parameters,hasVars = ParseParameters( sharpAngle )
3026         self.mesh.SetParameters(Parameters)
3027         return self.mesh.FaceGroupsSeparatedByEdges( sharpAngle, createEdges, useExistingEdges );
3028
3029     def ConvertToStandalone(self, group):
3030         """
3031         Convert group on geom into standalone group
3032         """
3033
3034         return self.mesh.ConvertToStandalone(group)
3035
3036     # Get some info about mesh:
3037     # ------------------------
3038
3039     def GetLog(self, clearAfterGet):
3040         """
3041         Return the log of nodes and elements added or removed
3042         since the previous clear of the log.
3043
3044         Parameters:
3045                 clearAfterGet: log is emptied after Get (safe if concurrents access)
3046
3047         Returns:
3048                 list of SMESH.log_block structures { commandType, number, coords, indexes }
3049         """
3050
3051         return self.mesh.GetLog(clearAfterGet)
3052
3053     def ClearLog(self):
3054         """
3055         Clear the log of nodes and elements added or removed since the previous
3056         clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
3057         """
3058
3059         self.mesh.ClearLog()
3060
3061     def SetAutoColor(self, theAutoColor):
3062         """
3063         Toggle auto color mode on the object.
3064         If switched on, a default color of a new group in Create Group dialog is chosen randomly.
3065
3066         Parameters:
3067                 theAutoColor (boolean): the flag which toggles auto color mode.
3068         """
3069
3070         self.mesh.SetAutoColor(theAutoColor)
3071
3072     def GetAutoColor(self):
3073         """
3074         Get flag of object auto color mode.
3075
3076         Returns:
3077                 True or False
3078         """
3079
3080         return self.mesh.GetAutoColor()
3081
3082     def GetId(self):
3083         """
3084         Get the internal ID
3085
3086         Returns:
3087             integer value, which is the internal Id of the mesh
3088         """
3089
3090         return self.mesh.GetId()
3091
3092     def HasDuplicatedGroupNamesMED(self):
3093         """
3094         Check the group names for duplications.
3095         Consider the maximum group name length stored in MED file.
3096
3097         Returns:
3098             True or False
3099         """
3100
3101         return self.mesh.HasDuplicatedGroupNamesMED()
3102
3103     def GetMeshEditor(self):
3104         """
3105         Obtain the mesh editor tool
3106
3107         Returns:
3108             an instance of :class:`SMESH.SMESH_MeshEditor`
3109         """
3110
3111         return self.editor
3112
3113     def GetIDSource(self, ids, elemType = SMESH.ALL):
3114         """
3115         Wrap a list of IDs of elements or nodes into :class:`SMESH.SMESH_IDSource` which
3116         can be passed as argument to a method accepting :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
3117
3118         Parameters:
3119                 ids: list of IDs
3120                 elemType: type of elements; this parameter is used to distinguish
3121                         IDs of nodes from IDs of elements; by default ids are treated as
3122                         IDs of elements; use SMESH.NODE if ids are IDs of nodes.
3123
3124         Returns:
3125             an instance of :class:`SMESH.SMESH_IDSource`
3126
3127         Warning:
3128                 call UnRegister() for the returned object as soon as it is no more useful::
3129
3130                         idSrc = mesh.GetIDSource( [1,3,5], SMESH.NODE )
3131                         mesh.DoSomething( idSrc )
3132                         idSrc.UnRegister()
3133         """
3134
3135         if isinstance( ids, int ):
3136             ids = [ids]
3137         return self.editor.MakeIDSource(ids, elemType)
3138
3139
3140     # Get information about mesh contents:
3141     # ------------------------------------
3142
3143     def GetMeshInfo(self, obj = None):
3144         """
3145         Get the mesh statistic.
3146
3147         Returns:
3148                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
3149         """
3150
3151         if not obj: obj = self.mesh
3152         return self.smeshpyD.GetMeshInfo(obj)
3153
3154     def NbNodes(self):
3155         """
3156         Return the number of nodes in the mesh
3157
3158         Returns:
3159             an integer value
3160         """
3161
3162         return self.mesh.NbNodes()
3163
3164     def NbElements(self):
3165         """
3166         Return the number of elements in the mesh
3167
3168         Returns:
3169             an integer value
3170         """
3171
3172         return self.mesh.NbElements()
3173
3174     def Nb0DElements(self):
3175         """
3176         Return the number of 0d elements in the mesh
3177
3178         Returns:
3179             an integer value
3180         """
3181
3182         return self.mesh.Nb0DElements()
3183
3184     def NbBalls(self):
3185         """
3186         Return the number of ball discrete elements in the mesh
3187
3188         Returns:
3189             an integer value
3190         """
3191
3192         return self.mesh.NbBalls()
3193
3194     def NbEdges(self):
3195         """
3196         Return the number of edges in the mesh
3197
3198         Returns:
3199             an integer value
3200         """
3201
3202         return self.mesh.NbEdges()
3203
3204     def NbEdgesOfOrder(self, elementOrder):
3205         """
3206         Return the number of edges with the given order in the mesh
3207
3208         Parameters:
3209                 elementOrder: the order of elements
3210                      (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3211
3212         Returns:
3213             an integer value
3214         """
3215
3216         return self.mesh.NbEdgesOfOrder(elementOrder)
3217
3218     def NbFaces(self):
3219         """
3220         Return the number of faces in the mesh
3221
3222         Returns:
3223             an integer value
3224         """
3225
3226         return self.mesh.NbFaces()
3227
3228     def NbFacesOfOrder(self, elementOrder):
3229         """
3230         Return the number of faces with the given order in the mesh
3231
3232         Parameters:
3233                 elementOrder: the order of elements
3234                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3235
3236         Returns:
3237             an integer value
3238         """
3239
3240         return self.mesh.NbFacesOfOrder(elementOrder)
3241
3242     def NbTriangles(self):
3243         """
3244         Return the number of triangles in the mesh
3245
3246         Returns:
3247             an integer value
3248         """
3249
3250         return self.mesh.NbTriangles()
3251
3252     def NbTrianglesOfOrder(self, elementOrder):
3253         """
3254         Return the number of triangles with the given order in the mesh
3255
3256         Parameters:
3257                 elementOrder: is the order of elements
3258                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3259
3260         Returns:
3261             an integer value
3262         """
3263
3264         return self.mesh.NbTrianglesOfOrder(elementOrder)
3265
3266     def NbBiQuadTriangles(self):
3267         """
3268         Return the number of biquadratic triangles in the mesh
3269
3270         Returns:
3271             an integer value
3272         """
3273
3274         return self.mesh.NbBiQuadTriangles()
3275
3276     def NbQuadrangles(self):
3277         """
3278         Return the number of quadrangles in the mesh
3279
3280         Returns:
3281             an integer value
3282         """
3283
3284         return self.mesh.NbQuadrangles()
3285
3286     def NbQuadranglesOfOrder(self, elementOrder):
3287         """
3288         Return the number of quadrangles with the given order in the mesh
3289
3290         Parameters:
3291                 elementOrder: the order of elements
3292                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3293
3294         Returns:
3295             an integer value
3296         """
3297
3298         return self.mesh.NbQuadranglesOfOrder(elementOrder)
3299
3300     def NbBiQuadQuadrangles(self):
3301         """
3302         Return the number of biquadratic quadrangles in the mesh
3303
3304         Returns:
3305             an integer value
3306         """
3307
3308         return self.mesh.NbBiQuadQuadrangles()
3309
3310     def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
3311         """
3312         Return the number of polygons of given order in the mesh
3313
3314         Parameters:
3315                 elementOrder: the order of elements
3316                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3317
3318         Returns:
3319             an integer value
3320         """
3321
3322         return self.mesh.NbPolygonsOfOrder(elementOrder)
3323
3324     def NbVolumes(self):
3325         """
3326         Return the number of volumes in the mesh
3327
3328         Returns:
3329             an integer value
3330         """
3331
3332         return self.mesh.NbVolumes()
3333
3334
3335     def NbVolumesOfOrder(self, elementOrder):
3336         """
3337         Return the number of volumes with the given order in the mesh
3338
3339         Parameters:
3340                 elementOrder:  the order of elements
3341                     (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3342
3343         Returns:
3344             an integer value
3345         """
3346
3347         return self.mesh.NbVolumesOfOrder(elementOrder)
3348
3349     def NbTetras(self):
3350         """
3351         Return the number of tetrahedrons in the mesh
3352
3353         Returns:
3354             an integer value
3355         """
3356
3357         return self.mesh.NbTetras()
3358
3359     def NbTetrasOfOrder(self, elementOrder):
3360         """
3361         Return the number of tetrahedrons with the given order in the mesh
3362
3363         Parameters:
3364                 elementOrder:  the order of elements
3365                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3366
3367         Returns:
3368             an integer value
3369         """
3370
3371         return self.mesh.NbTetrasOfOrder(elementOrder)
3372
3373     def NbHexas(self):
3374         """
3375         Return the number of hexahedrons in the mesh
3376
3377         Returns:
3378             an integer value
3379         """
3380
3381         return self.mesh.NbHexas()
3382
3383     def NbHexasOfOrder(self, elementOrder):
3384         """
3385         Return the number of hexahedrons with the given order in the mesh
3386
3387         Parameters:
3388                 elementOrder:  the order of elements
3389                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3390
3391         Returns:
3392             an integer value
3393         """
3394
3395         return self.mesh.NbHexasOfOrder(elementOrder)
3396
3397     def NbTriQuadraticHexas(self):
3398         """
3399         Return the number of triquadratic hexahedrons in the mesh
3400
3401         Returns:
3402             an integer value
3403         """
3404
3405         return self.mesh.NbTriQuadraticHexas()
3406
3407     def NbPyramids(self):
3408         """
3409         Return the number of pyramids in the mesh
3410
3411         Returns:
3412             an integer value
3413         """
3414
3415         return self.mesh.NbPyramids()
3416
3417     def NbPyramidsOfOrder(self, elementOrder):
3418         """
3419         Return the number of pyramids with the given order in the mesh
3420
3421         Parameters:
3422                 elementOrder:  the order of elements
3423                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3424
3425         Returns:
3426             an integer value
3427         """
3428
3429         return self.mesh.NbPyramidsOfOrder(elementOrder)
3430
3431     def NbPrisms(self):
3432         """
3433         Return the number of prisms in the mesh
3434
3435         Returns:
3436             an integer value
3437         """
3438
3439         return self.mesh.NbPrisms()
3440
3441     def NbPrismsOfOrder(self, elementOrder):
3442         """
3443         Return the number of prisms with the given order in the mesh
3444
3445         Parameters:
3446                 elementOrder:  the order of elements
3447                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3448
3449         Returns:
3450             an integer value
3451         """
3452
3453         return self.mesh.NbPrismsOfOrder(elementOrder)
3454
3455     def NbHexagonalPrisms(self):
3456         """
3457         Return the number of hexagonal prisms in the mesh
3458
3459         Returns:
3460             an integer value
3461         """
3462
3463         return self.mesh.NbHexagonalPrisms()
3464
3465     def NbPolyhedrons(self):
3466         """
3467         Return the number of polyhedrons in the mesh
3468
3469         Returns:
3470             an integer value
3471         """
3472
3473         return self.mesh.NbPolyhedrons()
3474
3475     def NbSubMesh(self):
3476         """
3477         Return the number of submeshes in the mesh
3478
3479         Returns:
3480             an integer value
3481         """
3482
3483         return self.mesh.NbSubMesh()
3484
3485     def GetElementsId(self):
3486         """
3487         Return the list of all mesh elements IDs
3488
3489         Returns:
3490             the list of integer values
3491
3492         See Also:
3493             :meth:`GetElementsByType`
3494         """
3495
3496         return self.mesh.GetElementsId()
3497
3498     def GetElementsByType(self, elementType):
3499         """
3500         Return the list of IDs of mesh elements with the given type
3501
3502         Parameters:
3503                 elementType (SMESH.ElementType):  the required type of elements
3504
3505         Returns:
3506             list of integer values
3507         """
3508
3509         return self.mesh.GetElementsByType(elementType)
3510
3511     def GetNodesId(self):
3512         """
3513         Return the list of mesh nodes IDs
3514
3515         Returns:
3516             the list of integer values
3517         """
3518
3519         return self.mesh.GetNodesId()
3520
3521     # Get the information about mesh elements:
3522     # ------------------------------------
3523
3524     def GetElementType(self, id, iselem=True):
3525         """
3526         Return the type of mesh element or node
3527
3528         Returns:
3529             the value from :class:`SMESH.ElementType` enumeration. 
3530             Return SMESH.ALL if element or node with the given ID does not exist
3531         """
3532
3533         return self.mesh.GetElementType(id, iselem)
3534
3535     def GetElementGeomType(self, id):
3536         """
3537         Return the geometric type of mesh element
3538
3539         Returns:
3540             the value from :class:`SMESH.EntityType` enumeration.
3541         """
3542
3543         return self.mesh.GetElementGeomType(id)
3544
3545     def GetElementShape(self, id):
3546         """
3547         Return the shape type of mesh element
3548
3549         Returns:
3550             the value from :class:`SMESH.GeometryType` enumeration.
3551         """
3552
3553         return self.mesh.GetElementShape(id)
3554
3555     def GetSubMeshElementsId(self, Shape):
3556         """
3557         Return the list of sub-mesh elements IDs
3558
3559         Parameters:
3560                 Shape (GEOM.GEOM_Object): a geom object (sub-shape).
3561                        *Shape* must be the sub-shape of the :meth:`main shape <GetShape>`
3562
3563         Returns:
3564             list of integer values
3565         """
3566
3567         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3568             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3569         else:
3570             ShapeID = Shape
3571         return self.mesh.GetSubMeshElementsId(ShapeID)
3572
3573     def GetSubMeshNodesId(self, Shape, all):
3574         """
3575         Return the list of sub-mesh nodes IDs
3576
3577         Parameters:
3578                 Shape: a geom object (sub-shape).
3579                        *Shape* must be the sub-shape of a :meth:`GetShape`
3580                 all: If True, gives all nodes of sub-mesh elements, otherwise gives only sub-mesh nodes
3581
3582         Returns:
3583             list of integer values
3584         """
3585
3586         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3587             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3588         else:
3589             ShapeID = Shape
3590         return self.mesh.GetSubMeshNodesId(ShapeID, all)
3591
3592     def GetSubMeshElementType(self, Shape):
3593         """
3594         Return type of elements on given shape
3595
3596         Parameters:
3597                 Shape: a geom object (sub-shape).
3598                        *Shape* must be a sub-shape of a ShapeToMesh()
3599
3600         Returns:
3601             :class:`SMESH.ElementType`
3602         """
3603
3604         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3605             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3606         else:
3607             ShapeID = Shape
3608         return self.mesh.GetSubMeshElementType(ShapeID)
3609
3610     def Dump(self):
3611         """
3612         Get the mesh description
3613
3614         Returns:
3615             string value
3616         """
3617
3618         return self.mesh.Dump()
3619
3620
3621     # Get the information about nodes and elements of a mesh by its IDs:
3622     # -----------------------------------------------------------
3623
3624     def GetNodeXYZ(self, id):
3625         """
3626         Get XYZ coordinates of a node.
3627         If there is no node for the given ID - return an empty list
3628
3629         Returns:
3630             list of float values
3631         """
3632
3633         return self.mesh.GetNodeXYZ(id)
3634
3635     def GetNodeInverseElements(self, id, elemType=SMESH.ALL):
3636         """
3637         Return list of IDs of inverse elements for the given node.
3638         If there is no node for the given ID - return an empty list
3639
3640         Parameters:
3641                 id: node ID
3642                 elementType: :class:`type of elements <SMESH.ElementType>` (SMESH.EDGE, SMESH.FACE, SMESH.VOLUME, etc.)
3643
3644         Returns:
3645             list of integer values
3646         """
3647
3648         return self.mesh.GetNodeInverseElements(id,elemType)
3649
3650     def GetNodePosition(self,NodeID):
3651         """
3652         Return the position of a node on the shape
3653
3654         Returns:
3655             :class:`SMESH.NodePosition`
3656         """
3657
3658         return self.mesh.GetNodePosition(NodeID)
3659
3660     def GetElementPosition(self,ElemID):
3661         """
3662         Return the position of an element on the shape
3663
3664         Returns:
3665             :class:`SMESH.ElementPosition`
3666         """
3667
3668         return self.mesh.GetElementPosition(ElemID)
3669
3670     def GetShapeID(self, id):
3671         """
3672         Return the ID of the shape, on which the given node was generated.
3673
3674         Returns:
3675             an integer value > 0 or -1 if there is no node for the given
3676             ID or the node is not assigned to any geometry
3677         """
3678
3679         return self.mesh.GetShapeID(id)
3680
3681     def GetShapeIDForElem(self,id):
3682         """
3683         Return the ID of the shape, on which the given element was generated.
3684
3685         Returns:
3686             an integer value > 0 or -1 if there is no element for the given
3687             ID or the element is not assigned to any geometry
3688         """
3689
3690         return self.mesh.GetShapeIDForElem(id)
3691
3692     def GetElemNbNodes(self, id):
3693         """
3694         Return the number of nodes of the given element
3695
3696         Returns:
3697             an integer value > 0 or -1 if there is no element for the given ID
3698         """
3699
3700         return self.mesh.GetElemNbNodes(id)
3701
3702     def GetElemNode(self, id, index):
3703         """
3704         Return the node ID the given (zero based) index for the given element.
3705
3706         * If there is no element for the given ID - return -1.
3707         * If there is no node for the given index - return -2.
3708
3709         Parameters:
3710             id (int): element ID
3711             index (int): node index within the element
3712
3713         Returns:
3714             an integer value (ID)
3715
3716         See Also:
3717             :meth:`GetElemNodes`
3718         """
3719
3720         return self.mesh.GetElemNode(id, index)
3721
3722     def GetElemNodes(self, id):
3723         """
3724         Return the IDs of nodes of the given element
3725
3726         Returns:
3727             a list of integer values
3728         """
3729
3730         return self.mesh.GetElemNodes(id)
3731
3732     def IsMediumNode(self, elementID, nodeID):
3733         """
3734         Return true if the given node is the medium node in the given quadratic element
3735         """
3736
3737         return self.mesh.IsMediumNode(elementID, nodeID)
3738
3739     def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
3740         """
3741         Return true if the given node is the medium node in one of quadratic elements
3742
3743         Parameters:
3744                 nodeID: ID of the node
3745                 elementType:  the type of elements to check a state of the node, either of
3746                         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
3747         """
3748
3749         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
3750
3751     def ElemNbEdges(self, id):
3752         """
3753         Return the number of edges for the given element
3754         """
3755
3756         return self.mesh.ElemNbEdges(id)
3757
3758     def ElemNbFaces(self, id):
3759         """
3760         Return the number of faces for the given element
3761         """
3762
3763         return self.mesh.ElemNbFaces(id)
3764
3765     def GetElemFaceNodes(self,elemId, faceIndex):
3766         """
3767         Return nodes of given face (counted from zero) for given volumic element.
3768         """
3769
3770         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
3771
3772     def GetFaceNormal(self, faceId, normalized=False):
3773         """
3774         Return three components of normal of given mesh face
3775         (or an empty array in KO case)
3776         """
3777
3778         return self.mesh.GetFaceNormal(faceId,normalized)
3779
3780     def FindElementByNodes(self, nodes):
3781         """
3782         Return an element based on all given nodes.
3783         """
3784
3785         return self.mesh.FindElementByNodes(nodes)
3786
3787     def GetElementsByNodes(self, nodes, elemType=SMESH.ALL):
3788         """
3789         Return elements including all given nodes.
3790         """
3791
3792         return self.mesh.GetElementsByNodes( nodes, elemType )
3793
3794     def IsPoly(self, id):
3795         """
3796         Return true if the given element is a polygon
3797         """
3798
3799         return self.mesh.IsPoly(id)
3800
3801     def IsQuadratic(self, id):
3802         """
3803         Return true if the given element is quadratic
3804         """
3805
3806         return self.mesh.IsQuadratic(id)
3807
3808     def GetBallDiameter(self, id):
3809         """
3810         Return diameter of a ball discrete element or zero in case of an invalid *id*
3811         """
3812
3813         return self.mesh.GetBallDiameter(id)
3814
3815     def BaryCenter(self, id):
3816         """
3817         Return XYZ coordinates of the barycenter of the given element.
3818         If there is no element for the given ID - return an empty list
3819
3820         Returns:
3821             a list of three double values
3822
3823         See also: 
3824                 :meth:`smeshBuilder.GetGravityCenter`
3825         """
3826
3827         return self.mesh.BaryCenter(id)
3828
3829     def GetIdsFromFilter(self, filter, meshParts=[] ):
3830         """
3831         Pass mesh elements through the given filter and return IDs of fitting elements
3832
3833         Parameters:
3834                 filter: :class:`SMESH.Filter`
3835                 meshParts: list of mesh parts (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to filter
3836
3837         Returns:
3838             a list of ids
3839
3840         See Also:
3841             :meth:`SMESH.Filter.GetIDs`
3842             :meth:`SMESH.Filter.GetElementsIdFromParts`
3843         """
3844
3845         filter.SetMesh( self.mesh )
3846
3847         if meshParts:
3848             if isinstance( meshParts, Mesh ):
3849                 filter.SetMesh( meshParts.GetMesh() )
3850                 return theFilter.GetIDs()
3851             if isinstance( meshParts, SMESH._objref_SMESH_IDSource ):
3852                 meshParts = [ meshParts ]
3853             return filter.GetElementsIdFromParts( meshParts )
3854
3855         return filter.GetIDs()
3856
3857     # Get mesh measurements information:
3858     # ------------------------------------
3859
3860     def GetFreeBorders(self):
3861         """
3862         Verify whether a 2D mesh element has free edges (edges connected to one face only).
3863         Return a list of special structures (borders).
3864
3865         Returns:
3866             a list of :class:`SMESH.FreeEdges.Border`
3867         """
3868
3869         aFilterMgr = self.smeshpyD.CreateFilterManager()
3870         aPredicate = aFilterMgr.CreateFreeEdges()
3871         aPredicate.SetMesh(self.mesh)
3872         aBorders = aPredicate.GetBorders()
3873         aFilterMgr.UnRegister()
3874         return aBorders
3875
3876     def MinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3877         """
3878         Get minimum distance between two nodes, elements or distance to the origin
3879
3880         Parameters:
3881                 id1: first node/element id
3882                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3883                 isElem1: *True* if *id1* is element id, *False* if it is node id
3884                 isElem2: *True* if *id2* is element id, *False* if it is node id
3885
3886         Returns:
3887             minimum distance value
3888         See Also:
3889             :meth:`GetMinDistance`
3890         """
3891
3892         aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
3893         return aMeasure.value
3894
3895     def GetMinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3896         """
3897         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
3898
3899         Parameters:
3900                 id1: first node/element id
3901                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3902                 isElem1: *True* if *id1* is element id, *False* if it is node id
3903                 isElem2: *True* if *id2* is element id, *False* if it is node id
3904
3905         Returns:
3906             :class:`SMESH.Measure` structure
3907         See Also:
3908             :meth:`MinDistance`
3909         """
3910
3911         if isElem1:
3912             id1 = self.editor.MakeIDSource([id1], SMESH.FACE)
3913         else:
3914             id1 = self.editor.MakeIDSource([id1], SMESH.NODE)
3915         if id2 != 0:
3916             if isElem2:
3917                 id2 = self.editor.MakeIDSource([id2], SMESH.FACE)
3918             else:
3919                 id2 = self.editor.MakeIDSource([id2], SMESH.NODE)
3920             pass
3921         else:
3922             id2 = None
3923
3924         aMeasurements = self.smeshpyD.CreateMeasurements()
3925         aMeasure = aMeasurements.MinDistance(id1, id2)
3926         genObjUnRegister([aMeasurements,id1, id2])
3927         return aMeasure
3928
3929     def BoundingBox(self, objects=None, isElem=False):
3930         """
3931         Get bounding box of the specified object(s)
3932
3933         Parameters:
3934                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
3935                 isElem: if *objects* is a list of IDs, *True* value in this parameters specifies that *objects* are elements,
3936                         *False* specifies that *objects* are nodes
3937
3938         Returns:
3939             tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
3940
3941         See Also: 
3942             :meth:`GetBoundingBox()`
3943         """
3944
3945         result = self.GetBoundingBox(objects, isElem)
3946         if result is None:
3947             result = (0.0,)*6
3948         else:
3949             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
3950         return result
3951
3952     def GetBoundingBox(self, objects=None, isElem=False):
3953         """
3954         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
3955
3956         Parameters:
3957                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
3958                 isElem: if *objects* is a list of IDs, True means that *objects* are elements,
3959                         False means that *objects* are nodes
3960
3961         Returns:
3962             :class:`SMESH.Measure` structure
3963
3964         See Also: 
3965             :meth:`BoundingBox()`
3966         """
3967
3968         if objects is None:
3969             objects = [self.mesh]
3970         elif isinstance(objects, tuple):
3971             objects = list(objects)
3972         if not isinstance(objects, list):
3973             objects = [objects]
3974         if len(objects) > 0 and isinstance(objects[0], int):
3975             objects = [objects]
3976         srclist = []
3977         unRegister = genObjUnRegister()
3978         for o in objects:
3979             if isinstance(o, Mesh):
3980                 srclist.append(o.mesh)
3981             elif hasattr(o, "_narrow"):
3982                 src = o._narrow(SMESH.SMESH_IDSource)
3983                 if src: srclist.append(src)
3984                 pass
3985             elif isinstance(o, list):
3986                 if isElem:
3987                     srclist.append(self.editor.MakeIDSource(o, SMESH.FACE))
3988                 else:
3989                     srclist.append(self.editor.MakeIDSource(o, SMESH.NODE))
3990                 unRegister.set( srclist[-1] )
3991                 pass
3992             pass
3993         aMeasurements = self.smeshpyD.CreateMeasurements()
3994         unRegister.set( aMeasurements )
3995         aMeasure = aMeasurements.BoundingBox(srclist)
3996         return aMeasure
3997
3998     # Mesh edition (SMESH_MeshEditor functionality):
3999     # ---------------------------------------------
4000
4001     def RemoveElements(self, IDsOfElements):
4002         """
4003         Remove the elements from the mesh by ids
4004
4005         Parameters:
4006                 IDsOfElements: is a list of ids of elements to remove
4007
4008         Returns:
4009             True or False
4010
4011         Note:
4012                 This operation can create gaps in numeration of elements.
4013                 Call :meth:`RenumberElements` to remove the gaps.
4014         """
4015
4016         return self.editor.RemoveElements(IDsOfElements)
4017
4018     def RemoveNodes(self, IDsOfNodes):
4019         """
4020         Remove nodes from mesh by ids
4021
4022         Parameters:
4023                 IDsOfNodes: is a list of ids of nodes to remove
4024
4025         Returns:
4026             True or False
4027
4028         Note:
4029                 This operation can create gaps in numeration of nodes.
4030                 Call :meth:`RenumberElements` to remove the gaps.
4031         """
4032
4033         return self.editor.RemoveNodes(IDsOfNodes)
4034
4035     def RemoveOrphanNodes(self):
4036         """
4037         Remove all orphan (free) nodes from mesh
4038
4039         Returns:
4040             number of the removed nodes
4041
4042         Note:
4043                 This operation can create gaps in numeration of nodes.
4044                 Call :meth:`RenumberElements` to remove the gaps.
4045         """
4046
4047         return self.editor.RemoveOrphanNodes()
4048
4049     def AddNode(self, x, y, z):
4050         """
4051         Add a node to the mesh by coordinates
4052
4053         Returns:
4054             ID of the new node
4055         """
4056
4057         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4058         if hasVars: self.mesh.SetParameters(Parameters)
4059         return self.editor.AddNode( x, y, z)
4060
4061     def Add0DElement( self, IDOfNode, DuplicateElements=True ):
4062         """
4063         Create a 0D element on a node with given number.
4064
4065         Parameters:
4066                 IDOfNode: the ID of node for creation of the element.
4067                 DuplicateElements: to add one more 0D element to a node or not
4068
4069         Returns:
4070             ID of the new 0D element
4071         """
4072
4073         return self.editor.Add0DElement( IDOfNode, DuplicateElements )
4074
4075     def Add0DElementsToAllNodes(self, theObject, theGroupName="", DuplicateElements=False):
4076         """
4077         Create 0D elements on all nodes of the given elements except those
4078         nodes on which a 0D element already exists.
4079
4080         Parameters:
4081                 theObject: an object on whose nodes 0D elements will be created.
4082                         It can be list of element IDs, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4083                 theGroupName: optional name of a group to add 0D elements created
4084                         and/or found on nodes of *theObject*.
4085                 DuplicateElements: to add one more 0D element to a node or not
4086
4087         Returns:
4088             an object (a new group or a temporary :class:`SMESH.SMESH_IDSource`) holding
4089             IDs of new and/or found 0D elements. IDs of 0D elements
4090             can be retrieved from the returned object by 
4091             calling :meth:`GetIDs() <SMESH.SMESH_IDSource.GetIDs>`
4092         """
4093
4094         unRegister = genObjUnRegister()
4095         if isinstance( theObject, Mesh ):
4096             theObject = theObject.GetMesh()
4097         elif isinstance( theObject, list ):
4098             theObject = self.GetIDSource( theObject, SMESH.ALL )
4099             unRegister.set( theObject )
4100         return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName, DuplicateElements )
4101
4102     def AddBall(self, IDOfNode, diameter):
4103         """
4104         Create a ball element on a node with given ID.
4105
4106         Parameters:
4107                 IDOfNode: the ID of node for creation of the element.
4108                 diameter: the bal diameter.
4109
4110         Returns:
4111             ID of the new ball element
4112         """
4113
4114         return self.editor.AddBall( IDOfNode, diameter )
4115
4116     def AddEdge(self, IDsOfNodes):
4117         """
4118         Create a linear or quadratic edge (this is determined
4119         by the number of given nodes).
4120
4121         Parameters:
4122                 IDsOfNodes: list of node IDs for creation of the element.
4123                         The order of nodes in this list should correspond to
4124                         the :ref:`connectivity convention <connectivity_page>`.
4125
4126         Returns:
4127             ID of the new edge
4128         """
4129
4130         return self.editor.AddEdge(IDsOfNodes)
4131
4132     def AddFace(self, IDsOfNodes):
4133         """
4134         Create a linear or quadratic face (this is determined
4135         by the number of given nodes).
4136
4137         Parameters:
4138                 IDsOfNodes: list of node IDs for creation of the element.
4139                         The order of nodes in this list should correspond to
4140                         the :ref:`connectivity convention <connectivity_page>`.
4141
4142         Returns:
4143             ID of the new face
4144         """
4145
4146         return self.editor.AddFace(IDsOfNodes)
4147
4148     def AddPolygonalFace(self, IdsOfNodes):
4149         """
4150         Add a polygonal face defined by a list of node IDs
4151
4152         Parameters:
4153                 IdsOfNodes: the list of node IDs for creation of the element.
4154
4155         Returns:
4156             ID of the new face
4157         """
4158
4159         return self.editor.AddPolygonalFace(IdsOfNodes)
4160
4161     def AddQuadPolygonalFace(self, IdsOfNodes):
4162         """
4163         Add a quadratic polygonal face defined by a list of node IDs
4164
4165         Parameters:
4166                 IdsOfNodes: the list of node IDs for creation of the element;
4167                         corner nodes follow first.
4168
4169         Returns:
4170             ID of the new face
4171         """
4172
4173         return self.editor.AddQuadPolygonalFace(IdsOfNodes)
4174
4175     def AddVolume(self, IDsOfNodes):
4176         """
4177         Create both simple and quadratic volume (this is determined
4178         by the number of given nodes).
4179
4180         Parameters:
4181                 IDsOfNodes: list of node IDs for creation of the element.
4182                         The order of nodes in this list should correspond to
4183                         the :ref:`connectivity convention <connectivity_page>`.
4184
4185         Returns:
4186             ID of the new volumic element
4187         """
4188
4189         return self.editor.AddVolume(IDsOfNodes)
4190
4191     def AddPolyhedralVolume (self, IdsOfNodes, Quantities):
4192         """
4193         Create a volume of many faces, giving nodes for each face.
4194
4195         Parameters:
4196                 IdsOfNodes: list of node IDs for volume creation, face by face.
4197                 Quantities: list of integer values, Quantities[i]
4198                         gives the quantity of nodes in face number i.
4199
4200         Returns:
4201             ID of the new volumic element
4202         """
4203
4204         return self.editor.AddPolyhedralVolume(IdsOfNodes, Quantities)
4205
4206     def AddPolyhedralVolumeByFaces (self, IdsOfFaces):
4207         """
4208         Create a volume of many faces, giving the IDs of the existing faces.
4209
4210         Note:
4211                 The created volume will refer only to the nodes
4212                 of the given faces, not to the faces themselves.
4213
4214         Parameters:
4215                 IdsOfFaces: the list of face IDs for volume creation.
4216
4217         Returns:
4218             ID of the new volumic element
4219         """
4220
4221         return self.editor.AddPolyhedralVolumeByFaces(IdsOfFaces)
4222
4223
4224     def SetNodeOnVertex(self, NodeID, Vertex):
4225         """
4226         Bind a node to a vertex
4227
4228         Parameters:
4229                 NodeID: a node ID
4230                 Vertex: a vertex (GEOM.GEOM_Object) or vertex ID
4231
4232         Returns:
4233             True if succeed else raises an exception
4234         """
4235
4236         if ( isinstance( Vertex, geomBuilder.GEOM._objref_GEOM_Object)):
4237             VertexID = self.geompyD.GetSubShapeID( self.geom, Vertex )
4238         else:
4239             VertexID = Vertex
4240         try:
4241             self.editor.SetNodeOnVertex(NodeID, VertexID)
4242         except SALOME.SALOME_Exception as inst:
4243             raise ValueError(inst.details.text)
4244         return True
4245
4246
4247     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
4248         """
4249         Store the node position on an edge
4250
4251         Parameters:
4252                 NodeID: a node ID
4253                 Edge: an edge (GEOM.GEOM_Object) or edge ID
4254                 paramOnEdge: a parameter on the edge where the node is located
4255
4256         Returns:
4257             True if succeed else raises an exception
4258         """
4259
4260         if ( isinstance( Edge, geomBuilder.GEOM._objref_GEOM_Object)):
4261             EdgeID = self.geompyD.GetSubShapeID( self.geom, Edge )
4262         else:
4263             EdgeID = Edge
4264         try:
4265             self.editor.SetNodeOnEdge(NodeID, EdgeID, paramOnEdge)
4266         except SALOME.SALOME_Exception as inst:
4267             raise ValueError(inst.details.text)
4268         return True
4269
4270     def SetNodeOnFace(self, NodeID, Face, u, v):
4271         """
4272         Store node position on a face
4273
4274         Parameters:
4275                 NodeID: a node ID
4276                 Face: a face (GEOM.GEOM_Object) or face ID
4277                 u: U parameter on the face where the node is located
4278                 v: V parameter on the face where the node is located
4279
4280         Returns:
4281             True if succeed else raises an exception
4282         """
4283
4284         if ( isinstance( Face, geomBuilder.GEOM._objref_GEOM_Object)):
4285             FaceID = self.geompyD.GetSubShapeID( self.geom, Face )
4286         else:
4287             FaceID = Face
4288         try:
4289             self.editor.SetNodeOnFace(NodeID, FaceID, u, v)
4290         except SALOME.SALOME_Exception as inst:
4291             raise ValueError(inst.details.text)
4292         return True
4293
4294     def SetNodeInVolume(self, NodeID, Solid):
4295         """
4296         Bind a node to a solid
4297
4298         Parameters:
4299                 NodeID: a node ID
4300                 Solid:  a solid (GEOM.GEOM_Object) or solid ID
4301
4302         Returns:
4303             True if succeed else raises an exception
4304         """
4305
4306         if ( isinstance( Solid, geomBuilder.GEOM._objref_GEOM_Object)):
4307             SolidID = self.geompyD.GetSubShapeID( self.geom, Solid )
4308         else:
4309             SolidID = Solid
4310         try:
4311             self.editor.SetNodeInVolume(NodeID, SolidID)
4312         except SALOME.SALOME_Exception as inst:
4313             raise ValueError(inst.details.text)
4314         return True
4315
4316     def SetMeshElementOnShape(self, ElementID, Shape):
4317         """
4318         Bind an element to a shape
4319
4320         Parameters:
4321                 ElementID: an element ID
4322                 Shape: a shape (GEOM.GEOM_Object) or shape ID
4323
4324         Returns:
4325             True if succeed else raises an exception
4326         """
4327
4328         if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
4329             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
4330         else:
4331             ShapeID = Shape
4332         try:
4333             self.editor.SetMeshElementOnShape(ElementID, ShapeID)
4334         except SALOME.SALOME_Exception as inst:
4335             raise ValueError(inst.details.text)
4336         return True
4337
4338
4339     def MoveNode(self, NodeID, x, y, z):
4340         """
4341         Move the node with the given id
4342
4343         Parameters:
4344                 NodeID: the id of the node
4345                 x:  a new X coordinate
4346                 y:  a new Y coordinate
4347                 z:  a new Z coordinate
4348
4349         Returns:
4350             True if succeed else False
4351         """
4352
4353         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4354         if hasVars: self.mesh.SetParameters(Parameters)
4355         return self.editor.MoveNode(NodeID, x, y, z)
4356
4357     def MoveClosestNodeToPoint(self, x, y, z, NodeID):
4358         """
4359         Find the node closest to a point and moves it to a point location
4360
4361         Parameters:
4362                 x:  the X coordinate of a point
4363                 y:  the Y coordinate of a point
4364                 z:  the Z coordinate of a point
4365                 NodeID: if specified (>0), the node with this ID is moved,
4366                         otherwise, the node closest to point (*x*, *y*, *z*) is moved
4367
4368         Returns:
4369             the ID of a moved node
4370         """
4371
4372         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4373         if hasVars: self.mesh.SetParameters(Parameters)
4374         return self.editor.MoveClosestNodeToPoint(x, y, z, NodeID)
4375
4376     def FindNodeClosestTo(self, x, y, z):
4377         """
4378         Find the node closest to a point
4379
4380         Parameters:
4381                 x:  the X coordinate of a point
4382                 y:  the Y coordinate of a point
4383                 z:  the Z coordinate of a point
4384
4385         Returns:
4386             the ID of a node
4387         """
4388
4389         return self.editor.FindNodeClosestTo(x, y, z)
4390
4391     def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL, meshPart=None):
4392         """
4393         Find the elements where a point lays IN or ON
4394
4395         Parameters:
4396                 x,y,z (float): coordinates of the point
4397                 elementType (SMESH.ElementType): type of elements to find; SMESH.ALL type
4398                         means elements of any type excluding nodes, discrete and 0D elements.
4399                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to search within
4400
4401         Returns:
4402             list of IDs of found elements
4403         """
4404         if meshPart:
4405             return self.editor.FindAmongElementsByPoint( meshPart, x, y, z, elementType );
4406         else:
4407             return self.editor.FindElementsByPoint(x, y, z, elementType)
4408
4409     def ProjectPoint(self, x,y,z, elementType, meshObject=None):
4410         """
4411         Project a point to a mesh object.
4412         Return ID of an element of given type where the given point is projected
4413         and coordinates of the projection point.
4414         In the case if nothing found, return -1 and []
4415         """
4416         if isinstance( meshObject, Mesh ):
4417             meshObject = meshObject.GetMesh()
4418         if not meshObject:
4419             meshObject = self.GetMesh()
4420         return self.editor.ProjectPoint( x,y,z, elementType, meshObject )
4421
4422     def GetPointState(self, x, y, z):
4423         """
4424         Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
4425         smesh.TopAbs_IN, smesh.TopAbs_OUT, smesh.TopAbs_ON and smesh.TopAbs_UNKNOWN.
4426         UNKNOWN state means that either mesh is wrong or the analysis fails.
4427         """
4428
4429         return self.editor.GetPointState(x, y, z)
4430
4431     def IsManifold(self):
4432         """
4433         Check if a 2D mesh is manifold
4434         """
4435
4436         return self.editor.IsManifold()
4437
4438     def IsCoherentOrientation2D(self):
4439         """
4440         Check if orientation of 2D elements is coherent
4441         """
4442
4443         return self.editor.IsCoherentOrientation2D()
4444
4445     def Get1DBranches( self, edges, startNode = 0 ):
4446         """
4447         Partition given 1D elements into groups of contiguous edges.
4448         A node where number of meeting edges != 2 is a group end.
4449         An optional startNode is used to orient groups it belongs to.
4450
4451         Returns:
4452              A list of edge groups and a list of corresponding node groups,
4453              where the group is a list of IDs of edges or nodes, like follows
4454              [[[branch_edges_1],[branch_edges_2]], [[branch_nodes_1],[branch_nodes_2]]].
4455              If a group is closed, the first and last nodes of the group are same.
4456         """
4457         if isinstance( edges, Mesh ):
4458             edges = edges.GetMesh()
4459         unRegister = genObjUnRegister()
4460         if isinstance( edges, list ):
4461             edges = self.GetIDSource( edges, SMESH.EDGE )
4462             unRegister.set( edges )
4463         return self.editor.Get1DBranches( edges, startNode )
4464     
4465     def FindSharpEdges( self, angle, addExisting=False ):
4466         """
4467         Return sharp edges of faces and non-manifold ones.
4468         Optionally add existing edges.
4469
4470         Parameters:
4471                 angle: angle (in degrees) between normals of adjacent faces to detect sharp edges
4472                 addExisting: to return existing edges (1D elements) as well
4473
4474         Returns:
4475             list of FaceEdge structures
4476         """
4477         angle = ParseParameters( angle )[0]
4478         return self.editor.FindSharpEdges( angle, addExisting )
4479
4480     def MeshToPassThroughAPoint(self, x, y, z):
4481         """
4482         Find the node closest to a point and moves it to a point location
4483
4484         Parameters:
4485                 x:  the X coordinate of a point
4486                 y:  the Y coordinate of a point
4487                 z:  the Z coordinate of a point
4488
4489         Returns:
4490             the ID of a moved node
4491         """
4492
4493         return self.editor.MoveClosestNodeToPoint(x, y, z, -1)
4494
4495     def InverseDiag(self, NodeID1, NodeID2):
4496         """
4497         Replace two neighbour triangles sharing Node1-Node2 link
4498         with the triangles built on the same 4 nodes but having other common link.
4499
4500         Parameters:
4501                 NodeID1:  the ID of the first node
4502                 NodeID2:  the ID of the second node
4503
4504         Returns:
4505             False if proper faces were not found
4506         """
4507         return self.editor.InverseDiag(NodeID1, NodeID2)
4508
4509     def DeleteDiag(self, NodeID1, NodeID2):
4510         """
4511         Replace two neighbour triangles sharing *Node1-Node2* link
4512         with a quadrangle built on the same 4 nodes.
4513
4514         Parameters:
4515                 NodeID1: ID of the first node
4516                 NodeID2: ID of the second node
4517
4518         Returns:
4519             False if proper faces were not found
4520
4521         Note:
4522                 This operation can create gaps in numeration of elements.
4523                 Call :meth:`RenumberElements` to remove the gaps.
4524         """
4525
4526         return self.editor.DeleteDiag(NodeID1, NodeID2)
4527
4528     def Reorient(self, IDsOfElements=None):
4529         """
4530         Reorient elements by ids
4531
4532         Parameters:
4533                 IDsOfElements: if undefined reorients all mesh elements
4534
4535         Returns:
4536             True if succeed else False
4537         """
4538
4539         if IDsOfElements == None:
4540             IDsOfElements = self.GetElementsId()
4541         return self.editor.Reorient(IDsOfElements)
4542
4543     def ReorientObject(self, theObject):
4544         """
4545         Reorient all elements of the object
4546
4547         Parameters:
4548                 theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4549
4550         Returns:
4551             True if succeed else False
4552         """
4553
4554         if ( isinstance( theObject, Mesh )):
4555             theObject = theObject.GetMesh()
4556         return self.editor.ReorientObject(theObject)
4557
4558     def Reorient2D(self, the2DObject, theDirection, theFaceOrPoint ):
4559         """
4560         Reorient faces contained in *the2DObject*.
4561
4562         Parameters:
4563                 the2DObject: a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` or list of IDs of 2D elements
4564                 theDirection: a desired direction of normal of *theFace*.
4565                         It can be either a GEOM vector or a list of coordinates [x,y,z].
4566                 theFaceOrPoint: defines a face of *the2DObject* whose normal will be
4567                         compared with theDirection. It can be either ID of face or a point
4568                         by which the face will be found. The point can be given as either
4569                         a GEOM vertex or a list of point coordinates.
4570
4571         Returns:
4572             number of reoriented faces
4573         """
4574
4575         unRegister = genObjUnRegister()
4576         # check the2DObject
4577         if isinstance( the2DObject, Mesh ):
4578             the2DObject = the2DObject.GetMesh()
4579         if isinstance( the2DObject, list ):
4580             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4581             unRegister.set( the2DObject )
4582         # check theDirection
4583         if isinstance( theDirection, geomBuilder.GEOM._objref_GEOM_Object):
4584             theDirection = self.smeshpyD.GetDirStruct( theDirection )
4585         if isinstance( theDirection, list ):
4586             theDirection = self.smeshpyD.MakeDirStruct( *theDirection  )
4587         # prepare theFace and thePoint
4588         theFace = theFaceOrPoint
4589         thePoint = PointStruct(0,0,0)
4590         if isinstance( theFaceOrPoint, geomBuilder.GEOM._objref_GEOM_Object):
4591             thePoint = self.smeshpyD.GetPointStruct( theFaceOrPoint )
4592             theFace = -1
4593         if isinstance( theFaceOrPoint, list ):
4594             thePoint = PointStruct( *theFaceOrPoint )
4595             theFace = -1
4596         if isinstance( theFaceOrPoint, PointStruct ):
4597             thePoint = theFaceOrPoint
4598             theFace = -1
4599         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
4600
4601     def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
4602         """
4603         Reorient faces according to adjacent volumes.
4604
4605         Parameters:
4606                 the2DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of
4607                         either IDs of faces or face groups.
4608                 the3DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of IDs of volumes.
4609                 theOutsideNormal: to orient faces to have their normals
4610                         pointing either *outside* or *inside* the adjacent volumes.
4611
4612         Returns:
4613             number of reoriented faces.
4614         """
4615
4616         unRegister = genObjUnRegister()
4617         # check the2DObject
4618         if not isinstance( the2DObject, list ):
4619             the2DObject = [ the2DObject ]
4620         elif the2DObject and isinstance( the2DObject[0], int ):
4621             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4622             unRegister.set( the2DObject )
4623             the2DObject = [ the2DObject ]
4624         for i,obj2D in enumerate( the2DObject ):
4625             if isinstance( obj2D, Mesh ):
4626                 the2DObject[i] = obj2D.GetMesh()
4627             if isinstance( obj2D, list ):
4628                 the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
4629                 unRegister.set( the2DObject[i] )
4630         # check the3DObject
4631         if isinstance( the3DObject, Mesh ):
4632             the3DObject = the3DObject.GetMesh()
4633         if isinstance( the3DObject, list ):
4634             the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
4635             unRegister.set( the3DObject )
4636         return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
4637
4638     def TriToQuad(self, IDsOfElements, theCriterion, MaxAngle):
4639         """
4640         Fuse the neighbouring triangles into quadrangles.
4641
4642         Parameters:
4643                 IDsOfElements: The triangles to be fused.
4644                 theCriterion:  a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4645                         applied to possible quadrangles to choose a neighbour to fuse with.
4646                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4647                         to numerical functors.
4648                 MaxAngle: is the maximum angle between element normals at which the fusion
4649                         is still performed; theMaxAngle is measured in radians.
4650                         Also it could be a name of variable which defines angle in degrees.
4651
4652         Returns:
4653             True in case of success, False otherwise.
4654
4655         Note:
4656                 This operation can create gaps in numeration of elements.
4657                 Call :meth:`RenumberElements` to remove the gaps.
4658         """
4659
4660         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4661         self.mesh.SetParameters(Parameters)
4662         if not IDsOfElements:
4663             IDsOfElements = self.GetElementsId()
4664         Functor = self.smeshpyD.GetFunctor(theCriterion)
4665         return self.editor.TriToQuad(IDsOfElements, Functor, MaxAngle)
4666
4667     def TriToQuadObject (self, theObject, theCriterion, MaxAngle):
4668         """
4669         Fuse the neighbouring triangles of the object into quadrangles
4670
4671         Parameters:
4672                 theObject: is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4673                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`,
4674                         applied to possible quadrangles to choose a neighbour to fuse with.
4675                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4676                         to numerical functors.
4677                 MaxAngle: a max angle between element normals at which the fusion
4678                         is still performed; theMaxAngle is measured in radians.
4679
4680         Returns:
4681             True in case of success, False otherwise.
4682
4683         Note:
4684                 This operation can create gaps in numeration of elements.
4685                 Call :meth:`RenumberElements` to remove the gaps.
4686         """
4687
4688         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4689         self.mesh.SetParameters(Parameters)
4690         if isinstance( theObject, Mesh ):
4691             theObject = theObject.GetMesh()
4692         Functor = self.smeshpyD.GetFunctor(theCriterion)
4693         return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
4694
4695     def QuadToTri (self, IDsOfElements, theCriterion = None):
4696         """
4697         Split quadrangles into triangles.
4698
4699         Parameters:
4700                 IDsOfElements: the faces to be splitted.
4701                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4702                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4703                         value, then quadrangles will be split by the smallest diagonal.
4704                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4705                         to numerical functors.
4706
4707         Returns:
4708             True in case of success, False otherwise.
4709
4710         Note:
4711                 This operation can create gaps in numeration of elements.
4712                 Call :meth:`RenumberElements` to remove the gaps.
4713         """
4714         if IDsOfElements == []:
4715             IDsOfElements = self.GetElementsId()
4716         if theCriterion is None:
4717             theCriterion = FT_MaxElementLength2D
4718         Functor = self.smeshpyD.GetFunctor(theCriterion)
4719         return self.editor.QuadToTri(IDsOfElements, Functor)
4720
4721     def QuadToTriObject (self, theObject, theCriterion = None):
4722         """
4723         Split quadrangles into triangles.
4724
4725         Parameters:
4726                 theObject: the object from which the list of elements is taken,
4727                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4728                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4729                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4730                         value, then quadrangles will be split by the smallest diagonal.
4731                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4732                         to numerical functors.
4733
4734         Returns:
4735             True in case of success, False otherwise.
4736
4737         Note:
4738                 This operation can create gaps in numeration of elements.
4739                 Call :meth:`RenumberElements` to remove the gaps.
4740         """
4741         if ( isinstance( theObject, Mesh )):
4742             theObject = theObject.GetMesh()
4743         if theCriterion is None:
4744             theCriterion = FT_MaxElementLength2D
4745         Functor = self.smeshpyD.GetFunctor(theCriterion)
4746         return self.editor.QuadToTriObject(theObject, Functor)
4747
4748     def QuadTo4Tri (self, theElements=[]):
4749         """
4750         Split each of given quadrangles into 4 triangles. A node is added at the center of
4751         a quadrangle.
4752
4753         Parameters:
4754                 theElements: the faces to be splitted. This can be either 
4755                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
4756                         or a list of face IDs. By default all quadrangles are split
4757
4758         Note:
4759                 This operation can create gaps in numeration of elements.
4760                 Call :meth:`RenumberElements` to remove the gaps.
4761         """
4762         unRegister = genObjUnRegister()
4763         if isinstance( theElements, Mesh ):
4764             theElements = theElements.mesh
4765         elif not theElements:
4766             theElements = self.mesh
4767         elif isinstance( theElements, list ):
4768             theElements = self.GetIDSource( theElements, SMESH.FACE )
4769             unRegister.set( theElements )
4770         return self.editor.QuadTo4Tri( theElements )
4771
4772     def SplitQuad (self, IDsOfElements, Diag13):
4773         """
4774         Split quadrangles into triangles.
4775
4776         Parameters:
4777                 IDsOfElements: the faces to be splitted
4778                 Diag13 (boolean):        is used to choose a diagonal for splitting.
4779
4780         Returns:
4781             True in case of success, False otherwise.
4782
4783         Note:
4784                 This operation can create gaps in numeration of elements.
4785                 Call :meth:`RenumberElements` to remove the gaps.
4786         """
4787         if IDsOfElements == []:
4788             IDsOfElements = self.GetElementsId()
4789         return self.editor.SplitQuad(IDsOfElements, Diag13)
4790
4791     def SplitQuadObject (self, theObject, Diag13):
4792         """
4793         Split quadrangles into triangles.
4794
4795         Parameters:
4796                 theObject: the object from which the list of elements is taken,
4797                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4798                 Diag13 (boolean):    is used to choose a diagonal for splitting.
4799
4800         Returns:
4801             True in case of success, False otherwise.
4802
4803         Note:
4804                 This operation can create gaps in numeration of elements.
4805                 Call :meth:`RenumberElements` to remove the gaps.
4806         """
4807         if ( isinstance( theObject, Mesh )):
4808             theObject = theObject.GetMesh()
4809         return self.editor.SplitQuadObject(theObject, Diag13)
4810
4811     def BestSplit (self, IDOfQuad, theCriterion):
4812         """
4813         Find a better splitting of the given quadrangle.
4814
4815         Parameters:
4816                 IDOfQuad:   the ID of the quadrangle to be splitted.
4817                 theCriterion:  is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4818                         choose a diagonal for splitting.
4819                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4820                         to numerical functors.
4821
4822         Returns:
4823             * 1 if 1-3 diagonal is better, 
4824             * 2 if 2-4 diagonal is better, 
4825             * 0 if error occurs.
4826
4827         Note:
4828                 This operation can create gaps in numeration of elements.
4829                 Call :meth:`RenumberElements` to remove the gaps.
4830         """
4831         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
4832
4833     def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
4834         """
4835         Split volumic elements into tetrahedrons
4836
4837         Parameters:
4838                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4839                 method:  flags passing splitting method:
4840                         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
4841                         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
4842
4843         Note:
4844                 This operation can create gaps in numeration of elements.
4845                 Call :meth:`RenumberElements` to remove the gaps.
4846         """
4847         unRegister = genObjUnRegister()
4848         if isinstance( elems, Mesh ):
4849             elems = elems.GetMesh()
4850         if ( isinstance( elems, list )):
4851             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4852             unRegister.set( elems )
4853         self.editor.SplitVolumesIntoTetra(elems, method)
4854         return
4855
4856     def SplitBiQuadraticIntoLinear(self, elems=None):
4857         """
4858         Split bi-quadratic elements into linear ones without creation of additional nodes:
4859
4860             - bi-quadratic triangle will be split into 3 linear quadrangles;
4861             - bi-quadratic quadrangle will be split into 4 linear quadrangles;
4862             - tri-quadratic hexahedron will be split into 8 linear hexahedra.
4863
4864         Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
4865         will be split in order to keep the mesh conformal.
4866
4867         Parameters:
4868             elems: elements to split\: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or element IDs;
4869                 if None (default), all bi-quadratic elements will be split
4870
4871         Note:
4872                 This operation can create gaps in numeration of elements.
4873                 Call :meth:`RenumberElements` to remove the gaps.
4874         """
4875         unRegister = genObjUnRegister()
4876         if elems and isinstance( elems, list ) and isinstance( elems[0], int ):
4877             elems = self.editor.MakeIDSource(elems, SMESH.ALL)
4878             unRegister.set( elems )
4879         if elems is None:
4880             elems = [ self.GetMesh() ]
4881         if isinstance( elems, Mesh ):
4882             elems = [ elems.GetMesh() ]
4883         if not isinstance( elems, list ):
4884             elems = [elems]
4885         self.editor.SplitBiQuadraticIntoLinear( elems )
4886
4887     def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
4888                                  method=smeshBuilder.Hex_2Prisms, allDomains=False ):
4889         """
4890         Split hexahedra into prisms
4891
4892         Parameters:
4893                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4894                 startHexPoint: a point used to find a hexahedron for which *facetNormal*
4895                         gives a normal vector defining facets to split into triangles.
4896                         *startHexPoint* can be either a triple of coordinates or a vertex.
4897                 facetNormal: a normal to a facet to split into triangles of a
4898                         hexahedron found by *startHexPoint*.
4899                         *facetNormal* can be either a triple of coordinates or an edge.
4900                 method:  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
4901                         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
4902                 allDomains: if :code:`False`, only hexahedra adjacent to one closest
4903                         to *startHexPoint* are split, else *startHexPoint*
4904                         is used to find the facet to split in all domains present in *elems*.
4905
4906         Note:
4907                 This operation can create gaps in numeration of elements.
4908                 Call :meth:`RenumberElements` to remove the gaps.
4909         """
4910         # IDSource
4911         unRegister = genObjUnRegister()
4912         if isinstance( elems, Mesh ):
4913             elems = elems.GetMesh()
4914         if ( isinstance( elems, list )):
4915             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4916             unRegister.set( elems )
4917             pass
4918         # axis
4919         if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
4920             startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
4921         elif isinstance( startHexPoint, list ):
4922             startHexPoint = SMESH.PointStruct( startHexPoint[0],
4923                                                startHexPoint[1],
4924                                                startHexPoint[2])
4925         if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
4926             facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
4927         elif isinstance( facetNormal, list ):
4928             facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
4929                                                        facetNormal[1],
4930                                                        facetNormal[2])
4931         self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
4932
4933         self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
4934
4935     def SplitQuadsNearTriangularFacets(self):
4936         """
4937         Split quadrangle faces near triangular facets of volumes
4938
4939         Note:
4940                 This operation can create gaps in numeration of elements.
4941                 Call :meth:`RenumberElements` to remove the gaps.
4942         """
4943         faces_array = self.GetElementsByType(SMESH.FACE)
4944         for face_id in faces_array:
4945             if self.GetElemNbNodes(face_id) == 4: # quadrangle
4946                 quad_nodes = self.mesh.GetElemNodes(face_id)
4947                 node1_elems = self.GetNodeInverseElements(quad_nodes[1 -1])
4948                 isVolumeFound = False
4949                 for node1_elem in node1_elems:
4950                     if not isVolumeFound:
4951                         if self.GetElementType(node1_elem, True) == SMESH.VOLUME:
4952                             nb_nodes = self.GetElemNbNodes(node1_elem)
4953                             if 3 < nb_nodes and nb_nodes < 7: # tetra or penta, or prism
4954                                 volume_elem = node1_elem
4955                                 volume_nodes = self.mesh.GetElemNodes(volume_elem)
4956                                 if volume_nodes.count(quad_nodes[2 -1]) > 0: # 1,2
4957                                     if volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,2,4
4958                                         isVolumeFound = True
4959                                         if volume_nodes.count(quad_nodes[3 -1]) == 0: # 1,2,4 & !3
4960                                             self.SplitQuad([face_id], False) # diagonal 2-4
4961                                     elif volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,2,3 & !4
4962                                         isVolumeFound = True
4963                                         self.SplitQuad([face_id], True) # diagonal 1-3
4964                                 elif volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,4 & !2
4965                                     if volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,4,3 & !2
4966                                         isVolumeFound = True
4967                                         self.SplitQuad([face_id], True) # diagonal 1-3
4968
4969     def SplitHexaToTetras (self, theObject, theNode000, theNode001):
4970         """
4971         Split hexahedrons into tetrahedrons.
4972
4973         This operation uses :doc:`pattern_mapping` functionality for splitting.
4974
4975         Parameters:
4976                 theObject: the object from which the list of hexahedrons is taken; 
4977                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4978                 theNode000,theNode001: within the range [0,7]; gives the orientation of the
4979                         pattern relatively each hexahedron: the (0,0,0) key-point of the pattern
4980                         will be mapped into *theNode000*-th node of each volume, the (0,0,1)
4981                         key-point will be mapped into *theNode001*-th node of each volume.
4982                         The (0,0,0) key-point of the used pattern corresponds to a non-split corner.
4983
4984         Returns:
4985             True in case of success, False otherwise.
4986
4987         Note:
4988                 This operation can create gaps in numeration of elements.
4989                 Call :meth:`RenumberElements` to remove the gaps.
4990         """
4991 #    Pattern:
4992 #                     5.---------.6
4993 #                    /|#*      /|
4994 #                   / | #*    / |
4995 #                  /  |  # * /  |
4996 #                 /   |   # /*  |
4997 #       (0,0,1) 4.---------.7 * |
4998 #                |#*  |1   | # *|
4999 #                | # *.----|---#.2
5000 #                |  #/ *   |   /
5001 #                |  /#  *  |  /
5002 #                | /   # * | /
5003 #                |/      #*|/
5004 #        (0,0,0) 0.---------.3
5005         pattern_tetra = "!!! Nb of points: \n 8 \n\
5006         !!! Points: \n\
5007         0 0 0  !- 0 \n\
5008         0 1 0  !- 1 \n\
5009         1 1 0  !- 2 \n\
5010         1 0 0  !- 3 \n\
5011         0 0 1  !- 4 \n\
5012         0 1 1  !- 5 \n\
5013         1 1 1  !- 6 \n\
5014         1 0 1  !- 7 \n\
5015         !!! Indices of points of 6 tetras: \n\
5016         0 3 4 1 \n\
5017         7 4 3 1 \n\
5018         4 7 5 1 \n\
5019         6 2 5 7 \n\
5020         1 5 2 7 \n\
5021         2 3 1 7 \n"
5022
5023         pattern = self.smeshpyD.GetPattern()
5024         isDone  = pattern.LoadFromFile(pattern_tetra)
5025         if not isDone:
5026             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
5027             return isDone
5028
5029         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
5030         isDone = pattern.MakeMesh(self.mesh, False, False)
5031         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
5032
5033         # split quafrangle faces near triangular facets of volumes
5034         self.SplitQuadsNearTriangularFacets()
5035
5036         return isDone
5037
5038     def SplitHexaToPrisms (self, theObject, theNode000, theNode001):
5039         """
5040         Split hexahedrons into prisms.
5041
5042         Uses the :doc:`pattern_mapping` functionality for splitting.
5043
5044         Parameters:
5045                 theObject: the object (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`) from where the list of hexahedrons is taken;
5046                 theNode000,theNode001: (within the range [0,7]) gives the orientation of the
5047                         pattern relatively each hexahedron: keypoint (0,0,0) of the pattern
5048                         will be mapped into the *theNode000* -th node of each volume, keypoint (0,0,1)
5049                         will be mapped into the *theNode001* -th node of each volume.
5050                         Edge (0,0,0)-(0,0,1) of used pattern connects two not split corners.
5051
5052         Returns:
5053             True in case of success, False otherwise.
5054
5055         Note:
5056                 This operation can create gaps in numeration of elements.
5057                 Call :meth:`RenumberElements` to remove the gaps.
5058         """
5059 #        Pattern:     5.---------.6
5060 #                     /|#       /|
5061 #                    / | #     / |
5062 #                   /  |  #   /  |
5063 #                  /   |   # /   |
5064 #        (0,0,1) 4.---------.7   |
5065 #                 |    |    |    |
5066 #                 |   1.----|----.2
5067 #                 |   / *   |   /
5068 #                 |  /   *  |  /
5069 #                 | /     * | /
5070 #                 |/       *|/
5071 #        (0,0,0) 0.---------.3
5072         pattern_prism = "!!! Nb of points: \n 8 \n\
5073         !!! Points: \n\
5074         0 0 0  !- 0 \n\
5075         0 1 0  !- 1 \n\
5076         1 1 0  !- 2 \n\
5077         1 0 0  !- 3 \n\
5078         0 0 1  !- 4 \n\
5079         0 1 1  !- 5 \n\
5080         1 1 1  !- 6 \n\
5081         1 0 1  !- 7 \n\
5082         !!! Indices of points of 2 prisms: \n\
5083         0 1 3 4 5 7 \n\
5084         2 3 1 6 7 5 \n"
5085
5086         pattern = self.smeshpyD.GetPattern()
5087         isDone  = pattern.LoadFromFile(pattern_prism)
5088         if not isDone:
5089             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
5090             return isDone
5091
5092         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
5093         isDone = pattern.MakeMesh(self.mesh, False, False)
5094         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
5095
5096         # Split quafrangle faces near triangular facets of volumes
5097         self.SplitQuadsNearTriangularFacets()
5098
5099         return isDone
5100
5101     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
5102                MaxNbOfIterations, MaxAspectRatio, Method):
5103         """
5104         Smooth elements
5105
5106         Parameters:
5107                 IDsOfElements: the list if ids of elements to smooth
5108                 IDsOfFixedNodes: the list of ids of fixed nodes.
5109                         Note that nodes built on edges and boundary nodes are always fixed.
5110                 MaxNbOfIterations: the maximum number of iterations
5111                 MaxAspectRatio: varies in range [1.0, inf]
5112                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5113                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5114
5115         Returns:
5116             True in case of success, False otherwise.
5117         """
5118
5119         if IDsOfElements == []:
5120             IDsOfElements = self.GetElementsId()
5121         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
5122         self.mesh.SetParameters(Parameters)
5123         return self.editor.Smooth(IDsOfElements, IDsOfFixedNodes,
5124                                   MaxNbOfIterations, MaxAspectRatio, Method)
5125
5126     def SmoothObject(self, theObject, IDsOfFixedNodes,
5127                      MaxNbOfIterations, MaxAspectRatio, Method):
5128         """
5129         Smooth elements which belong to the given object
5130
5131         Parameters:
5132                 theObject: the object to smooth
5133                 IDsOfFixedNodes: the list of ids of fixed nodes.
5134                         Note that nodes built on edges and boundary nodes are always fixed.
5135                 MaxNbOfIterations: the maximum number of iterations
5136                 MaxAspectRatio: varies in range [1.0, inf]
5137                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5138                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5139
5140         Returns:
5141             True in case of success, False otherwise.
5142         """
5143
5144         if ( isinstance( theObject, Mesh )):
5145             theObject = theObject.GetMesh()
5146         return self.editor.SmoothObject(theObject, IDsOfFixedNodes,
5147                                         MaxNbOfIterations, MaxAspectRatio, Method)
5148
5149     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
5150                          MaxNbOfIterations, MaxAspectRatio, Method):
5151         """
5152         Parametrically smooth the given elements
5153
5154         Parameters:
5155                 IDsOfElements: the list if ids of elements to smooth
5156                 IDsOfFixedNodes: the list of ids of fixed nodes.
5157                         Note that nodes built on edges and boundary nodes are always fixed.
5158                 MaxNbOfIterations: the maximum number of iterations
5159                 MaxAspectRatio: varies in range [1.0, inf]
5160                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5161                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5162
5163         Returns:
5164             True in case of success, False otherwise.
5165         """
5166
5167         if IDsOfElements == []:
5168             IDsOfElements = self.GetElementsId()
5169         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
5170         self.mesh.SetParameters(Parameters)
5171         return self.editor.SmoothParametric(IDsOfElements, IDsOfFixedNodes,
5172                                             MaxNbOfIterations, MaxAspectRatio, Method)
5173
5174     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
5175                                MaxNbOfIterations, MaxAspectRatio, Method):
5176         """
5177         Parametrically smooth the elements which belong to the given object
5178
5179         Parameters:
5180                 theObject: the object to smooth
5181                 IDsOfFixedNodes: the list of ids of fixed nodes.
5182                         Note that nodes built on edges and boundary nodes are always fixed.
5183                 MaxNbOfIterations: the maximum number of iterations
5184                 MaxAspectRatio: varies in range [1.0, inf]
5185                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
5186                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
5187
5188         Returns:
5189             True in case of success, False otherwise.
5190         """
5191
5192         if ( isinstance( theObject, Mesh )):
5193             theObject = theObject.GetMesh()
5194         return self.editor.SmoothParametricObject(theObject, IDsOfFixedNodes,
5195                                                   MaxNbOfIterations, MaxAspectRatio, Method)
5196
5197     def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
5198         """
5199         Convert the mesh to quadratic or bi-quadratic, deletes old elements, replacing
5200         them with quadratic with the same id.
5201
5202         Parameters:
5203                 theForce3d: method of new node creation:
5204
5205                   * False - the medium node lies at the geometrical entity from which the mesh element is built
5206                   * True - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
5207                 theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
5208                 theToBiQuad: If True, converts the mesh to bi-quadratic
5209
5210         Returns:
5211             :class:`SMESH.ComputeError` which can hold a warning
5212
5213         Warning:
5214             If *theSubMesh* is provided, the mesh can become non-conformal
5215
5216         Note:
5217                 This operation can create gaps in numeration of nodes or elements.
5218                 Call :meth:`RenumberElements` to remove the gaps.
5219         """
5220
5221         if isinstance( theSubMesh, Mesh ):
5222             theSubMesh = theSubMesh.mesh
5223         if theToBiQuad:
5224             self.editor.ConvertToBiQuadratic(theForce3d,theSubMesh)
5225         else:
5226             if theSubMesh:
5227                 self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
5228             else:
5229                 self.editor.ConvertToQuadratic(theForce3d)
5230         error = self.editor.GetLastError()
5231         if error and error.comment:
5232             print(error.comment)
5233         return error
5234
5235     def ConvertFromQuadratic(self, theSubMesh=None):
5236         """
5237         Convert the mesh from quadratic to ordinary,
5238         deletes old quadratic elements,
5239         replacing them with ordinary mesh elements with the same id.
5240
5241         Parameters:
5242             theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
5243
5244         Warning:
5245             If *theSubMesh* is provided, the mesh can become non-conformal
5246
5247         Note:
5248                 This operation can create gaps in numeration of nodes or elements.
5249                 Call :meth:`RenumberElements` to remove the gaps.
5250         """
5251
5252         if theSubMesh:
5253             self.editor.ConvertFromQuadraticObject(theSubMesh)
5254         else:
5255             return self.editor.ConvertFromQuadratic()
5256
5257     def Make2DMeshFrom3D(self):
5258         """
5259         Create 2D mesh as skin on boundary faces of a 3D mesh
5260
5261         Returns:
5262             True if operation has been completed successfully, False otherwise
5263         """
5264
5265         return self.editor.Make2DMeshFrom3D()
5266
5267     def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
5268                          toCopyElements=False, toCopyExistingBondary=False):
5269         """
5270         Create missing boundary elements
5271
5272         Parameters:
5273                 elements: elements whose boundary is to be checked:
5274                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of elements.
5275                         If *elements* is mesh, it must be the mesh whose MakeBoundaryMesh() is called
5276                 dimension: defines type of boundary elements to create, either of
5277                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }.
5278                         SMESH.BND_1DFROM3D create mesh edges on all borders of free facets of 3D cells
5279                 groupName: a name of group to store created boundary elements in,
5280                         "" means not to create the group
5281                 meshName: a name of new mesh to store created boundary elements in,
5282                         "" means not to create the new mesh
5283                 toCopyElements: if True, the checked elements will be copied into
5284                         the new mesh else only boundary elements will be copied into the new mesh
5285                 toCopyExistingBondary: if True, not only new but also pre-existing
5286                         boundary elements will be copied into the new mesh
5287
5288         Returns:
5289             tuple (:class:`Mesh`, :class:`group <SMESH.SMESH_Group>`) where boundary elements were added to
5290         """
5291
5292         unRegister = genObjUnRegister()
5293         if isinstance( elements, Mesh ):
5294             elements = elements.GetMesh()
5295         if ( isinstance( elements, list )):
5296             elemType = SMESH.ALL
5297             if elements: elemType = self.GetElementType( elements[0], iselem=True)
5298             elements = self.editor.MakeIDSource(elements, elemType)
5299             unRegister.set( elements )
5300         mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName,
5301                                                    toCopyElements,toCopyExistingBondary)
5302         if mesh: mesh = self.smeshpyD.Mesh(mesh)
5303         return mesh, group
5304
5305     def MakeBoundaryElements(self, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
5306                              toCopyAll=False, groups=[]):
5307         """
5308         Create missing boundary elements around either the whole mesh or
5309         groups of elements
5310
5311         Parameters:
5312                 dimension: defines type of boundary elements to create, either of
5313                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
5314                 groupName: a name of group to store all boundary elements in,
5315                         "" means not to create the group
5316                 meshName: a name of a new mesh, which is a copy of the initial
5317                         mesh + created boundary elements; "" means not to create the new mesh
5318                 toCopyAll: if True, the whole initial mesh will be copied into
5319                         the new mesh else only boundary elements will be copied into the new mesh
5320                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` of elements to make boundary around
5321
5322         Returns:
5323                 tuple( long, mesh, group )
5324                        - long - number of added boundary elements
5325                        - mesh - the :class:`Mesh` where elements were added to
5326                        - group - the :class:`group <SMESH.SMESH_Group>` of boundary elements or None
5327         """
5328
5329         nb, mesh, group = self.editor.MakeBoundaryElements(dimension,groupName,meshName,
5330                                                            toCopyAll,groups)
5331         if mesh: mesh = self.smeshpyD.Mesh(mesh)
5332         return nb, mesh, group
5333
5334     def RenumberNodes(self):
5335         """
5336         Renumber mesh nodes to remove unused node IDs
5337         """
5338         self.editor.RenumberNodes()
5339
5340     def RenumberElements(self):
5341         """
5342         Renumber mesh elements to remove unused element IDs
5343         """
5344         self.editor.RenumberElements()
5345
5346     def _getIdSourceList(self, arg, idType, unRegister):
5347         """
5348         Private method converting *arg* into a list of :class:`SMESH.SMESH_IDSource`
5349         """
5350         if arg and isinstance( arg, list ):
5351             if isinstance( arg[0], int ):
5352                 arg = self.GetIDSource( arg, idType )
5353                 unRegister.set( arg )
5354             elif isinstance( arg[0], Mesh ):
5355                 arg[0] = arg[0].GetMesh()
5356         elif isinstance( arg, Mesh ):
5357             arg = arg.GetMesh()
5358         if arg and isinstance( arg, SMESH._objref_SMESH_IDSource ):
5359             arg = [arg]
5360         return arg
5361
5362     def RotationSweepObjects(self, nodes, edges, faces, Axis, AngleInRadians, NbOfSteps, Tolerance,
5363                              MakeGroups=False, TotalAngle=False):
5364         """
5365         Generate new elements by rotation of the given elements and nodes around the axis
5366
5367         Parameters:
5368                 nodes: nodes to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5369                 edges: edges to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5370                 faces: faces to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5371                 Axis: the axis of rotation: :class:`SMESH.AxisStruct`, line (geom object) or [x,y,z,dx,dy,dz]
5372                 AngleInRadians: the angle of Rotation (in radians) or a name of variable
5373                         which defines angle in degrees
5374                 NbOfSteps: the number of steps
5375                 Tolerance: tolerance
5376                 MakeGroups: forces the generation of new groups from existing ones
5377                 TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5378                         of all steps, else - size of each step
5379
5380         Returns:
5381             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5382         """
5383
5384         unRegister = genObjUnRegister()
5385         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5386         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5387         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5388
5389         if isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object):
5390             Axis = self.smeshpyD.GetAxisStruct( Axis )
5391         if isinstance( Axis, list ):
5392             Axis = SMESH.AxisStruct( *Axis )
5393
5394         AngleInRadians,AngleParameters,hasVars = ParseAngles(AngleInRadians)
5395         NbOfSteps,Tolerance,Parameters,hasVars = ParseParameters(NbOfSteps,Tolerance)
5396         Parameters = Axis.parameters + var_separator + AngleParameters + var_separator + Parameters
5397         self.mesh.SetParameters(Parameters)
5398         if TotalAngle and NbOfSteps:
5399             AngleInRadians /= NbOfSteps
5400         return self.editor.RotationSweepObjects( nodes, edges, faces,
5401                                                  Axis, AngleInRadians,
5402                                                  NbOfSteps, Tolerance, MakeGroups)
5403
5404     def RotationSweep(self, IDsOfElements, Axis, AngleInRadians, NbOfSteps, Tolerance,
5405                       MakeGroups=False, TotalAngle=False):
5406         """
5407         Generate new elements by rotation of the elements around the axis
5408
5409         Parameters:
5410             IDsOfElements: the list of ids of elements to sweep
5411             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5412             AngleInRadians: the angle of Rotation (in radians) or a name of variable which defines angle in degrees
5413             NbOfSteps: the number of steps
5414             Tolerance: tolerance
5415             MakeGroups: forces the generation of new groups from existing ones
5416             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5417                 of all steps, else - size of each step
5418
5419         Returns:
5420             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5421         """
5422
5423         return self.RotationSweepObjects([], IDsOfElements, IDsOfElements, Axis,
5424                                          AngleInRadians, NbOfSteps, Tolerance,
5425                                          MakeGroups, TotalAngle)
5426
5427     def RotationSweepObject(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5428                             MakeGroups=False, TotalAngle=False):
5429         """
5430         Generate new elements by rotation of the elements of object around the axis
5431         theObject object which elements should be sweeped.
5432         It can be a mesh, a sub mesh or a group.
5433
5434         Parameters:
5435             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5436             AngleInRadians: the angle of Rotation
5437             NbOfSteps: number of steps
5438             Tolerance: tolerance
5439             MakeGroups: forces the generation of new groups from existing ones
5440             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5441                 of all steps, else - size of each step
5442
5443         Returns:
5444             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5445         """
5446
5447         return self.RotationSweepObjects( [], theObject, theObject, Axis,
5448                                           AngleInRadians, NbOfSteps, Tolerance,
5449                                           MakeGroups, TotalAngle )
5450
5451     def RotationSweepObject1D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5452                               MakeGroups=False, TotalAngle=False):
5453         """
5454         Generate new elements by rotation of the elements of object around the axis
5455         theObject object which elements should be sweeped.
5456         It can be a mesh, a sub mesh or a group.
5457
5458         Parameters:
5459             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5460             AngleInRadians: the angle of Rotation
5461             NbOfSteps: number of steps
5462             Tolerance: tolerance
5463             MakeGroups: forces the generation of new groups from existing ones
5464             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5465                 of all steps, else - size of each step
5466
5467         Returns:
5468             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, 
5469             empty list otherwise
5470         """
5471
5472         return self.RotationSweepObjects([],theObject,[], Axis,
5473                                          AngleInRadians, NbOfSteps, Tolerance,
5474                                          MakeGroups, TotalAngle)
5475
5476     def RotationSweepObject2D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5477                               MakeGroups=False, TotalAngle=False):
5478         """
5479         Generate new elements by rotation of the elements of object around the axis
5480         theObject object which elements should be sweeped.
5481         It can be a mesh, a sub mesh or a group.
5482
5483         Parameters:
5484             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5485             AngleInRadians: the angle of Rotation
5486             NbOfSteps: number of steps
5487             Tolerance: tolerance
5488             MakeGroups: forces the generation of new groups from existing ones
5489             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5490                 of all steps, else - size of each step
5491
5492         Returns:
5493             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5494         """
5495
5496         return self.RotationSweepObjects([],[],theObject, Axis, AngleInRadians,
5497                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
5498
5499     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
5500                               scaleFactors=[], linearVariation=False, basePoint=[],
5501                               angles=[], anglesVariation=False):
5502         """
5503         Generate new elements by extrusion of the given elements and nodes
5504
5505         Parameters:
5506             nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5507             edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5508             faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5509             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5510                 the direction and value of extrusion for one step (the total extrusion
5511                 length will be NbOfSteps * ||StepVector||)
5512             NbOfSteps: the number of steps
5513             MakeGroups: forces the generation of new groups from existing ones
5514             scaleFactors: optional scale factors to apply during extrusion
5515             linearVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
5516                 else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
5517             basePoint: optional scaling and rotation center; if not provided, a gravity center of
5518                 nodes and elements being extruded is used as the scaling center.
5519                 It can be either
5520
5521                         - a list of tree components of the point or
5522                         - a node ID or
5523                         - a GEOM point
5524             angles: list of angles in radians. Nodes at each extrusion step are rotated 
5525                 around *basePoint*, additionally to previous steps.
5526             anglesVariation: forces the computation of rotation angles as linear
5527                 variation of the given *angles* along path steps
5528         Returns:
5529             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5530
5531         Example: :ref:`tui_extrusion`
5532         """
5533         unRegister = genObjUnRegister()
5534         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5535         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5536         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5537
5538         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5539             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5540         if isinstance( StepVector, list ):
5541             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5542
5543         if isinstance( basePoint, int):
5544             xyz = self.GetNodeXYZ( basePoint )
5545             if not xyz:
5546                 raise RuntimeError("Invalid node ID: %s" % basePoint)
5547             basePoint = xyz
5548         if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ):
5549             basePoint = self.geompyD.PointCoordinates( basePoint )
5550
5551         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
5552         scaleFactors,scaleParameters,hasVars = ParseParameters(scaleFactors)
5553         angles,angleParameters,hasVars = ParseAngles(angles)
5554         Parameters = StepVector.PS.parameters + var_separator + \
5555                      Parameters + var_separator + \
5556                      scaleParameters + var_separator + angleParameters
5557         self.mesh.SetParameters(Parameters)
5558
5559         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
5560                                                   StepVector, NbOfSteps, MakeGroups,
5561                                                   scaleFactors, linearVariation, basePoint,
5562                                                   angles, anglesVariation )
5563
5564
5565     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
5566         """
5567         Generate new elements by extrusion of the elements with given ids
5568
5569         Parameters:
5570             IDsOfElements: the list of ids of elements or nodes for extrusion
5571             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5572                 the direction and value of extrusion for one step (the total extrusion
5573                 length will be NbOfSteps * ||StepVector||)
5574             NbOfSteps: the number of steps
5575             MakeGroups: forces the generation of new groups from existing ones
5576             IsNodes: is True if elements with given ids are nodes
5577
5578         Returns:
5579             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5580
5581         Example: :ref:`tui_extrusion`
5582         """
5583         n,e,f = [],[],[]
5584         if IsNodes: n = IDsOfElements
5585         else      : e,f, = IDsOfElements,IDsOfElements
5586         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5587
5588     def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
5589                           ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
5590         """
5591         Generate new elements by extrusion along the normal to a discretized surface or wire
5592
5593         Parameters:
5594             Elements: elements to extrude - a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`.
5595                 Only faces can be extruded so far. A sub-mesh should be a sub-mesh on geom faces.
5596             StepSize: length of one extrusion step (the total extrusion
5597                 length will be *NbOfSteps* *StepSize*).
5598             NbOfSteps: number of extrusion steps.
5599             ByAverageNormal: if True each node is translated by *StepSize*
5600                 along the average of the normal vectors to the faces sharing the node;
5601                 else each node is translated along the same average normal till
5602                 intersection with the plane got by translation of the face sharing
5603                 the node along its own normal by *StepSize*.
5604             UseInputElemsOnly: to use only *Elements* when computing extrusion direction
5605                 for every node of *Elements*.
5606             MakeGroups: forces generation of new groups from existing ones.
5607             Dim: dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
5608                 is not yet implemented. This parameter is used if *Elements* contains
5609                 both faces and edges, i.e. *Elements* is a Mesh.
5610
5611         Returns:
5612             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
5613             empty list otherwise.
5614         Example: :ref:`tui_extrusion`
5615         """
5616
5617         unRegister = genObjUnRegister()
5618         if isinstance( Elements, Mesh ):
5619             Elements = [ Elements.GetMesh() ]
5620         if isinstance( Elements, list ):
5621             if not Elements:
5622                 raise RuntimeError("Elements empty!")
5623             if isinstance( Elements[0], Mesh ):
5624                 Elements = [ Elements[0].GetMesh() ]
5625             if isinstance( Elements[0], int ):
5626                 Elements = self.GetIDSource( Elements, SMESH.ALL )
5627                 unRegister.set( Elements )
5628         if not isinstance( Elements, list ):
5629             Elements = [ Elements ]
5630         StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
5631         self.mesh.SetParameters(Parameters)
5632         return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
5633                                              ByAverageNormal, UseInputElemsOnly, MakeGroups, Dim)
5634
5635     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
5636         """
5637         Generate new elements by extrusion of the elements or nodes which belong to the object
5638
5639         Parameters:
5640             theObject: the object whose elements or nodes should be processed.
5641                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5642             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5643                 the direction and value of extrusion for one step (the total extrusion
5644                 length will be NbOfSteps * ||StepVector||)
5645             NbOfSteps: the number of steps
5646             MakeGroups: forces the generation of new groups from existing ones
5647             IsNodes: is True if elements to extrude are nodes
5648
5649         Returns:
5650             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5651         Example: :ref:`tui_extrusion`
5652         """
5653
5654         n,e,f = [],[],[]
5655         if IsNodes: n    = theObject
5656         else      : e,f, = theObject,theObject
5657         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5658
5659     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5660         """
5661         Generate new elements by extrusion of edges which belong to the object
5662
5663         Parameters:
5664             theObject: object whose 1D elements should be processed.
5665                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5666             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5667                 the direction and value of extrusion for one step (the total extrusion
5668                 length will be NbOfSteps * ||StepVector||)
5669             NbOfSteps: the number of steps
5670             MakeGroups: to generate new groups from existing ones
5671
5672         Returns:
5673             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5674         Example: :ref:`tui_extrusion`
5675         """
5676
5677         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
5678
5679     def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5680         """
5681         Generate new elements by extrusion of faces which belong to the object
5682
5683         Parameters:
5684             theObject: object whose 2D elements should be processed.
5685                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5686             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5687                 the direction and value of extrusion for one step (the total extrusion
5688                 length will be NbOfSteps * ||StepVector||)
5689             NbOfSteps: the number of steps
5690             MakeGroups: forces the generation of new groups from existing ones
5691
5692         Returns:
5693             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5694         Example: :ref:`tui_extrusion`
5695         """
5696
5697         return self.ExtrusionSweepObjects([],[],theObject, StepVector, NbOfSteps, MakeGroups)
5698
5699     def AdvancedExtrusion(self, IDsOfElements, StepVector, NbOfSteps,
5700                           ExtrFlags, SewTolerance, MakeGroups=False):
5701         """
5702         Generate new elements by extrusion of the elements with given ids
5703
5704         Parameters:
5705             IDsOfElements: is ids of elements
5706             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5707                 the direction and value of extrusion for one step (the total extrusion
5708                 length will be NbOfSteps * ||StepVector||)
5709             NbOfSteps: the number of steps
5710             ExtrFlags: sets flags for extrusion
5711             SewTolerance: uses for comparing locations of nodes if flag
5712                 EXTRUSION_FLAG_SEW is set
5713             MakeGroups: forces the generation of new groups from existing ones
5714
5715         Returns:
5716             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5717         """
5718
5719         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5720             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5721         if isinstance( StepVector, list ):
5722             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5723         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
5724                                              ExtrFlags, SewTolerance, MakeGroups)
5725
5726     def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathObject, PathShape=None,
5727                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
5728                                   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
5729                                   ScaleFactors=[], ScalesVariation=False):
5730         """
5731         Generate new elements by extrusion of the given elements and nodes along the path.
5732         The path of extrusion must be a meshed edge.
5733
5734         Parameters:
5735             Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5736             Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5737             Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5738             PathObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` containing edges along which proceeds the extrusion
5739             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
5740             NodeStart: the first or the last node on the path. Defines the direction of extrusion
5741             HasAngles: not used obsolete
5742             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5743                 around *basePoint*, additionally to previous steps.
5744             LinearVariation: forces the computation of rotation angles as linear
5745                 variation of the given Angles along path steps
5746             HasRefPoint: allows using the reference point
5747             RefPoint: optional scaling and rotation center (mass center of the extruded
5748                 elements by default). The User can specify any point as the Reference Point. 
5749                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5750             MakeGroups: forces the generation of new groups from existing ones
5751             ScaleFactors: optional scale factors to apply during extrusion
5752             ScalesVariation: if *True*, *scaleFactors* are spread over all *NbOfSteps*,
5753                 else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
5754
5755         Returns:
5756             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5757             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5758         Example: :ref:`tui_extrusion_along_path`
5759         """
5760
5761         unRegister = genObjUnRegister()
5762         Nodes = self._getIdSourceList( Nodes, SMESH.NODE, unRegister )
5763         Edges = self._getIdSourceList( Edges, SMESH.EDGE, unRegister )
5764         Faces = self._getIdSourceList( Faces, SMESH.FACE, unRegister )
5765
5766         if isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object):
5767             RefPoint = self.smeshpyD.GetPointStruct(RefPoint)
5768         if isinstance( RefPoint, list ):
5769             if not RefPoint: RefPoint = [0,0,0]
5770             RefPoint = SMESH.PointStruct( *RefPoint )
5771         if isinstance( PathObject, Mesh ):
5772             PathObject = PathObject.GetMesh()
5773         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
5774         ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors)
5775         Parameters = AnglesParameters + var_separator + \
5776                      RefPoint.parameters + var_separator + ScalesParameters 
5777         self.mesh.SetParameters(Parameters)
5778         return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces,
5779                                                      PathObject, PathShape, NodeStart,
5780                                                      HasAngles, Angles, LinearVariation,
5781                                                      HasRefPoint, RefPoint, MakeGroups,
5782                                                      ScaleFactors, ScalesVariation)
5783
5784     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
5785                             HasAngles=False, Angles=[], LinearVariation=False,
5786                             HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
5787                             ElemType=SMESH.FACE):
5788         """
5789         Generate new elements by extrusion of the given elements.
5790         The path of extrusion must be a meshed edge.
5791
5792         Parameters:
5793             Base: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`, or list of ids of elements for extrusion
5794             Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
5795             NodeStart: the start node from Path. Defines the direction of extrusion
5796             HasAngles: not used obsolete
5797             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5798                 around *basePoint*, additionally to previous steps.
5799             LinearVariation: forces the computation of rotation angles as linear
5800                 variation of the given Angles along path steps
5801             HasRefPoint: allows using the reference point
5802             RefPoint: the reference point around which the elements are rotated (the mass
5803                 center of the elements by default).
5804                 The User can specify any point as the Reference Point.
5805                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5806             MakeGroups: forces the generation of new groups from existing ones
5807             ElemType: type of elements for extrusion (if param Base is a mesh)
5808
5809         Returns:
5810             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5811             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5812             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5813             otherwise
5814         Example: :ref:`tui_extrusion_along_path`
5815         """
5816
5817         n,e,f = [],[],[]
5818         if ElemType == SMESH.NODE: n = Base
5819         if ElemType == SMESH.EDGE: e = Base
5820         if ElemType == SMESH.FACE: f = Base
5821         gr,er = self.ExtrusionAlongPathObjects(n,e,f, Path, None, NodeStart,
5822                                                HasAngles, Angles, LinearVariation,
5823                                                HasRefPoint, RefPoint, MakeGroups)
5824         if MakeGroups: return gr,er
5825         return er
5826
5827     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
5828                            HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5829                            MakeGroups=False, LinearVariation=False):
5830         """
5831         Generate new elements by extrusion of the given elements.
5832         The path of extrusion must be a meshed edge.
5833
5834         Parameters:
5835             IDsOfElements: ids of elements
5836             PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
5837             PathShape: shape (edge) defines the sub-mesh for the path
5838             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5839             HasAngles: not used obsolete
5840             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5841                 around *basePoint*, additionally to previous steps.
5842             HasRefPoint: allows using the reference point
5843             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5844                 The User can specify any point as the Reference Point.
5845                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5846             MakeGroups: forces the generation of new groups from existing ones
5847             LinearVariation: forces the computation of rotation angles as linear
5848                 variation of the given Angles along path steps
5849
5850         Returns:
5851             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5852             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5853             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5854         Example: :ref:`tui_extrusion_along_path`
5855         """
5856
5857         if not IDsOfElements:
5858             IDsOfElements = [ self.GetMesh() ]
5859         n,e,f = [],IDsOfElements,IDsOfElements
5860         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape,
5861                                                NodeStart, HasAngles, Angles,
5862                                                LinearVariation,
5863                                                HasRefPoint, RefPoint, MakeGroups)
5864         if MakeGroups: return gr,er
5865         return er
5866
5867     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
5868                                  HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5869                                  MakeGroups=False, LinearVariation=False):
5870         """
5871         Generate new elements by extrusion of the elements which belong to the object.
5872         The path of extrusion must be a meshed edge.
5873
5874         Parameters:
5875             theObject: the object whose elements should be processed.
5876                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5877             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5878             PathShape: shape (edge) defines the sub-mesh for the path
5879             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5880             HasAngles: not used obsolete
5881             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5882                 around *basePoint*, additionally to previous steps.
5883             HasRefPoint: allows using the reference point
5884             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5885                 The User can specify any point as the Reference Point.
5886                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5887             MakeGroups: forces the generation of new groups from existing ones
5888             LinearVariation: forces the computation of rotation angles as linear
5889                 variation of the given Angles along path steps
5890
5891         Returns:
5892             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5893             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5894             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5895         Example: :ref:`tui_extrusion_along_path`
5896         """
5897
5898         n,e,f = [],theObject,theObject
5899         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5900                                                HasAngles, Angles, LinearVariation,
5901                                                HasRefPoint, RefPoint, MakeGroups)
5902         if MakeGroups: return gr,er
5903         return er
5904
5905     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
5906                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5907                                    MakeGroups=False, LinearVariation=False):
5908         """
5909         Generate new elements by extrusion of mesh segments which belong to the object.
5910         The path of extrusion must be a meshed edge.
5911
5912         Parameters:
5913             theObject: the object whose 1D elements should be processed.
5914                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5915             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5916             PathShape: shape (edge) defines the sub-mesh for the path
5917             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5918             HasAngles: not used obsolete
5919             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5920                 around *basePoint*, additionally to previous steps.
5921             HasRefPoint: allows using the reference point
5922             RefPoint:  the reference point around which the shape is rotated (the mass center of the shape by default).
5923                 The User can specify any point as the Reference Point.
5924                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5925             MakeGroups: forces the generation of new groups from existing ones
5926             LinearVariation: forces the computation of rotation angles as linear
5927                 variation of the given Angles along path steps
5928
5929         Returns:
5930             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5931             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5932             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5933         Example: :ref:`tui_extrusion_along_path`
5934         """
5935
5936         n,e,f = [],theObject,[]
5937         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5938                                                HasAngles, Angles, LinearVariation,
5939                                                HasRefPoint, RefPoint, MakeGroups)
5940         if MakeGroups: return gr,er
5941         return er
5942
5943     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
5944                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5945                                    MakeGroups=False, LinearVariation=False):
5946         """
5947         Generate new elements by extrusion of faces which belong to the object.
5948         The path of extrusion must be a meshed edge.
5949
5950         Parameters:
5951             theObject: the object whose 2D elements should be processed.
5952                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5953             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5954             PathShape: shape (edge) defines the sub-mesh for the path
5955             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5956             HasAngles: not used obsolete
5957             Angles: list of angles in radians. Nodes at each extrusion step are rotated 
5958                 around *basePoint*, additionally to previous steps.
5959             HasRefPoint: allows using the reference point
5960             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5961                 The User can specify any point as the Reference Point.
5962                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5963             MakeGroups: forces the generation of new groups from existing ones
5964             LinearVariation: forces the computation of rotation angles as linear
5965                 variation of the given Angles along path steps
5966
5967         Returns:
5968             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5969             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5970             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5971         Example: :ref:`tui_extrusion_along_path`
5972         """
5973
5974         n,e,f = [],[],theObject
5975         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5976                                                HasAngles, Angles, LinearVariation,
5977                                                HasRefPoint, RefPoint, MakeGroups)
5978         if MakeGroups: return gr,er
5979         return er
5980
5981     def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
5982         """
5983         Create a symmetrical copy of mesh elements
5984
5985         Parameters:
5986             IDsOfElements: list of elements ids
5987             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
5988             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
5989                 If the *Mirror* is a geom object this parameter is unnecessary
5990             Copy: allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
5991             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5992
5993         Returns:
5994             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5995         """
5996
5997         if IDsOfElements == []:
5998             IDsOfElements = self.GetElementsId()
5999         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6000             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6001             theMirrorType = Mirror._mirrorType
6002         else:
6003             self.mesh.SetParameters(Mirror.parameters)
6004         if Copy and MakeGroups:
6005             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
6006         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
6007         return []
6008
6009     def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
6010         """
6011         Create a new mesh by a symmetrical copy of mesh elements
6012
6013         Parameters:
6014             IDsOfElements: the list of elements ids
6015             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6016             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6017                 If the *Mirror* is a geom object this parameter is unnecessary
6018             MakeGroups: to generate new groups from existing ones
6019             NewMeshName: a name of the new mesh to create
6020
6021         Returns:
6022             instance of class :class:`Mesh`
6023         """
6024
6025         if IDsOfElements == []:
6026             IDsOfElements = self.GetElementsId()
6027         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6028             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6029             theMirrorType = Mirror._mirrorType
6030         else:
6031             self.mesh.SetParameters(Mirror.parameters)
6032         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
6033                                           MakeGroups, NewMeshName)
6034         return Mesh(self.smeshpyD,self.geompyD,mesh)
6035
6036     def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
6037         """
6038         Create a symmetrical copy of the object
6039
6040         Parameters:
6041             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6042             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6043             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6044                 If the *Mirror* is a geom object this parameter is unnecessary
6045             Copy: allows copying the element (Copy==True) or replacing it with its mirror (Copy==False)
6046             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6047
6048         Returns:
6049             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6050         """
6051
6052         if ( isinstance( theObject, Mesh )):
6053             theObject = theObject.GetMesh()
6054         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6055             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6056             theMirrorType = Mirror._mirrorType
6057         else:
6058             self.mesh.SetParameters(Mirror.parameters)
6059         if Copy and MakeGroups:
6060             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
6061         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
6062         return []
6063
6064     def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
6065         """
6066         Create a new mesh by a symmetrical copy of the object
6067
6068         Parameters:
6069             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6070             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
6071             theMirrorType: smesh.POINT, smesh.AXIS or smesh.PLANE.
6072                 If the *Mirror* is a geom object this parameter is unnecessary
6073             MakeGroups: forces the generation of new groups from existing ones
6074             NewMeshName: the name of the new mesh to create
6075
6076         Returns:
6077             instance of class :class:`Mesh`
6078         """
6079
6080         if ( isinstance( theObject, Mesh )):
6081             theObject = theObject.GetMesh()
6082         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
6083             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
6084             theMirrorType = Mirror._mirrorType
6085         else:
6086             self.mesh.SetParameters(Mirror.parameters)
6087         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
6088                                                 MakeGroups, NewMeshName)
6089         return Mesh( self.smeshpyD,self.geompyD,mesh )
6090
6091     def Translate(self, IDsOfElements, Vector, Copy, MakeGroups=False):
6092         """
6093         Translate the elements
6094
6095         Parameters:
6096             IDsOfElements: list of elements ids
6097             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
6098             Copy: allows copying the translated elements
6099             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6100
6101         Returns:
6102             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6103         """
6104
6105         if IDsOfElements == []:
6106             IDsOfElements = self.GetElementsId()
6107         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6108             Vector = self.smeshpyD.GetDirStruct(Vector)
6109         if isinstance( Vector, list ):
6110             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6111         self.mesh.SetParameters(Vector.PS.parameters)
6112         if Copy and MakeGroups:
6113             return self.editor.TranslateMakeGroups(IDsOfElements, Vector)
6114         self.editor.Translate(IDsOfElements, Vector, Copy)
6115         return []
6116
6117     def TranslateMakeMesh(self, IDsOfElements, Vector, MakeGroups=False, NewMeshName=""):
6118         """
6119         Create a new mesh of translated elements
6120
6121         Parameters:
6122             IDsOfElements: list of elements ids
6123             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
6124             MakeGroups: forces the generation of new groups from existing ones
6125             NewMeshName: the name of the newly created mesh
6126
6127         Returns:
6128             instance of class :class:`Mesh`
6129         """
6130
6131         if IDsOfElements == []:
6132             IDsOfElements = self.GetElementsId()
6133         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6134             Vector = self.smeshpyD.GetDirStruct(Vector)
6135         if isinstance( Vector, list ):
6136             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6137         self.mesh.SetParameters(Vector.PS.parameters)
6138         mesh = self.editor.TranslateMakeMesh(IDsOfElements, Vector, MakeGroups, NewMeshName)
6139         return Mesh ( self.smeshpyD, self.geompyD, mesh )
6140
6141     def TranslateObject(self, theObject, Vector, Copy, MakeGroups=False):
6142         """
6143         Translate the object
6144
6145         Parameters:
6146             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6147             Vector: direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
6148             Copy: allows copying the translated elements
6149             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6150
6151         Returns:
6152             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6153         """
6154
6155         if ( isinstance( theObject, Mesh )):
6156             theObject = theObject.GetMesh()
6157         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
6158             Vector = self.smeshpyD.GetDirStruct(Vector)
6159         if isinstance( Vector, list ):
6160             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6161         self.mesh.SetParameters(Vector.PS.parameters)
6162         if Copy and MakeGroups:
6163             return self.editor.TranslateObjectMakeGroups(theObject, Vector)
6164         self.editor.TranslateObject(theObject, Vector, Copy)
6165         return []
6166
6167     def TranslateObjectMakeMesh(self, theObject, Vector, MakeGroups=False, NewMeshName=""):
6168         """
6169         Create a new mesh from the translated object
6170
6171         Parameters:
6172             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6173             Vector: the direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
6174             MakeGroups: forces the generation of new groups from existing ones
6175             NewMeshName: the name of the newly created mesh
6176
6177         Returns:
6178             instance of class :class:`Mesh`
6179         """
6180
6181         if isinstance( theObject, Mesh ):
6182             theObject = theObject.GetMesh()
6183         if isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object ):
6184             Vector = self.smeshpyD.GetDirStruct(Vector)
6185         if isinstance( Vector, list ):
6186             Vector = self.smeshpyD.MakeDirStruct(*Vector)
6187         self.mesh.SetParameters(Vector.PS.parameters)
6188         mesh = self.editor.TranslateObjectMakeMesh(theObject, Vector, MakeGroups, NewMeshName)
6189         return Mesh( self.smeshpyD, self.geompyD, mesh )
6190
6191
6192
6193     def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False):
6194         """
6195         Scale the object
6196
6197         Parameters:
6198             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6199             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
6200             theScaleFact: list of 1-3 scale factors for axises
6201             Copy: allows copying the translated elements
6202             MakeGroups: forces the generation of new groups from existing
6203                 ones (if Copy)
6204
6205         Returns:
6206             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
6207             empty list otherwise
6208         """
6209         unRegister = genObjUnRegister()
6210         if ( isinstance( theObject, Mesh )):
6211             theObject = theObject.GetMesh()
6212         if ( isinstance( theObject, list )):
6213             theObject = self.GetIDSource(theObject, SMESH.ALL)
6214             unRegister.set( theObject )
6215         if ( isinstance( thePoint, list )):
6216             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
6217         if ( isinstance( theScaleFact, float )):
6218             theScaleFact = [theScaleFact]
6219         if ( isinstance( theScaleFact, int )):
6220             theScaleFact = [ float(theScaleFact)]
6221
6222         self.mesh.SetParameters(thePoint.parameters)
6223
6224         if Copy and MakeGroups:
6225             return self.editor.ScaleMakeGroups(theObject, thePoint, theScaleFact)
6226         self.editor.Scale(theObject, thePoint, theScaleFact, Copy)
6227         return []
6228
6229     def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""):
6230         """
6231         Create a new mesh from the translated object
6232
6233         Parameters:
6234             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6235             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
6236             theScaleFact: list of 1-3 scale factors for axises
6237             MakeGroups: forces the generation of new groups from existing ones
6238             NewMeshName: the name of the newly created mesh
6239
6240         Returns:
6241             instance of class :class:`Mesh`
6242         """
6243         unRegister = genObjUnRegister()
6244         if (isinstance(theObject, Mesh)):
6245             theObject = theObject.GetMesh()
6246         if ( isinstance( theObject, list )):
6247             theObject = self.GetIDSource(theObject,SMESH.ALL)
6248             unRegister.set( theObject )
6249         if ( isinstance( thePoint, list )):
6250             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
6251         if ( isinstance( theScaleFact, float )):
6252             theScaleFact = [theScaleFact]
6253         if ( isinstance( theScaleFact, int )):
6254             theScaleFact = [ float(theScaleFact)]
6255
6256         self.mesh.SetParameters(thePoint.parameters)
6257         mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact,
6258                                          MakeGroups, NewMeshName)
6259         return Mesh( self.smeshpyD, self.geompyD, mesh )
6260
6261
6262
6263     def Rotate (self, IDsOfElements, Axis, AngleInRadians, Copy, MakeGroups=False):
6264         """
6265         Rotate the elements
6266
6267         Parameters:
6268             IDsOfElements: list of elements ids
6269             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6270             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6271             Copy: allows copying the rotated elements
6272             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6273
6274         Returns:
6275             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
6276         """
6277
6278
6279         if IDsOfElements == []:
6280             IDsOfElements = self.GetElementsId()
6281         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6282             Axis = self.smeshpyD.GetAxisStruct(Axis)
6283         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6284         Parameters = Axis.parameters + var_separator + Parameters
6285         self.mesh.SetParameters(Parameters)
6286         if Copy and MakeGroups:
6287             return self.editor.RotateMakeGroups(IDsOfElements, Axis, AngleInRadians)
6288         self.editor.Rotate(IDsOfElements, Axis, AngleInRadians, Copy)
6289         return []
6290
6291     def RotateMakeMesh (self, IDsOfElements, Axis, AngleInRadians, MakeGroups=0, NewMeshName=""):
6292         """
6293         Create a new mesh of rotated elements
6294
6295         Parameters:
6296             IDsOfElements: list of element ids
6297             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6298             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6299             MakeGroups: forces the generation of new groups from existing ones
6300             NewMeshName: the name of the newly created mesh
6301
6302         Returns:
6303             instance of class :class:`Mesh`
6304         """
6305
6306         if IDsOfElements == []:
6307             IDsOfElements = self.GetElementsId()
6308         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6309             Axis = self.smeshpyD.GetAxisStruct(Axis)
6310         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6311         Parameters = Axis.parameters + var_separator + Parameters
6312         self.mesh.SetParameters(Parameters)
6313         mesh = self.editor.RotateMakeMesh(IDsOfElements, Axis, AngleInRadians,
6314                                           MakeGroups, NewMeshName)
6315         return Mesh( self.smeshpyD, self.geompyD, mesh )
6316
6317     def RotateObject (self, theObject, Axis, AngleInRadians, Copy, MakeGroups=False):
6318         """
6319         Rotate the object
6320
6321         Parameters:
6322             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6323             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6324             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
6325             Copy: allows copying the rotated elements
6326             MakeGroups: forces the generation of new groups from existing ones (if Copy)
6327
6328         Returns:
6329             list of created :class:`groups <SMESH.SMESH_GroupBase>` if MakeGroups==True, empty list otherwise
6330         """
6331
6332         if (isinstance(theObject, Mesh)):
6333             theObject = theObject.GetMesh()
6334         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6335             Axis = self.smeshpyD.GetAxisStruct(Axis)
6336         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6337         Parameters = Axis.parameters + ":" + Parameters
6338         self.mesh.SetParameters(Parameters)
6339         if Copy and MakeGroups:
6340             return self.editor.RotateObjectMakeGroups(theObject, Axis, AngleInRadians)
6341         self.editor.RotateObject(theObject, Axis, AngleInRadians, Copy)
6342         return []
6343
6344     def RotateObjectMakeMesh(self, theObject, Axis, AngleInRadians, MakeGroups=0,NewMeshName=""):
6345         """
6346         Create a new mesh from the rotated object
6347
6348         Parameters:
6349             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
6350             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
6351             AngleInRadians: the angle of rotation (in radians)  or a name of variable which defines angle in degrees
6352             MakeGroups: forces the generation of new groups from existing ones
6353             NewMeshName: the name of the newly created mesh
6354
6355         Returns:
6356             instance of class :class:`Mesh`
6357         """
6358
6359         if (isinstance( theObject, Mesh )):
6360             theObject = theObject.GetMesh()
6361         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
6362             Axis = self.smeshpyD.GetAxisStruct(Axis)
6363         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
6364         Parameters = Axis.parameters + ":" + Parameters
6365         mesh = self.editor.RotateObjectMakeMesh(theObject, Axis, AngleInRadians,
6366                                                        MakeGroups, NewMeshName)
6367         self.mesh.SetParameters(Parameters)
6368         return Mesh( self.smeshpyD, self.geompyD, mesh )
6369
6370     def Offset(self, theObject, Value, MakeGroups=False, CopyElements=False, NewMeshName=''):
6371         """
6372         Create an offset mesh from the given 2D object
6373
6374         Parameters:
6375             theObject (SMESH.SMESH_IDSource): the source object (mesh, sub-mesh, group or filter)
6376             theValue (float): signed offset size
6377             MakeGroups (boolean): forces the generation of new groups from existing ones
6378             CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, 
6379                           False means to remove original elements.
6380             NewMeshName (string): the name of a mesh to create. If empty, offset elements are added to this mesh
6381
6382         Returns:
6383             A tuple (:class:`Mesh`, list of :class:`groups <SMESH.SMESH_Group>`)
6384         """
6385
6386         if isinstance( theObject, Mesh ):
6387             theObject = theObject.GetMesh()
6388         theValue,Parameters,hasVars = ParseParameters(Value)
6389         mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName)
6390         self.mesh.SetParameters(Parameters)
6391         if mesh_groups[0]:
6392             return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
6393         return mesh_groups
6394
6395     def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
6396         """
6397         Find groups of adjacent nodes within Tolerance.
6398
6399         Parameters:
6400             Tolerance (float): the value of tolerance
6401             SeparateCornerAndMediumNodes (boolean): if *True*, in quadratic mesh puts
6402                 corner and medium nodes in separate groups thus preventing
6403                 their further merge.
6404
6405         Returns:
6406             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6407         """
6408
6409         return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
6410
6411     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance,
6412                                    exceptNodes=[], SeparateCornerAndMediumNodes=False):
6413         """
6414         Find groups of adjacent nodes within Tolerance.
6415
6416         Parameters:
6417             Tolerance: the value of tolerance
6418             SubMeshOrGroup: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or of node IDs
6419             exceptNodes: list of either SubMeshes, Groups or node IDs to exclude from search
6420             SeparateCornerAndMediumNodes: if *True*, in quadratic mesh puts
6421                 corner and medium nodes in separate groups thus preventing
6422                 their further merge.
6423
6424         Returns:
6425             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6426         """
6427
6428         unRegister = genObjUnRegister()
6429         if not isinstance( SubMeshOrGroup, list ):
6430             SubMeshOrGroup = [ SubMeshOrGroup ]
6431         for i,obj in enumerate( SubMeshOrGroup ):
6432             if isinstance( obj, Mesh ):
6433                 SubMeshOrGroup = [ obj.GetMesh() ]
6434                 break
6435             if isinstance( obj, int ):
6436                 SubMeshOrGroup = [ self.GetIDSource( SubMeshOrGroup, SMESH.NODE )]
6437                 unRegister.set( SubMeshOrGroup )
6438                 break
6439
6440         if not isinstance( exceptNodes, list ):
6441             exceptNodes = [ exceptNodes ]
6442         if exceptNodes and isinstance( exceptNodes[0], int ):
6443             exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
6444             unRegister.set( exceptNodes )
6445
6446         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
6447                                                         exceptNodes, SeparateCornerAndMediumNodes)
6448
6449     def MergeNodes (self, GroupsOfNodes, NodesToKeep=[], AvoidMakingHoles=False):
6450         """
6451         Merge nodes
6452
6453         Parameters:
6454             GroupsOfNodes: a list of groups of nodes IDs for merging.
6455                 E.g. [[1,12,13],[25,4]] means that nodes 12, 13 and 4 will be removed and replaced
6456                 in all elements and mesh groups by nodes 1 and 25 correspondingly
6457             NodesToKeep: nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
6458                 If *NodesToKeep* does not include a node to keep for some group to merge,
6459                 then the first node in the group is kept.
6460             AvoidMakingHoles: prevent merging nodes which cause removal of elements becoming
6461                 invalid
6462
6463         Note:
6464                 This operation can create gaps in numeration of nodes or elements.
6465                 Call :meth:`RenumberElements` to remove the gaps.
6466         """
6467         self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles )
6468
6469     def FindEqualElements (self, MeshOrSubMeshOrGroup=None, exceptElements=[]):
6470         """
6471         Find the elements built on the same nodes.
6472
6473         Parameters:
6474             MeshOrSubMeshOrGroup: :class:`mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` or element IDs to check for equal elements
6475             exceptElements: list of either SubMeshes, Groups or elements IDs to exclude from search
6476
6477
6478         Returns:
6479             the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
6480         """
6481
6482         unRegister = genObjUnRegister()
6483         if MeshOrSubMeshOrGroup is None:
6484             MeshOrSubMeshOrGroup = [ self.mesh ]
6485         elif isinstance( MeshOrSubMeshOrGroup, Mesh ):
6486             MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup.GetMesh() ]
6487         elif not isinstance( MeshOrSubMeshOrGroup, list ):
6488             MeshOrSubMeshOrGroup = [ MeshOrSubMeshOrGroup ]
6489         if isinstance( MeshOrSubMeshOrGroup[0], int ):
6490             MeshOrSubMeshOrGroup = [ self.GetIDSource( MeshOrSubMeshOrGroup, SMESH.ALL )]
6491             unRegister.set( MeshOrSubMeshOrGroup )
6492         for item in MeshOrSubMeshOrGroup:
6493             if isinstance( item, Mesh ):
6494                 MeshOrSubMeshOrGroup = [ item.GetMesh() ]
6495
6496         if not isinstance( exceptElements, list ):
6497             exceptElements = [ exceptElements ]
6498         if exceptElements and isinstance( exceptElements[0], int ):
6499             exceptElements = [ self.GetIDSource( exceptElements, SMESH.ALL )]
6500             unRegister.set( exceptElements )
6501
6502         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup, exceptElements )
6503
6504     def MergeElements(self, GroupsOfElementsID, ElementsToKeep=[]):
6505         """
6506         Merge elements in each given group.
6507
6508         Parameters:
6509             GroupsOfElementsID: a list of groups (lists) of elements IDs for merging
6510                 (e.g. [[1,12,13],[25,4]] means that elements 12, 13 and 4 will be removed and
6511                 replaced in all mesh groups by elements 1 and 25)
6512             ElementsToKeep: elements to keep in the mesh: a list of groups, sub-meshes or node IDs.
6513                 If *ElementsToKeep* does not include an element to keep for some group to merge,
6514                 then the first element in the group is kept.
6515
6516         Note:
6517                 This operation can create gaps in numeration of elements.
6518                 Call :meth:`RenumberElements` to remove the gaps.
6519         """
6520
6521         unRegister = genObjUnRegister()
6522         if ElementsToKeep:
6523             if not isinstance( ElementsToKeep, list ):
6524                 ElementsToKeep = [ ElementsToKeep ]
6525             if isinstance( ElementsToKeep[0], int ):
6526                 ElementsToKeep = [ self.GetIDSource( ElementsToKeep, SMESH.ALL )]
6527                 unRegister.set( ElementsToKeep )
6528
6529         self.editor.MergeElements( GroupsOfElementsID, ElementsToKeep )
6530
6531     def MergeEqualElements(self):
6532         """
6533         Leave one element and remove all other elements built on the same nodes.
6534
6535         Note:
6536                 This operation can create gaps in numeration of elements.
6537                 Call :meth:`RenumberElements` to remove the gaps.
6538         """
6539
6540         self.editor.MergeEqualElements()
6541
6542     def FindFreeBorders(self, ClosedOnly=True):
6543         """
6544         Returns all or only closed free borders
6545
6546         Returns:
6547             list of SMESH.FreeBorder's
6548         """
6549
6550         return self.editor.FindFreeBorders( ClosedOnly )
6551
6552     def FillHole(self, holeNodes, groupName=""):
6553         """
6554         Fill with 2D elements a hole defined by a SMESH.FreeBorder.
6555
6556         Parameters:
6557             holeNodes: either a SMESH.FreeBorder or a list on node IDs. These nodes
6558                 must describe all sequential nodes of the hole border. The first and the last
6559                 nodes must be the same. Use :meth:`FindFreeBorders` to get nodes of holes.
6560             groupName (string): name of a group to add new faces
6561         Returns:
6562             a :class:`group <SMESH.SMESH_GroupBase>` containing the new faces; or :code:`None` if `groupName` == ""
6563         """
6564
6565
6566         if holeNodes and isinstance( holeNodes, list ) and isinstance( holeNodes[0], int ):
6567             holeNodes = SMESH.FreeBorder(nodeIDs=holeNodes)
6568         if not isinstance( holeNodes, SMESH.FreeBorder ):
6569             raise TypeError("holeNodes must be either SMESH.FreeBorder or list of integer and not %s" % holeNodes)
6570         return self.editor.FillHole( holeNodes, groupName )
6571
6572     def FindCoincidentFreeBorders (self, tolerance=0.):
6573         """
6574         Return groups of FreeBorder's coincident within the given tolerance.
6575
6576         Parameters:
6577             tolerance: the tolerance. If the tolerance <= 0.0 then one tenth of an average
6578                 size of elements adjacent to free borders being compared is used.
6579
6580         Returns:
6581             SMESH.CoincidentFreeBorders structure
6582         """
6583
6584         return self.editor.FindCoincidentFreeBorders( tolerance )
6585
6586     def SewCoincidentFreeBorders (self, freeBorders, createPolygons=False, createPolyhedra=False):
6587         """
6588         Sew FreeBorder's of each group
6589
6590         Parameters:
6591             freeBorders: either a SMESH.CoincidentFreeBorders structure or a list of lists
6592                 where each enclosed list contains node IDs of a group of coincident free
6593                 borders such that each consequent triple of IDs within a group describes
6594                 a free border in a usual way: n1, n2, nLast - i.e. 1st node, 2nd node and
6595                 last node of a border.
6596                 For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes two
6597                 groups of coincident free borders, each group including two borders.
6598             createPolygons: if :code:`True` faces adjacent to free borders are converted to
6599                 polygons if a node of opposite border falls on a face edge, else such
6600                 faces are split into several ones.
6601             createPolyhedra: if :code:`True` volumes adjacent to free borders are converted to
6602                 polyhedra if a node of opposite border falls on a volume edge, else such
6603                 volumes, if any, remain intact and the mesh becomes non-conformal.
6604
6605         Returns:
6606             a number of successfully sewed groups
6607
6608         Note:
6609                 This operation can create gaps in numeration of nodes or elements.
6610                 Call :meth:`RenumberElements` to remove the gaps.
6611         """
6612
6613         if freeBorders and isinstance( freeBorders, list ):
6614             # construct SMESH.CoincidentFreeBorders
6615             if isinstance( freeBorders[0], int ):
6616                 freeBorders = [freeBorders]
6617             borders = []
6618             coincidentGroups = []
6619             for nodeList in freeBorders:
6620                 if not nodeList or len( nodeList ) % 3:
6621                     raise ValueError("Wrong number of nodes in this group: %s" % nodeList)
6622                 group = []
6623                 while nodeList:
6624                     group.append  ( SMESH.FreeBorderPart( len(borders), 0, 1, 2 ))
6625                     borders.append( SMESH.FreeBorder( nodeList[:3] ))
6626                     nodeList = nodeList[3:]
6627                     pass
6628                 coincidentGroups.append( group )
6629                 pass
6630             freeBorders = SMESH.CoincidentFreeBorders( borders, coincidentGroups )
6631
6632         return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
6633
6634     def SewFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6635                         FirstNodeID2, SecondNodeID2, LastNodeID2,
6636                         CreatePolygons, CreatePolyedrs):
6637         """
6638         Sew free borders
6639
6640         Returns:
6641             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6642
6643         Note:
6644                 This operation can create gaps in numeration of nodes or elements.
6645                 Call :meth:`RenumberElements` to remove the gaps.
6646         """
6647
6648         return self.editor.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6649                                           FirstNodeID2, SecondNodeID2, LastNodeID2,
6650                                           CreatePolygons, CreatePolyedrs)
6651
6652     def SewConformFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6653                                FirstNodeID2, SecondNodeID2):
6654         """
6655         Sew conform free borders
6656
6657         Returns:
6658             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6659
6660         Note:
6661                 This operation can create gaps in numeration of elements.
6662                 Call :meth:`RenumberElements` to remove the gaps.
6663         """
6664
6665         return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6666                                                  FirstNodeID2, SecondNodeID2)
6667
6668     def SewBorderToSide (self, FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6669                          FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs):
6670         """
6671         Sew border to side
6672
6673         Returns:
6674             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6675
6676         Note:
6677                 This operation can create gaps in numeration of elements.
6678                 Call :meth:`RenumberElements` to remove the gaps.
6679         """
6680
6681         return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6682                                            FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs)
6683
6684     def SewSideElements (self, IDsOfSide1Elements, IDsOfSide2Elements,
6685                          NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6686                          NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge):
6687         """
6688         Sew two sides of a mesh. The nodes belonging to Side1 are
6689         merged with the nodes of elements of Side2.
6690         The number of elements in theSide1 and in theSide2 must be
6691         equal and they should have similar nodal connectivity.
6692         The nodes to merge should belong to side borders and
6693         the first node should be linked to the second.
6694
6695         Returns:
6696             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6697
6698         Note:
6699                 This operation can create gaps in numeration of nodes.
6700                 Call :meth:`RenumberElements` to remove the gaps.
6701         """
6702
6703         return self.editor.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
6704                                            NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6705                                            NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
6706
6707     def ChangeElemNodes(self, ide, newIDs):
6708         """
6709         Set new nodes for the given element. Number of nodes should be kept.
6710
6711         Parameters:
6712             ide: the element ID
6713             newIDs: nodes IDs
6714
6715         Returns:
6716             False if the number of nodes does not correspond to the type of element
6717         """
6718
6719         return self.editor.ChangeElemNodes(ide, newIDs)
6720
6721     def GetLastCreatedNodes(self):
6722         """
6723         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some nodes were
6724         created, this method return the list of their IDs.
6725         If new nodes were not created - return empty list
6726
6727         Returns:
6728             the list of integer values (can be empty)
6729         """
6730
6731         return self.editor.GetLastCreatedNodes()
6732
6733     def GetLastCreatedElems(self):
6734         """
6735         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some elements were
6736         created this method return the list of their IDs.
6737         If new elements were not created - return empty list
6738
6739         Returns:
6740             the list of integer values (can be empty)
6741         """
6742
6743         return self.editor.GetLastCreatedElems()
6744
6745     def ClearLastCreated(self):
6746         """
6747         Forget what nodes and elements were created by the last mesh edition operation
6748         """
6749
6750         self.editor.ClearLastCreated()
6751
6752     def DoubleElements(self, theElements, theGroupName=""):
6753         """
6754         Create duplicates of given elements, i.e. create new elements based on the
6755         same nodes as the given ones.
6756
6757         Parameters:
6758             theElements: container of elements to duplicate. It can be a
6759                 :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` 
6760                 or a list of element IDs. If *theElements* is
6761                 a :class:`Mesh`, elements of highest dimension are duplicated
6762             theGroupName: a name of group to contain the generated elements.
6763                 If a group with such a name already exists, the new elements
6764                 are added to the existing group, else a new group is created.
6765                 If *theGroupName* is empty, new elements are not added
6766                 in any group.
6767
6768         Returns:
6769                 a :class:`group <SMESH.SMESH_Group>` where the new elements are added. 
6770                 None if *theGroupName* == "".
6771         """
6772
6773         unRegister = genObjUnRegister()
6774         if isinstance( theElements, Mesh ):
6775             theElements = theElements.mesh
6776         elif isinstance( theElements, list ):
6777             theElements = self.GetIDSource( theElements, SMESH.ALL )
6778             unRegister.set( theElements )
6779         return self.editor.DoubleElements(theElements, theGroupName)
6780
6781     def DoubleNodes(self, theNodes, theModifiedElems):
6782         """
6783         Create a hole in a mesh by doubling the nodes of some particular elements
6784
6785         Parameters:
6786             theNodes: IDs of nodes to be doubled
6787             theModifiedElems: IDs of elements to be updated by the new (doubled)
6788                 nodes. If list of element identifiers is empty then nodes are doubled but
6789                 they not assigned to elements
6790
6791         Returns:
6792             True if operation has been completed successfully, False otherwise
6793         """
6794
6795         return self.editor.DoubleNodes(theNodes, theModifiedElems)
6796
6797     def DoubleNode(self, theNodeId, theModifiedElems):
6798         """
6799         Create a hole in a mesh by doubling the nodes of some particular elements.
6800         This method provided for convenience works as :meth:`DoubleNodes`.
6801
6802         Parameters:
6803             theNodeId: IDs of node to double
6804             theModifiedElems: IDs of elements to update
6805
6806         Returns:
6807             True if operation has been completed successfully, False otherwise
6808         """
6809
6810         return self.editor.DoubleNode(theNodeId, theModifiedElems)
6811
6812     def DoubleNodeGroup(self, theNodes, theModifiedElems, theMakeGroup=False):
6813         """
6814         Create a hole in a mesh by doubling the nodes of some particular elements.
6815         This method provided for convenience works as :meth:`DoubleNodes`.
6816
6817         Parameters:
6818             theNodes: group of nodes to double.
6819             theModifiedElems: group of elements to update.
6820             theMakeGroup: forces the generation of a group containing new nodes.
6821
6822         Returns:
6823             True or a created group if operation has been completed successfully,
6824             False or None otherwise
6825         """
6826
6827         if theMakeGroup:
6828             return self.editor.DoubleNodeGroupNew(theNodes, theModifiedElems)
6829         return self.editor.DoubleNodeGroup(theNodes, theModifiedElems)
6830
6831     def DoubleNodeGroups(self, theNodes, theModifiedElems, theMakeGroup=False):
6832         """
6833         Create a hole in a mesh by doubling the nodes of some particular elements.
6834         This method provided for convenience works as :meth:`DoubleNodes`.
6835
6836         Parameters:
6837             theNodes: list of groups of nodes to double.
6838             theModifiedElems: list of groups of elements to update.
6839             theMakeGroup: forces the generation of a group containing new nodes.
6840
6841         Returns:
6842             True if operation has been completed successfully, False otherwise
6843         """
6844
6845         if theMakeGroup:
6846             return self.editor.DoubleNodeGroupsNew(theNodes, theModifiedElems)
6847         return self.editor.DoubleNodeGroups(theNodes, theModifiedElems)
6848
6849     def DoubleNodeElem(self, theElems, theNodesNot, theAffectedElems):
6850         """
6851         Create a hole in a mesh by doubling the nodes of some particular elements
6852
6853         Parameters:
6854             theElems: the list of elements (edges or faces) to replicate.
6855                 The nodes for duplication could be found from these elements
6856             theNodesNot: list of nodes NOT to replicate
6857             theAffectedElems: the list of elements (cells and edges) to which the
6858                 replicated nodes should be associated to
6859
6860         Returns:
6861             True if operation has been completed successfully, False otherwise
6862         """
6863
6864         return self.editor.DoubleNodeElem(theElems, theNodesNot, theAffectedElems)
6865
6866     def DoubleNodeElemInRegion(self, theElems, theNodesNot, theShape):
6867         """
6868         Create a hole in a mesh by doubling the nodes of some particular elements
6869
6870         Parameters:
6871             theElems: the list of elements (edges or faces) to replicate.
6872                 The nodes for duplication could be found from these elements
6873             theNodesNot: list of nodes NOT to replicate
6874             theShape: shape to detect affected elements (element which geometric center
6875                 located on or inside shape).
6876                 The replicated nodes should be associated to affected elements.
6877
6878         Returns:
6879             True if operation has been completed successfully, False otherwise
6880         """
6881
6882         return self.editor.DoubleNodeElemInRegion(theElems, theNodesNot, theShape)
6883
6884     def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems,
6885                              theMakeGroup=False, theMakeNodeGroup=False):
6886         """
6887         Create a hole in a mesh by doubling the nodes of some particular elements.
6888         This method provided for convenience works as :meth:`DoubleNodes`.
6889
6890         Parameters:
6891             theElems: group of of elements (edges or faces) to replicate.
6892             theNodesNot: group of nodes NOT to replicate.
6893             theAffectedElems: group of elements to which the replicated nodes
6894                 should be associated to.
6895             theMakeGroup: forces the generation of a group containing new elements.
6896             theMakeNodeGroup: forces the generation of a group containing new nodes.
6897
6898         Returns:
6899             True or created groups (one or two) if operation has been completed successfully,
6900             False or None otherwise
6901         """
6902
6903         if theMakeGroup or theMakeNodeGroup:
6904             twoGroups = self.editor.DoubleNodeElemGroup2New(theElems, theNodesNot,
6905                                                             theAffectedElems,
6906                                                             theMakeGroup, theMakeNodeGroup)
6907             if theMakeGroup and theMakeNodeGroup:
6908                 return twoGroups
6909             else:
6910                 return twoGroups[ int(theMakeNodeGroup) ]
6911         return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems)
6912
6913     def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape):
6914         """
6915         Create a hole in a mesh by doubling the nodes of some particular elements.
6916         This method provided for convenience works as :meth:`DoubleNodes`.
6917
6918         Parameters:
6919             theElems: group of of elements (edges or faces) to replicate
6920             theNodesNot: group of nodes not to replicate
6921             theShape: shape to detect affected elements (element which geometric center
6922                 located on or inside shape).
6923                 The replicated nodes should be associated to affected elements
6924         """
6925
6926         return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape)
6927
6928     def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems,
6929                              theMakeGroup=False, theMakeNodeGroup=False):
6930         """
6931         Create a hole in a mesh by doubling the nodes of some particular elements.
6932         This method provided for convenience works as :meth:`DoubleNodes`.
6933
6934         Parameters:
6935             theElems: list of groups of elements (edges or faces) to replicate
6936             theNodesNot: list of groups of nodes NOT to replicate
6937             theAffectedElems: group of elements to which the replicated nodes
6938                 should be associated to
6939             theMakeGroup: forces generation of a group containing new elements.
6940             theMakeNodeGroup: forces generation of a group containing new nodes
6941
6942         Returns:
6943             True or created groups (one or two) if operation has been completed successfully,
6944             False or None otherwise
6945         """
6946
6947         if theMakeGroup or theMakeNodeGroup:
6948             twoGroups = self.editor.DoubleNodeElemGroups2New(theElems, theNodesNot,
6949                                                              theAffectedElems,
6950                                                              theMakeGroup, theMakeNodeGroup)
6951             if theMakeGroup and theMakeNodeGroup:
6952                 return twoGroups
6953             else:
6954                 return twoGroups[ int(theMakeNodeGroup) ]
6955         return self.editor.DoubleNodeElemGroups(theElems, theNodesNot, theAffectedElems)
6956
6957     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
6958         """
6959         Create a hole in a mesh by doubling the nodes of some particular elements.
6960         This method provided for convenience works as :meth:`DoubleNodes`.
6961
6962         Parameters:
6963             theElems: list of groups of elements (edges or faces) to replicate
6964             theNodesNot: list of groups of nodes NOT to replicate
6965             theShape: shape to detect affected elements (element which geometric center
6966                 located on or inside shape).
6967                 The replicated nodes should be associated to affected elements
6968
6969         Returns:
6970             True if operation has been completed successfully, False otherwise
6971         """
6972
6973         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
6974
6975     def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
6976         """
6977         Identify the elements that will be affected by node duplication (actual duplication is not performed).
6978         This method is the first step of :meth:`DoubleNodeElemGroupsInRegion`.
6979
6980         Parameters:
6981             theElems: list of groups of nodes or elements (edges or faces) to replicate
6982             theNodesNot: list of groups of nodes NOT to replicate
6983             theShape: shape to detect affected elements (element which geometric center
6984                 located on or inside shape).
6985                 The replicated nodes should be associated to affected elements
6986
6987         Returns:
6988             groups of affected elements in order: volumes, faces, edges
6989         """
6990
6991         return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)
6992
6993     def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
6994
6995         """
6996         Double nodes on shared faces between groups of volumes and create flat elements on demand.
6997         The list of groups must describe a partition of the mesh volumes.
6998         The nodes of the internal faces at the boundaries of the groups are doubled.
6999         In option, the internal faces are replaced by flat elements.
7000         Triangles are transformed to prisms, and quadrangles to hexahedrons.
7001
7002         Parameters:
7003             theDomains: list of groups of volumes
7004             createJointElems: if True, create the elements
7005             onAllBoundaries: if True, the nodes and elements are also created on
7006                 the boundary between *theDomains* and the rest mesh
7007
7008         Returns:
7009             True if operation has been completed successfully, False otherwise
7010         """
7011
7012         return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
7013
7014     def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
7015         """
7016         Double nodes on some external faces and create flat elements.
7017         Flat elements are mainly used by some types of mechanic calculations.
7018
7019         Each group of the list must be constituted of faces.
7020         Triangles are transformed in prisms, and quadrangles in hexahedrons.
7021
7022         Parameters:
7023             theGroupsOfFaces: list of groups of faces
7024
7025         Returns:
7026             True if operation has been completed successfully, False otherwise
7027         """
7028
7029         return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
7030
7031     def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
7032         """
7033         Identify all the elements around a geom shape, get the faces delimiting the hole
7034         """
7035         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
7036
7037     def MakePolyLine(self, segments, groupName='', isPreview=False ):
7038         """    
7039         Create a polyline consisting of 1D mesh elements each lying on a 2D element of
7040         the initial triangle mesh. Positions of new nodes are found by cutting the mesh by the
7041         plane passing through pairs of points specified by each :class:`SMESH.PolySegment` structure.
7042         If there are several paths connecting a pair of points, the shortest path is
7043         selected by the module. Position of the cutting plane is defined by the two
7044         points and an optional vector lying on the plane specified by a PolySegment.
7045         By default the vector is defined by Mesh module as following. A middle point
7046         of the two given points is computed. The middle point is projected to the mesh.
7047         The vector goes from the middle point to the projection point. In case of planar
7048         mesh, the vector is normal to the mesh.
7049
7050         In preview mode, *segments* [i].vector returns the used vector which goes from the middle point to its projection.
7051
7052         Parameters:
7053             segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes.
7054             groupName: optional name of a group where created mesh segments will be added.
7055
7056         """    
7057         editor = self.editor
7058         if isPreview:
7059             editor = self.mesh.GetMeshEditPreviewer()
7060         segmentsRes = editor.MakePolyLine( segments, groupName )
7061         for i, seg in enumerate( segmentsRes ):
7062             segments[i].vector = seg.vector
7063         if isPreview:
7064             return editor.GetPreviewData()
7065         return None
7066
7067     def MakeSlot(self, segmentGroup, width ):
7068         """
7069         Create a slot of given width around given 1D elements lying on a triangle mesh.
7070         The slot is constructed by cutting faces by cylindrical surfaces made
7071         around each segment. Segments are expected to be created by MakePolyLine().
7072
7073         Returns:
7074                FaceEdge's located at the slot boundary
7075         """
7076         return self.editor.MakeSlot( segmentGroup, width )
7077
7078     def GetFunctor(self, funcType ):
7079         """
7080         Return a cached numerical functor by its type.
7081
7082         Parameters:
7083             funcType: functor type: an item of :class:`SMESH.FunctorType` enumeration.
7084                 Note that not all items correspond to numerical functors.
7085
7086         Returns:
7087             :class:`SMESH.NumericalFunctor`. The functor is already initialized with a mesh
7088         """
7089
7090         fn = self.functors[ funcType._v ]
7091         if not fn:
7092             fn = self.smeshpyD.GetFunctor(funcType)
7093             fn.SetMesh(self.mesh)
7094             self.functors[ funcType._v ] = fn
7095         return fn
7096
7097     def FunctorValue(self, funcType, elemId, isElem=True):
7098         """
7099         Return value of a functor for a given element
7100
7101         Parameters:
7102             funcType: an item of :class:`SMESH.FunctorType` enum.
7103             elemId: element or node ID
7104             isElem: *elemId* is ID of element or node
7105
7106         Returns:
7107             the functor value or zero in case of invalid arguments
7108         """
7109
7110         fn = self.GetFunctor( funcType )
7111         if fn.GetElementType() == self.GetElementType(elemId, isElem):
7112             val = fn.GetValue(elemId)
7113         else:
7114             val = 0
7115         return val
7116
7117     def GetLength(self, elemId=None):
7118         """
7119         Get length of given 1D elements or of all 1D mesh elements
7120
7121         Parameters:
7122             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.
7123
7124         Returns:
7125             Sum of lengths of given elements
7126         """
7127
7128         length = 0
7129         if elemId == None:
7130             length = self.smeshpyD.GetLength(self)
7131         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7132             length = self.smeshpyD.GetLength(elemId)
7133         elif elemId == []:
7134             length = 0
7135         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7136             for obj in elemId:
7137                 length += self.smeshpyD.GetLength(obj)
7138         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7139             unRegister = genObjUnRegister()
7140             obj = self.GetIDSource( elemId )
7141             unRegister.set( obj )
7142             length = self.smeshpyD.GetLength( obj )
7143         else:
7144             length = self.FunctorValue(SMESH.FT_Length, elemId)
7145         return length
7146
7147     def GetArea(self, elemId=None):
7148         """
7149         Get area of given 2D elements or of all 2D mesh elements
7150
7151         Parameters:
7152             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.
7153
7154         Returns:
7155             Area of given element's if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
7156         """
7157
7158         area = 0
7159         if elemId == None:
7160             area = self.smeshpyD.GetArea(self)
7161         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7162             area = self.smeshpyD.GetArea(elemId)
7163         elif elemId == []:
7164             area = 0
7165         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7166             for obj in elemId:
7167                 area += self.smeshpyD.GetArea(obj)
7168         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7169             unRegister = genObjUnRegister()
7170             obj = self.GetIDSource( elemId )
7171             unRegister.set( obj )
7172             area = self.smeshpyD.GetArea( obj )
7173         else:
7174             area = self.FunctorValue(SMESH.FT_Area, elemId)
7175         return area
7176
7177     def GetVolume(self, elemId=None):
7178         """
7179         Get volume of given 3D elements or of all 3D mesh elements
7180
7181         Parameters:
7182             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.
7183
7184         Returns:
7185             Sum element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
7186         """
7187
7188         volume = 0
7189         if elemId == None:
7190             volume= self.smeshpyD.GetVolume(self)
7191         elif isinstance(elemId, SMESH._objref_SMESH_IDSource):
7192             volume= self.smeshpyD.GetVolume(elemId)
7193         elif elemId == []:
7194             volume = 0
7195         elif isinstance(elemId, list) and isinstance(elemId[0], SMESH._objref_SMESH_IDSource):
7196             for obj in elemId:
7197                 volume+= self.smeshpyD.GetVolume(obj)
7198         elif isinstance(elemId, list) and isinstance(elemId[0], int):
7199             unRegister = genObjUnRegister()
7200             obj = self.GetIDSource( elemId )
7201             unRegister.set( obj )
7202             volume= self.smeshpyD.GetVolume( obj )
7203         else:
7204             volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
7205         return volume
7206
7207     def GetAngle(self, node1, node2, node3 ):
7208         """
7209         Computes a radian measure of an angle defined by 3 nodes: <(node1,node2,node3)
7210
7211         Parameters:            
7212                 node1,node2,node3: IDs of the three nodes
7213
7214         Returns:        
7215             Angle in radians [0,PI]. -1 if failure case.
7216         """
7217         p1 = self.GetNodeXYZ( node1 )
7218         p2 = self.GetNodeXYZ( node2 )
7219         p3 = self.GetNodeXYZ( node3 )
7220         if p1 and p2 and p3:
7221             return self.smeshpyD.GetAngle( p1,p2,p3 )
7222         return -1.
7223
7224
7225     def GetMaxElementLength(self, elemId):
7226         """
7227         Get maximum element length.
7228
7229         Parameters:
7230             elemId: mesh element ID
7231
7232         Returns:
7233             element's maximum length value
7234         """
7235
7236         if self.GetElementType(elemId, True) == SMESH.VOLUME:
7237             ftype = SMESH.FT_MaxElementLength3D
7238         else:
7239             ftype = SMESH.FT_MaxElementLength2D
7240         return self.FunctorValue(ftype, elemId)
7241
7242     def GetAspectRatio(self, elemId):
7243         """
7244         Get aspect ratio of 2D or 3D element.
7245
7246         Parameters:
7247             elemId: mesh element ID
7248
7249         Returns:
7250             element's aspect ratio value
7251         """
7252
7253         if self.GetElementType(elemId, True) == SMESH.VOLUME:
7254             ftype = SMESH.FT_AspectRatio3D
7255         else:
7256             ftype = SMESH.FT_AspectRatio
7257         return self.FunctorValue(ftype, elemId)
7258
7259     def GetWarping(self, elemId):
7260         """
7261         Get warping angle of 2D element.
7262
7263         Parameters:
7264             elemId: mesh element ID
7265
7266         Returns:
7267             element's warping angle value
7268         """
7269
7270         return self.FunctorValue(SMESH.FT_Warping, elemId)
7271
7272     def GetMinimumAngle(self, elemId):
7273         """
7274         Get minimum angle of 2D element.
7275
7276         Parameters:
7277             elemId: mesh element ID
7278
7279         Returns:
7280             element's minimum angle value
7281         """
7282
7283         return self.FunctorValue(SMESH.FT_MinimumAngle, elemId)
7284
7285     def GetTaper(self, elemId):
7286         """
7287         Get taper of 2D element.
7288
7289         Parameters:
7290             elemId: mesh element ID
7291
7292         Returns:
7293             element's taper value
7294         """
7295
7296         return self.FunctorValue(SMESH.FT_Taper, elemId)
7297
7298     def GetSkew(self, elemId):
7299         """
7300         Get skew of 2D element.
7301
7302         Parameters:
7303             elemId: mesh element ID
7304
7305         Returns:
7306             element's skew value
7307         """
7308
7309         return self.FunctorValue(SMESH.FT_Skew, elemId)
7310
7311     def GetMinMax(self, funType, meshPart=None):
7312         """
7313         Return minimal and maximal value of a given functor.
7314
7315         Parameters:
7316             funType (SMESH.FunctorType): a functor type.
7317                   Note that not all items of :class:`SMESH.FunctorType` corresponds
7318                   to numerical functors.
7319             meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to treat
7320
7321         Returns:
7322             tuple (min,max)
7323         """
7324
7325         unRegister = genObjUnRegister()
7326         if isinstance( meshPart, list ):
7327             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
7328             unRegister.set( meshPart )
7329         if isinstance( meshPart, Mesh ):
7330             meshPart = meshPart.mesh
7331         fun = self.GetFunctor( funType )
7332         if fun:
7333             if meshPart:
7334                 if hasattr( meshPart, "SetMesh" ):
7335                     meshPart.SetMesh( self.mesh ) # set mesh to filter
7336                 hist = fun.GetLocalHistogram( 1, False, meshPart )
7337             else:
7338                 hist = fun.GetHistogram( 1, False )
7339             if hist:
7340                 return hist[0].min, hist[0].max
7341         return None
7342
7343     pass # end of Mesh class
7344
7345
7346 class meshProxy(SMESH._objref_SMESH_Mesh):
7347     """
7348     Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
7349     with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
7350     """
7351     def __init__(self,*args):
7352         SMESH._objref_SMESH_Mesh.__init__(self,*args)
7353     def __deepcopy__(self, memo=None):
7354         new = self.__class__(self)
7355         return new
7356     def CreateDimGroup(self,*args): # 2 args added: nbCommonNodes, underlyingOnly
7357         if len( args ) == 3:
7358             args += SMESH.ALL_NODES, True
7359         return SMESH._objref_SMESH_Mesh.CreateDimGroup(self, *args)
7360     def ExportToMEDX(self, *args): # function removed
7361         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
7362         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7363         SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
7364     def ExportToMED(self, *args): # function removed
7365         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
7366         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7367         args2 = list(args)
7368         while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
7369             args2.append(True)
7370         SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
7371     def ExportPartToMED(self, *args): # 'version' parameter removed
7372         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7373         SMESH._objref_SMESH_Mesh.ExportPartToMED(self, *args)
7374     def ExportMED(self, *args): # signature of method changed
7375         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
7376         args2 = list(args)
7377         while len(args2) < 5:  # !!!! nb of parameters for ExportToMED IDL's method
7378             args2.append(True)
7379         SMESH._objref_SMESH_Mesh.ExportMED(self, *args2)
7380     pass
7381 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
7382
7383
7384 class submeshProxy(SMESH._objref_SMESH_subMesh):
7385
7386     """
7387     Private class wrapping SMESH.SMESH_SubMesh in order to add Compute()
7388     """
7389     def __init__(self,*args):
7390         SMESH._objref_SMESH_subMesh.__init__(self,*args)
7391         self.mesh = None
7392     def __deepcopy__(self, memo=None):
7393         new = self.__class__(self)
7394         return new
7395
7396     def Compute(self,refresh=False):
7397         """
7398         Compute the sub-mesh and return the status of the computation
7399
7400         Parameters:
7401             refresh: if *True*, Object Browser is automatically updated (when running in GUI)
7402
7403         Returns:
7404             True or False
7405
7406         This is a method of SMESH.SMESH_submesh that can be obtained via Mesh.GetSubMesh() or
7407         :meth:`smeshBuilder.Mesh.GetSubMesh`.
7408         """
7409
7410         if not self.mesh:
7411             self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
7412
7413         ok = self.mesh.Compute( self.GetSubShape(),refresh=[] )
7414
7415         if salome.sg.hasDesktop():
7416             if refresh: salome.sg.updateObjBrowser()
7417             pass
7418
7419         return ok
7420     pass
7421 omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
7422
7423
7424 class meshEditor(SMESH._objref_SMESH_MeshEditor):
7425     """
7426     Private class used to compensate change of CORBA API of SMESH_MeshEditor for backward
7427     compatibility with old dump scripts which call SMESH_MeshEditor directly and not via
7428     smeshBuilder.Mesh
7429     """
7430     def __init__(self,*args):
7431         SMESH._objref_SMESH_MeshEditor.__init__( self, *args)
7432         self.mesh = None
7433     def __getattr__(self, name ): # method called if an attribute not found
7434         if not self.mesh:         # look for name() method in Mesh class
7435             self.mesh = Mesh( None, None, SMESH._objref_SMESH_MeshEditor.GetMesh(self))
7436         if hasattr( self.mesh, name ):
7437             return getattr( self.mesh, name )
7438         if name == "ExtrusionAlongPathObjX":
7439             return getattr( self.mesh, "ExtrusionAlongPathX" ) # other method name
7440         print("meshEditor: attribute '%s' NOT FOUND" % name)
7441         return None
7442     def __deepcopy__(self, memo=None):
7443         new = self.__class__(self)
7444         return new
7445     def FindCoincidentNodes(self,*args): # a 2nd arg added (SeparateCornerAndMediumNodes)
7446         if len( args ) == 1: args += False,
7447         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodes( self, *args )
7448     def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
7449         if len( args ) == 2: args += False,
7450         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args )
7451     def MergeNodes(self,*args): # 2 args added (NodesToKeep,AvoidMakingHoles)
7452         if len( args ) == 1:
7453             return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [], False )
7454         NodesToKeep = args[1]
7455         AvoidMakingHoles = args[2] if len( args ) == 3 else False
7456         unRegister  = genObjUnRegister()
7457         if NodesToKeep:
7458             if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
7459                 NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
7460             if not isinstance( NodesToKeep, list ):
7461                 NodesToKeep = [ NodesToKeep ]
7462         return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles )
7463     pass
7464 omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)
7465
7466 class Pattern(SMESH._objref_SMESH_Pattern):
7467     """
7468     Private class wrapping SMESH.SMESH_Pattern CORBA class in order to treat Notebook
7469     variables in some methods
7470     """
7471
7472     def LoadFromFile(self, patternTextOrFile ):
7473         text = patternTextOrFile
7474         if os.path.exists( text ):
7475             text = open( patternTextOrFile ).read()
7476             pass
7477         return SMESH._objref_SMESH_Pattern.LoadFromFile( self, text )
7478
7479     def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse):
7480         decrFun = lambda i: i-1
7481         theNodeIndexOnKeyPoint1,Parameters,hasVars = ParseParameters(theNodeIndexOnKeyPoint1, decrFun)
7482         theMesh.SetParameters(Parameters)
7483         return SMESH._objref_SMESH_Pattern.ApplyToMeshFaces( self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse )
7484
7485     def ApplyToHexahedrons(self, theMesh, theVolumesIDs, theNode000Index, theNode001Index):
7486         decrFun = lambda i: i-1
7487         theNode000Index,theNode001Index,Parameters,hasVars = ParseParameters(theNode000Index,theNode001Index, decrFun)
7488         theMesh.SetParameters(Parameters)
7489         return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index )
7490
7491     def MakeMesh(self, mesh, CreatePolygons=False, CreatePolyhedra=False):
7492         if isinstance( mesh, Mesh ):
7493             mesh = mesh.GetMesh()
7494         return SMESH._objref_SMESH_Pattern.MakeMesh( self, mesh, CreatePolygons, CreatePolyhedra )
7495
7496 omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
7497 """
7498 Registering the new proxy for Pattern
7499 """
7500
7501 class algoCreator:
7502     """
7503     Private class used to bind methods creating algorithms to the class Mesh
7504     """
7505
7506     def __init__(self, method):
7507         self.mesh = None
7508         self.defaultAlgoType = ""
7509         self.algoTypeToClass = {}
7510         self.method = method
7511
7512     def add(self, algoClass):
7513         """
7514         Store a python class of algorithm
7515         """
7516         if inspect.isclass(algoClass) and \
7517            hasattr( algoClass, "algoType"):
7518             self.algoTypeToClass[ algoClass.algoType ] = algoClass
7519             if not self.defaultAlgoType and \
7520                hasattr( algoClass, "isDefault") and algoClass.isDefault:
7521                 self.defaultAlgoType = algoClass.algoType
7522             #print("Add",algoClass.algoType, "dflt",self.defaultAlgoType)
7523
7524     def copy(self, mesh):
7525         """
7526         Create a copy of self and assign mesh to the copy
7527         """
7528
7529         other = algoCreator( self.method )
7530         other.defaultAlgoType = self.defaultAlgoType
7531         other.algoTypeToClass = self.algoTypeToClass
7532         other.mesh = mesh
7533         return other
7534
7535     def __call__(self,algo="",geom=0,*args):
7536         """
7537         Create an instance of algorithm
7538         """
7539         algoType = ""
7540         shape = 0
7541         if isinstance( algo, str ):
7542             algoType = algo
7543         elif ( isinstance( algo, geomBuilder.GEOM._objref_GEOM_Object ) and \
7544                not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object )):
7545             shape = algo
7546         elif algo:
7547             args += (algo,)
7548
7549         if isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
7550             shape = geom
7551         elif not algoType and isinstance( geom, str ):
7552             algoType = geom
7553         elif geom:
7554             args += (geom,)
7555         for arg in args:
7556             if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ) and not shape:
7557                 shape = arg
7558             elif isinstance( arg, str ) and not algoType:
7559                 algoType = arg
7560             else:
7561                 import traceback, sys
7562                 msg = "Warning. Unexpected argument in mesh.%s() --->  %s" % ( self.method, arg )
7563                 sys.stderr.write( msg + '\n' )
7564                 tb = traceback.extract_stack(None,2)
7565                 traceback.print_list( [tb[0]] )
7566         if not algoType:
7567             algoType = self.defaultAlgoType
7568         if not algoType and self.algoTypeToClass:
7569             algoType = sorted( self.algoTypeToClass.keys() )[0]
7570         if algoType in self.algoTypeToClass:
7571             #print("Create algo",algoType)
7572             return self.algoTypeToClass[ algoType ]( self.mesh, shape )
7573         raise RuntimeError( "No class found for algo type %s" % algoType)
7574         return None
7575
7576 class hypMethodWrapper:
7577     """
7578     Private class used to substitute and store variable parameters of hypotheses.
7579     """
7580
7581     def __init__(self, hyp, method):
7582         self.hyp    = hyp
7583         self.method = method
7584         #print("REBIND:", method.__name__)
7585         return
7586
7587     def __call__(self,*args):
7588         """
7589         call a method of hypothesis with calling SetVarParameter() before
7590         """
7591
7592         if not args:
7593             return self.method( self.hyp, *args ) # hypothesis method with no args
7594
7595         #print("MethWrapper.__call__", self.method.__name__, args)
7596         try:
7597             parsed = ParseParameters(*args)     # replace variables with their values
7598             self.hyp.SetVarParameter( parsed[-2], self.method.__name__ )
7599             result = self.method( self.hyp, *parsed[:-2] ) # call hypothesis method
7600         except omniORB.CORBA.BAD_PARAM: # raised by hypothesis method call
7601             # maybe there is a replaced string arg which is not variable
7602             result = self.method( self.hyp, *args )
7603         except ValueError as detail: # raised by ParseParameters()
7604             try:
7605                 result = self.method( self.hyp, *args )
7606             except omniORB.CORBA.BAD_PARAM:
7607                 raise ValueError(detail) # wrong variable name
7608
7609         return result
7610     pass
7611
7612 class genObjUnRegister:
7613     """
7614     A helper class that calls UnRegister() of SALOME.GenericObj'es stored in it
7615     """
7616
7617     def __init__(self, genObj=None):
7618         self.genObjList = []
7619         self.set( genObj )
7620         return
7621
7622     def set(self, genObj):
7623         "Store one or a list of of SALOME.GenericObj'es"
7624         if isinstance( genObj, list ):
7625             self.genObjList.extend( genObj )
7626         else:
7627             self.genObjList.append( genObj )
7628         return
7629
7630     def __del__(self):
7631         for genObj in self.genObjList:
7632             if genObj and hasattr( genObj, "UnRegister" ):
7633                 genObj.UnRegister()
7634
7635 for pluginName in os.environ[ "SMESH_MeshersList" ].split( os.pathsep ):
7636     """
7637     Bind methods creating mesher plug-ins to the Mesh class
7638     """
7639
7640     # print("pluginName: ", pluginName)
7641     pluginBuilderName = pluginName + "Builder"
7642     try:
7643         exec( "from salome.%s.%s import *" % (pluginName, pluginBuilderName))
7644     except Exception as e:
7645         from salome_utils import verbose
7646         if verbose(): print("Exception while loading %s: %s" % ( pluginBuilderName, e ))
7647         continue
7648     exec( "from salome.%s import %s" % (pluginName, pluginBuilderName))
7649     plugin = eval( pluginBuilderName )
7650     # print("  plugin:" , str(plugin))
7651
7652     # add methods creating algorithms to Mesh
7653     for k in dir( plugin ):
7654         if k[0] == '_': continue
7655         algo = getattr( plugin, k )
7656         #print("             algo:", str(algo))
7657         if inspect.isclass(algo) and hasattr(algo, "meshMethod"):
7658             #print("                     meshMethod:" , str(algo.meshMethod))
7659             if not hasattr( Mesh, algo.meshMethod ):
7660                 setattr( Mesh, algo.meshMethod, algoCreator( algo.meshMethod ))
7661                 pass
7662             _mmethod = getattr( Mesh, algo.meshMethod )
7663             if hasattr(  _mmethod, "add" ):
7664                 _mmethod.add(algo)
7665             pass
7666         pass
7667     pass
7668 del pluginName