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