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