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