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