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