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