Salome HOME
Merge from V5_1_main branch 24/11/2010
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
24 //  File   : SMESH_MeshEditor_i.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //
28 #ifdef WNT
29 #define NOMINMAX
30 #endif
31
32 #include "SMESH_MeshEditor_i.hxx"
33
34 #include "SMDS_Mesh0DElement.hxx"
35 #include "SMDS_MeshEdge.hxx"
36 #include "SMDS_MeshFace.hxx"
37 #include "SMDS_MeshVolume.hxx"
38 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
39 #include "SMESH_subMeshEventListener.hxx"
40 #include "SMESH_Gen_i.hxx"
41 #include "SMESH_Filter_i.hxx"
42 #include "SMESH_subMesh_i.hxx"
43 #include "SMESH_Group_i.hxx"
44 #include "SMESH_PythonDump.hxx"
45 #include "SMESH_ControlsDef.hxx"
46
47 #include "utilities.h"
48 #include "Utils_ExceptHandlers.hxx"
49 #include "Utils_CorbaException.hxx"
50
51 #include <BRepAdaptor_Surface.hxx>
52 #include <BRep_Tool.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Face.hxx>
57 #include <gp_Ax1.hxx>
58 #include <gp_Ax2.hxx>
59 #include <gp_Vec.hxx>
60
61 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
62 #define NO_CAS_CATCH
63 #endif
64
65 #include <Standard_Failure.hxx>
66
67 #ifdef NO_CAS_CATCH
68 #include <Standard_ErrorHandler.hxx>
69 #endif
70
71 #include <sstream>
72 #include <limits>
73
74 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
75
76 using namespace std;
77 using SMESH::TPythonDump;
78
79 namespace {
80
81   //=============================================================================
82   /*!
83    * \brief Mesh to apply modifications for preview purposes
84    */
85   //=============================================================================
86
87   struct TPreviewMesh: public SMESH_Mesh
88   {
89     SMDSAbs_ElementType myPreviewType; // type to show
90     //!< Constructor
91     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
92       _isShapeToMesh = (_id =_studyId =_idDoc = 0);
93       _myMeshDS  = new SMESHDS_Mesh( _id, true );
94       myPreviewType = previewElements;
95     }
96     //!< Destructor
97     virtual ~TPreviewMesh() { delete _myMeshDS; }
98     //!< Copy a set of elements
99     void Copy(const TIDSortedElemSet & theElements,
100               TIDSortedElemSet&        theCopyElements,
101               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
102               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
103     {
104       // loop on theIDsOfElements
105       TIDSortedElemSet::const_iterator eIt = theElements.begin();
106       for ( ; eIt != theElements.end(); ++eIt )
107       {
108         const SMDS_MeshElement* anElem = *eIt;
109         if ( !anElem ) continue;
110         SMDSAbs_ElementType type = anElem->GetType();
111         if ( type == theAvoidType ||
112              ( theSelectType != SMDSAbs_All && type != theSelectType ))
113           continue;
114
115         if ( const SMDS_MeshElement* anElemCopy = Copy( anElem ))
116           theCopyElements.insert( theCopyElements.end(), anElemCopy );
117       }
118     }
119     //!< Copy an element
120     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
121     {
122       // copy element nodes
123       int anElemNbNodes = anElem->NbNodes();
124       vector< int > anElemNodesID( anElemNbNodes ) ;
125       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
126       for ( int i = 0; itElemNodes->more(); i++)
127       {
128         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
129         Copy( anElemNode );
130         anElemNodesID[i] = anElemNode->GetID();
131       }
132
133       // creates a corresponding element on copied nodes
134       SMDS_MeshElement* anElemCopy = 0;
135       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
136       {
137         const SMDS_PolyhedralVolumeOfNodes* ph =
138           dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem);
139         if ( ph )
140           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
141             (anElemNodesID, ph->GetQuanities(),anElem->GetID());
142       }
143       else {
144         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
145                                                           anElem->GetType(),
146                                                           anElem->IsPoly() );
147       }
148       return anElemCopy;
149     }
150     //!< Copy a node
151     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
152     {
153       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(), 
154                                       anElemNode->GetID());
155     }
156   };// struct TPreviewMesh
157
158   static SMESH_NodeSearcher *    theNodeSearcher    = 0;
159   static SMESH_ElementSearcher * theElementSearcher = 0;
160
161   //=============================================================================
162   /*!
163    * \brief Deleter of theNodeSearcher at any compute event occured
164    */
165   //=============================================================================
166
167   struct TSearchersDeleter : public SMESH_subMeshEventListener
168   {
169     SMESH_Mesh* myMesh;
170     //!< Constructor
171     TSearchersDeleter(): SMESH_subMeshEventListener( false ), // won't be deleted by submesh
172                          myMesh(0) {}
173     //!< Delete theNodeSearcher
174     static void Delete()
175     {
176       if ( theNodeSearcher )    delete theNodeSearcher;    theNodeSearcher    = 0;
177       if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
178     }
179     typedef map < int, SMESH_subMesh * > TDependsOnMap;
180     //!< The meshod called by submesh: do my main job
181     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
182                       SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
183     {
184       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
185         Delete();
186         Unset( sm->GetFather() );
187       }
188     }
189     //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
190     void Set(SMESH_Mesh* mesh)
191     {
192       if ( myMesh != mesh )
193       {
194         if ( myMesh ) {
195           Delete();
196           Unset( myMesh );
197         }
198         myMesh = mesh;
199         if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
200           const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
201           TDependsOnMap::const_iterator sm;
202           for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
203             sm->second->SetEventListener( this, 0, sm->second );
204         }
205       }
206     }
207     //!<  delete self from all submeshes
208     void Unset(SMESH_Mesh* mesh)
209     {
210       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
211         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
212         TDependsOnMap::const_iterator sm;
213         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
214           sm->second->DeleteEventListener( this );
215       }
216       myMesh = 0;
217     }
218
219   } theSearchersDeleter;
220
221   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
222   {
223     TCollection_AsciiString typeStr;
224     switch ( theMirrorType ) {
225     case  SMESH::SMESH_MeshEditor::POINT:
226       typeStr = "SMESH.SMESH_MeshEditor.POINT";
227       break;
228     case  SMESH::SMESH_MeshEditor::AXIS:
229       typeStr = "SMESH.SMESH_MeshEditor.AXIS";
230       break;
231     default:
232       typeStr = "SMESH.SMESH_MeshEditor.PLANE";
233     }
234     return typeStr;
235   }
236   //================================================================================
237   /*!
238    * \brief function for conversion long_array to TIDSortedElemSet
239    * \param IDs - array of IDs
240    * \param aMesh - mesh
241    * \param aMap - collection to fill
242    * \param aType - element type
243    */
244   //================================================================================
245
246   void arrayToSet(const SMESH::long_array & IDs,
247                   const SMESHDS_Mesh*       aMesh,
248                   TIDSortedElemSet&         aMap,
249                   const SMDSAbs_ElementType aType = SMDSAbs_All )
250   {
251     for (int i=0; i<IDs.length(); i++) {
252       CORBA::Long ind = IDs[i];
253       const SMDS_MeshElement * elem =
254         (aType == SMDSAbs_Node ? aMesh->FindNode(ind) : aMesh->FindElement(ind));
255       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
256         aMap.insert( elem );
257     }
258   }
259   //================================================================================
260   /*!
261    * \brief Retrieve elements of given type from SMESH_IDSource
262    */
263   //================================================================================
264
265   bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
266                      const SMESHDS_Mesh*        theMeshDS,
267                      TIDSortedElemSet&          theElemSet,
268                      const SMDSAbs_ElementType  theType,
269                      const bool                 emptyIfIsMesh=false)
270
271   {
272     if ( CORBA::is_nil( theIDSource ) )
273       return false;
274     if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
275       return true;
276
277     SMESH::long_array_var anIDs = theIDSource->GetIDs();
278     if ( anIDs->length() == 0 )
279       return false;
280     SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
281     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
282     {
283       if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
284         arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
285       else
286         return false;
287     }
288     else
289     {
290       arrayToSet( anIDs, theMeshDS, theElemSet, theType);
291     }
292     return true;
293   }
294   //================================================================================
295   /*!
296    * \brief Retrieve nodes from SMESH_IDSource
297    */
298   //================================================================================
299
300   void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr  theObject,
301                          const SMESHDS_Mesh*        theMeshDS,
302                          TIDSortedNodeSet&          theNodeSet)
303
304   {
305     if ( CORBA::is_nil( theObject ) )
306       return;
307     SMESH::array_of_ElementType_var types = theObject->GetTypes();
308     SMESH::long_array_var     aElementsId = theObject->GetIDs();
309     if ( types->length() == 1 && types[0] == SMESH::NODE)
310     {
311       for(int i = 0; i < aElementsId->length(); i++)
312         if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
313           theNodeSet.insert( theNodeSet.end(), n);
314     }
315     else {
316       for(int i = 0; i < aElementsId->length(); i++)
317         if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
318           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
319     }
320   }
321 }
322
323 //=============================================================================
324 /*!
325  *
326  */
327 //=============================================================================
328
329 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview)
330 {
331   myMesh_i = theMesh;
332   myMesh = & theMesh->GetImpl();
333   myPreviewMode = isPreview;
334 }
335
336 //================================================================================
337 /*!
338  * \brief Destructor
339  */
340 //================================================================================
341
342 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
343 {
344 }
345
346 //================================================================================
347 /*!
348  * \brief Clear members
349  */
350 //================================================================================
351
352 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
353 {
354   if ( myPreviewMode ) {
355     myPreviewData = new SMESH::MeshPreviewStruct();
356   }
357   else {
358     myLastCreatedElems = new SMESH::long_array();
359     myLastCreatedNodes = new SMESH::long_array();
360     if ( deleteSearchers )
361       TSearchersDeleter::Delete();
362   }
363 }
364
365 //=======================================================================
366 //function : MakeIDSource
367 //purpose  : Wrap a sequence of ids in a SMESH_IDSource
368 //=======================================================================
369
370 struct _IDSource : public POA_SMESH::SMESH_IDSource
371 {
372   SMESH::long_array     _ids;
373   SMESH::ElementType    _type;
374   SMESH::SMESH_Mesh_ptr _mesh;
375   SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
376   SMESH::long_array* GetMeshInfo() { return 0; }
377   SMESH::SMESH_Mesh_ptr GetMesh()  { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
378   SMESH::array_of_ElementType* GetTypes()
379   {
380     SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
381     types->length( 1 );
382     types[0] = _type;
383     return types._retn();
384   }
385 };
386
387 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
388                                                            SMESH::ElementType       type)
389 {
390   _IDSource* anIDSource = new _IDSource;
391   anIDSource->_ids = ids;
392   anIDSource->_type = type;
393   anIDSource->_mesh = myMesh_i->_this();
394   SMESH::SMESH_IDSource_var anIDSourceVar = anIDSource->_this();
395
396   return anIDSourceVar._retn();
397 }
398
399 //=============================================================================
400 /*!
401  *
402  */
403 //=============================================================================
404
405 CORBA::Boolean
406 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
407 {
408   initData();
409
410   ::SMESH_MeshEditor anEditor( myMesh );
411   list< int > IdList;
412
413   for (int i = 0; i < IDsOfElements.length(); i++)
414     IdList.push_back( IDsOfElements[i] );
415
416   // Update Python script
417   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
418
419   if ( IDsOfElements.length() )
420     myMesh->SetIsModified( true ); // issue 0020693
421
422   // Remove Elements
423   return anEditor.Remove( IdList, false );
424 }
425
426 //=============================================================================
427 /*!
428  *
429  */
430 //=============================================================================
431
432 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
433 {
434   initData();
435
436   ::SMESH_MeshEditor anEditor( myMesh );
437   list< int > IdList;
438   for (int i = 0; i < IDsOfNodes.length(); i++)
439     IdList.push_back( IDsOfNodes[i] );
440
441   // Update Python script
442   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
443
444   if ( IDsOfNodes.length() )
445     myMesh->SetIsModified( true ); // issue 0020693
446
447   return anEditor.Remove( IdList, true );
448 }
449
450 //=============================================================================
451 /*!
452  *
453  */
454 //=============================================================================
455
456 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
457 {
458   initData();
459
460   ::SMESH_MeshEditor anEditor( myMesh );
461
462   // Update Python script
463   TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
464
465   // Create filter to find all orphan nodes
466   SMESH::Controls::Filter::TIdSequence seq;
467   SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
468   SMESH::Controls::Filter::GetElementsId( GetMeshDS(), predicate, seq );
469
470   // remove orphan nodes (if there are any)
471   list< int > IdList;
472   for ( int i = 0; i < seq.size(); i++ )
473     IdList.push_back( seq[i] );
474
475   if ( IdList.size() )
476     myMesh->SetIsModified( true );
477
478   return anEditor.Remove( IdList, true );
479 }
480
481 //=============================================================================
482 /*!
483  *
484  */
485 //=============================================================================
486
487 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
488                                         CORBA::Double y, CORBA::Double z)
489 {
490   initData();
491
492   const SMDS_MeshNode* N = GetMeshDS()->AddNode(x, y, z);
493
494   // Update Python script
495   TPythonDump() << "nodeID = " << this << ".AddNode( "
496                 << x << ", " << y << ", " << z << " )";
497
498   myMesh->SetIsModified( true ); // issue 0020693
499
500   return N->GetID();
501 }
502
503 //=============================================================================
504 /*!
505  *
506  */
507 //=============================================================================
508 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
509 {
510   initData();
511
512   const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(IDOfNode);
513   SMDS_MeshElement* elem = GetMeshDS()->Add0DElement(aNode);
514
515   // Update Python script
516   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
517
518   myMesh->SetIsModified( true ); // issue 0020693
519
520   if (elem)
521     return elem->GetID();
522
523   return 0;
524 }
525
526 //=============================================================================
527 /*!
528  *
529  */
530 //=============================================================================
531
532 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
533 {
534   initData();
535
536   int NbNodes = IDsOfNodes.length();
537   SMDS_MeshElement* elem = 0;
538   if (NbNodes == 2)
539   {
540     CORBA::Long index1 = IDsOfNodes[0];
541     CORBA::Long index2 = IDsOfNodes[1];
542     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(index1), GetMeshDS()->FindNode(index2));
543
544     // Update Python script
545     TPythonDump() << "edge = " << this << ".AddEdge([ "
546                   << index1 << ", " << index2 <<" ])";
547   }
548   if (NbNodes == 3) {
549     CORBA::Long n1 = IDsOfNodes[0];
550     CORBA::Long n2 = IDsOfNodes[1];
551     CORBA::Long n12 = IDsOfNodes[2];
552     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(n1),
553                                 GetMeshDS()->FindNode(n2),
554                                 GetMeshDS()->FindNode(n12));
555     // Update Python script
556     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
557                   <<n1<<", "<<n2<<", "<<n12<<" ])";
558   }
559
560   if(elem)
561     return myMesh->SetIsModified( true ), elem->GetID();
562
563   return 0;
564 }
565
566 //=============================================================================
567 /*!
568  *  AddFace
569  */
570 //=============================================================================
571
572 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
573 {
574   initData();
575
576   int NbNodes = IDsOfNodes.length();
577   if (NbNodes < 3)
578   {
579     return 0;
580   }
581
582   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
583   for (int i = 0; i < NbNodes; i++)
584     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
585
586   SMDS_MeshElement* elem = 0;
587   if (NbNodes == 3) {
588     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
589   }
590   else if (NbNodes == 4) {
591     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
592   }
593   else if (NbNodes == 6) {
594     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
595                                 nodes[4], nodes[5]);
596   }
597   else if (NbNodes == 8) {
598     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
599                                 nodes[4], nodes[5], nodes[6], nodes[7]);
600   }
601   else if (NbNodes > 2) {
602     elem = GetMeshDS()->AddPolygonalFace(nodes);
603   }
604
605   // Update Python script
606   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
607
608   if(elem)
609     return myMesh->SetIsModified( true ), elem->GetID();
610
611   return 0;
612 }
613
614 //=============================================================================
615 /*!
616  *  AddPolygonalFace
617  */
618 //=============================================================================
619 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
620 {
621   initData();
622
623   int NbNodes = IDsOfNodes.length();
624   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
625   for (int i = 0; i < NbNodes; i++)
626     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
627
628   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
629
630   // Update Python script
631   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
632
633   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
634 }
635
636 //=============================================================================
637 /*!
638  *
639  */
640 //=============================================================================
641
642 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
643 {
644   initData();
645
646   int NbNodes = IDsOfNodes.length();
647   vector< const SMDS_MeshNode*> n(NbNodes);
648   for(int i=0;i<NbNodes;i++)
649     n[i]=GetMeshDS()->FindNode(IDsOfNodes[i]);
650
651   SMDS_MeshElement* elem = 0;
652   switch(NbNodes)
653   {
654   case 4 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
655   case 5 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
656   case 6 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
657   case 8 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
658   case 10:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
659                                         n[6],n[7],n[8],n[9]);
660     break;
661   case 13:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
662                                         n[7],n[8],n[9],n[10],n[11],n[12]);
663     break;
664   case 15:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
665                                         n[9],n[10],n[11],n[12],n[13],n[14]);
666     break;
667   case 20:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
668                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
669                                         n[15],n[16],n[17],n[18],n[19]);
670     break;
671   }
672
673   // Update Python script
674   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
675
676   if(elem)
677     return myMesh->SetIsModified( true ), elem->GetID();
678
679   return 0;
680 }
681
682 //=============================================================================
683 /*!
684  *  AddPolyhedralVolume
685  */
686 //=============================================================================
687 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
688                                                      const SMESH::long_array & Quantities)
689 {
690   initData();
691
692   int NbNodes = IDsOfNodes.length();
693   std::vector<const SMDS_MeshNode*> n (NbNodes);
694   for (int i = 0; i < NbNodes; i++)
695     n[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
696
697   int NbFaces = Quantities.length();
698   std::vector<int> q (NbFaces);
699   for (int j = 0; j < NbFaces; j++)
700     q[j] = Quantities[j];
701
702   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(n, q);
703
704   // Update Python script
705   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
706                 << IDsOfNodes << ", " << Quantities << " )";
707
708   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
709 }
710
711 //=============================================================================
712 /*!
713  *  AddPolyhedralVolumeByFaces
714  */
715 //=============================================================================
716 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
717 {
718   initData();
719
720   int NbFaces = IdsOfFaces.length();
721   std::vector<const SMDS_MeshNode*> poly_nodes;
722   std::vector<int> quantities (NbFaces);
723
724   for (int i = 0; i < NbFaces; i++) {
725     const SMDS_MeshElement* aFace = GetMeshDS()->FindElement(IdsOfFaces[i]);
726     quantities[i] = aFace->NbNodes();
727
728     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
729     while (It->more()) {
730       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
731     }
732   }
733
734   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
735
736   // Update Python script
737   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
738                 << IdsOfFaces << " )";
739
740   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
741 }
742
743 //=============================================================================
744 /*!
745  * \brief Bind a node to a vertex
746  * \param NodeID - node ID
747  * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
748  * \retval boolean - false if NodeID or VertexID is invalid
749  */
750 //=============================================================================
751
752 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
753   throw (SALOME::SALOME_Exception)
754 {
755   Unexpect aCatch(SALOME_SalomeException);
756
757   SMESHDS_Mesh * mesh = GetMeshDS();
758   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
759   if ( !node )
760     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
761
762   if ( mesh->MaxShapeIndex() < VertexID )
763     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
764
765   TopoDS_Shape shape = mesh->IndexToShape( VertexID );
766   if ( shape.ShapeType() != TopAbs_VERTEX )
767     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
768
769   mesh->SetNodeOnVertex( node, VertexID );
770
771   myMesh->SetIsModified( true );
772 }
773
774 //=============================================================================
775 /*!
776  * \brief Store node position on an edge
777  * \param NodeID - node ID
778  * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
779  * \param paramOnEdge - parameter on edge where the node is located
780  * \retval boolean - false if any parameter is invalid
781  */
782 //=============================================================================
783
784 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
785                                        CORBA::Double paramOnEdge)
786   throw (SALOME::SALOME_Exception)
787 {
788   Unexpect aCatch(SALOME_SalomeException);
789
790   SMESHDS_Mesh * mesh = GetMeshDS();
791   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
792   if ( !node )
793     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
794
795   if ( mesh->MaxShapeIndex() < EdgeID )
796     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
797
798   TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
799   if ( shape.ShapeType() != TopAbs_EDGE )
800     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
801
802   Standard_Real f,l;
803   BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
804   if ( paramOnEdge < f || paramOnEdge > l )
805     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
806
807   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
808
809   myMesh->SetIsModified( true );
810 }
811
812 //=============================================================================
813 /*!
814  * \brief Store node position on a face
815  * \param NodeID - node ID
816  * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
817  * \param u - U parameter on face where the node is located
818  * \param v - V parameter on face where the node is located
819  * \retval boolean - false if any parameter is invalid
820  */
821 //=============================================================================
822
823 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
824                                        CORBA::Double u, CORBA::Double v)
825   throw (SALOME::SALOME_Exception)
826 {
827   Unexpect aCatch(SALOME_SalomeException);
828
829   SMESHDS_Mesh * mesh = GetMeshDS();
830   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
831   if ( !node )
832     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
833
834   if ( mesh->MaxShapeIndex() < FaceID )
835     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
836
837   TopoDS_Shape shape = mesh->IndexToShape( FaceID );
838   if ( shape.ShapeType() != TopAbs_FACE )
839     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
840
841   BRepAdaptor_Surface surf( TopoDS::Face( shape ));
842   bool isOut = ( u < surf.FirstUParameter() ||
843                  u > surf.LastUParameter()  ||
844                  v < surf.FirstVParameter() ||
845                  v > surf.LastVParameter() );
846
847   if ( isOut ) {
848 #ifdef _DEBUG_
849     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
850               << " u( " <<  surf.FirstUParameter() 
851               << "," <<  surf.LastUParameter()  
852               << ") v( " <<  surf.FirstVParameter() 
853               << "," <<  surf.LastVParameter() << ")" );
854 #endif    
855     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
856   }
857
858   mesh->SetNodeOnFace( node, FaceID, u, v );
859
860   myMesh->SetIsModified( true );
861 }
862
863 //=============================================================================
864 /*!
865  * \brief Bind a node to a solid
866  * \param NodeID - node ID
867  * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
868  * \retval boolean - false if NodeID or SolidID is invalid
869  */
870 //=============================================================================
871
872 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
873   throw (SALOME::SALOME_Exception)
874 {
875   Unexpect aCatch(SALOME_SalomeException);
876
877   SMESHDS_Mesh * mesh = GetMeshDS();
878   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
879   if ( !node )
880     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
881
882   if ( mesh->MaxShapeIndex() < SolidID )
883     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
884
885   TopoDS_Shape shape = mesh->IndexToShape( SolidID );
886   if ( shape.ShapeType() != TopAbs_SOLID &&
887        shape.ShapeType() != TopAbs_SHELL)
888     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
889
890   mesh->SetNodeInVolume( node, SolidID );
891
892   // myMesh->SetIsModified( true ); - SetNodeInVolume() can't prevent re-compute, I believe
893 }
894
895 //=============================================================================
896 /*!
897  * \brief Bind an element to a shape
898  * \param ElementID - element ID
899  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
900  * \retval boolean - false if ElementID or ShapeID is invalid
901  */
902 //=============================================================================
903
904 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
905                                                CORBA::Long ShapeID)
906   throw (SALOME::SALOME_Exception)
907 {
908   Unexpect aCatch(SALOME_SalomeException);
909
910   SMESHDS_Mesh * mesh = GetMeshDS();
911   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
912   if ( !elem )
913     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
914
915   if ( mesh->MaxShapeIndex() < ShapeID )
916     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
917
918   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
919   if ( shape.ShapeType() != TopAbs_EDGE &&
920        shape.ShapeType() != TopAbs_FACE &&
921        shape.ShapeType() != TopAbs_SOLID &&
922        shape.ShapeType() != TopAbs_SHELL )
923     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
924
925   mesh->SetMeshElementOnShape( elem, ShapeID );
926
927   myMesh->SetIsModified( true );
928 }
929
930 //=============================================================================
931 /*!
932  *
933  */
934 //=============================================================================
935
936 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
937                                                CORBA::Long NodeID2)
938 {
939   initData();
940
941   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
942   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
943   if ( !n1 || !n2 )
944     return false;
945
946   // Update Python script
947   TPythonDump() << "isDone = " << this << ".InverseDiag( "
948                 << NodeID1 << ", " << NodeID2 << " )";
949
950   myMesh->SetIsModified( true );
951
952   ::SMESH_MeshEditor aMeshEditor( myMesh );
953   return aMeshEditor.InverseDiag ( n1, n2 );
954 }
955
956 //=============================================================================
957 /*!
958  *
959  */
960 //=============================================================================
961
962 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
963                                               CORBA::Long NodeID2)
964 {
965   initData();
966
967   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
968   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
969   if ( !n1 || !n2 )
970     return false;
971
972   // Update Python script
973   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
974                 << NodeID1 << ", " << NodeID2 <<  " )";
975
976   ::SMESH_MeshEditor aMeshEditor( myMesh );
977
978   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
979
980   if ( stat )
981     myMesh->SetIsModified( true ); // issue 0020693
982     
983   storeResult(aMeshEditor);
984
985   return stat;
986 }
987
988 //=============================================================================
989 /*!
990  *
991  */
992 //=============================================================================
993
994 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
995 {
996   initData();
997
998   ::SMESH_MeshEditor anEditor( myMesh );
999   for (int i = 0; i < IDsOfElements.length(); i++)
1000   {
1001     CORBA::Long index = IDsOfElements[i];
1002     const SMDS_MeshElement * elem = GetMeshDS()->FindElement(index);
1003     if ( elem )
1004       anEditor.Reorient( elem );
1005   }
1006   // Update Python script
1007   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1008
1009   if ( IDsOfElements.length() )
1010     myMesh->SetIsModified( true ); // issue 0020693
1011
1012   return true;
1013 }
1014
1015
1016 //=============================================================================
1017 /*!
1018  *
1019  */
1020 //=============================================================================
1021
1022 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1023 {
1024   initData();
1025
1026   TPythonDump aTPythonDump; // suppress dump in Reorient()
1027
1028   SMESH::long_array_var anElementsId = theObject->GetIDs();
1029   CORBA::Boolean isDone = Reorient(anElementsId);
1030
1031   // Update Python script
1032   aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1033
1034   return isDone;
1035 }
1036
1037 //=============================================================================
1038 /*!
1039  *
1040  */
1041 //=============================================================================
1042 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
1043                                               SMESH::NumericalFunctor_ptr Criterion,
1044                                               CORBA::Double               MaxAngle)
1045 {
1046   initData();
1047
1048   SMESHDS_Mesh* aMesh = GetMeshDS();
1049   TIDSortedElemSet faces;
1050   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1051
1052   SMESH::NumericalFunctor_i* aNumericalFunctor =
1053     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1054   SMESH::Controls::NumericalFunctorPtr aCrit;
1055   if ( !aNumericalFunctor )
1056     aCrit.reset( new SMESH::Controls::AspectRatio() );
1057   else
1058     aCrit = aNumericalFunctor->GetNumericalFunctor();
1059
1060   // Update Python script
1061   TPythonDump() << "isDone = " << this << ".TriToQuad( "
1062                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
1063
1064   ::SMESH_MeshEditor anEditor( myMesh );
1065
1066   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
1067   if ( stat )
1068     myMesh->SetIsModified( true ); // issue 0020693
1069
1070   storeResult(anEditor);
1071
1072   return stat;
1073 }
1074
1075
1076 //=============================================================================
1077 /*!
1078  *
1079  */
1080 //=============================================================================
1081 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
1082                                                     SMESH::NumericalFunctor_ptr Criterion,
1083                                                     CORBA::Double               MaxAngle)
1084 {
1085   initData();
1086
1087   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
1088   SMESH::long_array_var anElementsId = theObject->GetIDs();
1089   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1090
1091   SMESH::NumericalFunctor_i* aNumericalFunctor =
1092     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1093
1094   // Update Python script
1095   aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1096                << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
1097
1098   return isDone;
1099 }
1100
1101
1102 //=============================================================================
1103 /*!
1104  *
1105  */
1106 //=============================================================================
1107 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
1108                                               SMESH::NumericalFunctor_ptr Criterion)
1109 {
1110   initData();
1111
1112   SMESHDS_Mesh* aMesh = GetMeshDS();
1113   TIDSortedElemSet faces;
1114   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1115
1116   SMESH::NumericalFunctor_i* aNumericalFunctor =
1117     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1118   SMESH::Controls::NumericalFunctorPtr aCrit;
1119   if ( !aNumericalFunctor )
1120     aCrit.reset( new SMESH::Controls::AspectRatio() );
1121   else
1122     aCrit = aNumericalFunctor->GetNumericalFunctor();
1123
1124
1125   // Update Python script
1126   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1127
1128   ::SMESH_MeshEditor anEditor( myMesh );
1129   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
1130   if ( stat )
1131     myMesh->SetIsModified( true ); // issue 0020693
1132
1133   storeResult(anEditor);
1134
1135   return stat;
1136 }
1137
1138
1139 //=============================================================================
1140 /*!
1141  *
1142  */
1143 //=============================================================================
1144 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1145                                                     SMESH::NumericalFunctor_ptr Criterion)
1146 {
1147   initData();
1148
1149   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
1150
1151   SMESH::long_array_var anElementsId = theObject->GetIDs();
1152   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1153
1154   SMESH::NumericalFunctor_i* aNumericalFunctor =
1155     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1156
1157   // Update Python script
1158   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1159
1160   return isDone;
1161 }
1162
1163
1164 //=============================================================================
1165 /*!
1166  *
1167  */
1168 //=============================================================================
1169 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1170                                               CORBA::Boolean            Diag13)
1171 {
1172   initData();
1173
1174   SMESHDS_Mesh* aMesh = GetMeshDS();
1175   TIDSortedElemSet faces;
1176   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1177
1178   // Update Python script
1179   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1180                 << IDsOfElements << ", " << Diag13 << " )";
1181
1182   ::SMESH_MeshEditor anEditor( myMesh );
1183   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
1184   if ( stat )
1185     myMesh->SetIsModified( true ); // issue 0020693
1186
1187
1188   storeResult(anEditor);
1189
1190   return stat;
1191 }
1192
1193
1194 //=============================================================================
1195 /*!
1196  *
1197  */
1198 //=============================================================================
1199 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1200                                                     CORBA::Boolean            Diag13)
1201 {
1202   initData();
1203
1204   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
1205
1206   SMESH::long_array_var anElementsId = theObject->GetIDs();
1207   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1208
1209   // Update Python script
1210   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1211                << theObject << ", " << Diag13 << " )";
1212
1213   return isDone;
1214 }
1215
1216
1217 //=============================================================================
1218 /*!
1219  *  BestSplit
1220  */
1221 //=============================================================================
1222 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
1223                                            SMESH::NumericalFunctor_ptr Criterion)
1224 {
1225   initData();
1226
1227   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
1228   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1229   {
1230     SMESH::NumericalFunctor_i* aNumericalFunctor =
1231       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1232     SMESH::Controls::NumericalFunctorPtr aCrit;
1233     if (aNumericalFunctor)
1234       aCrit = aNumericalFunctor->GetNumericalFunctor();
1235     else
1236       aCrit.reset(new SMESH::Controls::AspectRatio());
1237
1238     ::SMESH_MeshEditor anEditor (myMesh);
1239     return anEditor.BestSplit(quad, aCrit);
1240   }
1241   return -1;
1242 }
1243
1244 //================================================================================
1245 /*!
1246  * \brief Split volumic elements into tetrahedrons
1247  */
1248 //================================================================================
1249
1250 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
1251                                                 CORBA::Short              methodFlags)
1252   throw (SALOME::SALOME_Exception)
1253 {
1254   Unexpect aCatch(SALOME_SalomeException);
1255
1256   initData();
1257
1258   SMESH::long_array_var anElementsId = elems->GetIDs();
1259   TIDSortedElemSet elemSet;
1260   arrayToSet( anElementsId, GetMeshDS(), elemSet, SMDSAbs_Volume );
1261   
1262   ::SMESH_MeshEditor anEditor (myMesh);
1263   anEditor.SplitVolumesIntoTetra( elemSet, int( methodFlags ));
1264
1265   storeResult(anEditor);
1266
1267 //   if ( myLastCreatedElems.length() ) - it does not influence Compute()
1268 //     myMesh->SetIsModified( true ); // issue 0020693
1269
1270   TPythonDump() << this << ".SplitVolumesIntoTetra( "
1271                 << elems << ", " << methodFlags << " )";
1272 }
1273
1274 //=======================================================================
1275 //function : Smooth
1276 //purpose  :
1277 //=======================================================================
1278
1279 CORBA::Boolean
1280 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
1281                            const SMESH::long_array &              IDsOfFixedNodes,
1282                            CORBA::Long                            MaxNbOfIterations,
1283                            CORBA::Double                          MaxAspectRatio,
1284                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1285 {
1286   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1287                  MaxAspectRatio, Method, false );
1288 }
1289
1290
1291 //=======================================================================
1292 //function : SmoothParametric
1293 //purpose  :
1294 //=======================================================================
1295
1296 CORBA::Boolean
1297 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
1298                                      const SMESH::long_array &              IDsOfFixedNodes,
1299                                      CORBA::Long                            MaxNbOfIterations,
1300                                      CORBA::Double                          MaxAspectRatio,
1301                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
1302 {
1303   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1304                  MaxAspectRatio, Method, true );
1305 }
1306
1307
1308 //=======================================================================
1309 //function : SmoothObject
1310 //purpose  :
1311 //=======================================================================
1312
1313 CORBA::Boolean
1314 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1315                                  const SMESH::long_array &              IDsOfFixedNodes,
1316                                  CORBA::Long                            MaxNbOfIterations,
1317                                  CORBA::Double                          MaxAspectRatio,
1318                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
1319 {
1320   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1321                        MaxAspectRatio, Method, false);
1322 }
1323
1324
1325 //=======================================================================
1326 //function : SmoothParametricObject
1327 //purpose  :
1328 //=======================================================================
1329
1330 CORBA::Boolean
1331 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
1332                                            const SMESH::long_array &              IDsOfFixedNodes,
1333                                            CORBA::Long                            MaxNbOfIterations,
1334                                            CORBA::Double                          MaxAspectRatio,
1335                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1336 {
1337   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1338                        MaxAspectRatio, Method, true);
1339 }
1340
1341
1342 //=============================================================================
1343 /*!
1344  *
1345  */
1346 //=============================================================================
1347
1348 CORBA::Boolean
1349 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1350                            const SMESH::long_array &              IDsOfFixedNodes,
1351                            CORBA::Long                            MaxNbOfIterations,
1352                            CORBA::Double                          MaxAspectRatio,
1353                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
1354                            bool                                   IsParametric)
1355 {
1356   initData();
1357
1358   SMESHDS_Mesh* aMesh = GetMeshDS();
1359
1360   TIDSortedElemSet elements;
1361   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1362
1363   set<const SMDS_MeshNode*> fixedNodes;
1364   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1365     CORBA::Long index = IDsOfFixedNodes[i];
1366     const SMDS_MeshNode * node = aMesh->FindNode(index);
1367     if ( node )
1368       fixedNodes.insert( node );
1369   }
1370   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1371   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1372     method = ::SMESH_MeshEditor::CENTROIDAL;
1373
1374   ::SMESH_MeshEditor anEditor( myMesh );
1375   anEditor.Smooth(elements, fixedNodes, method,
1376                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1377
1378   myMesh->SetIsModified( true ); // issue 0020693
1379
1380   storeResult(anEditor);
1381
1382   // Update Python script
1383   TPythonDump() << "isDone = " << this << "."
1384                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1385                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1386                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1387                 << "SMESH.SMESH_MeshEditor."
1388                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1389                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1390
1391   return true;
1392 }
1393
1394
1395 //=============================================================================
1396 /*!
1397  *
1398  */
1399 //=============================================================================
1400
1401 CORBA::Boolean
1402 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1403                                  const SMESH::long_array &              IDsOfFixedNodes,
1404                                  CORBA::Long                            MaxNbOfIterations,
1405                                  CORBA::Double                          MaxAspectRatio,
1406                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1407                                  bool                                   IsParametric)
1408 {
1409   initData();
1410
1411   TPythonDump aTPythonDump;  // suppress dump in smooth()
1412
1413   SMESH::long_array_var anElementsId = theObject->GetIDs();
1414   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1415                                   MaxAspectRatio, Method, IsParametric);
1416
1417   // Update Python script
1418   aTPythonDump << "isDone = " << this << "."
1419                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1420                << theObject << ", " << IDsOfFixedNodes << ", "
1421                << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1422                << "SMESH.SMESH_MeshEditor."
1423                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1424                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1425
1426   return isDone;
1427 }
1428
1429
1430 //=============================================================================
1431 /*!
1432  *
1433  */
1434 //=============================================================================
1435
1436 void SMESH_MeshEditor_i::RenumberNodes()
1437 {
1438   // Update Python script
1439   TPythonDump() << this << ".RenumberNodes()";
1440
1441   GetMeshDS()->Renumber( true );
1442 }
1443
1444
1445 //=============================================================================
1446 /*!
1447  *
1448  */
1449 //=============================================================================
1450
1451 void SMESH_MeshEditor_i::RenumberElements()
1452 {
1453   // Update Python script
1454   TPythonDump() << this << ".RenumberElements()";
1455
1456   GetMeshDS()->Renumber( false );
1457 }
1458
1459 //=======================================================================
1460 /*!
1461  * \brief Return groups by their IDs
1462  */
1463 //=======================================================================
1464
1465 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
1466 {
1467   if ( !groupIDs )
1468     return 0;
1469   myMesh_i->CreateGroupServants();
1470   return myMesh_i->GetGroups( *groupIDs );
1471 }
1472
1473 //=======================================================================
1474 //function : rotationSweep
1475 //purpose  : 
1476 //=======================================================================
1477
1478 SMESH::ListOfGroups*
1479 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
1480                                   const SMESH::AxisStruct & theAxis,
1481                                   CORBA::Double             theAngleInRadians,
1482                                   CORBA::Long               theNbOfSteps,
1483                                   CORBA::Double             theTolerance,
1484                                   const bool                theMakeGroups,
1485                                   const SMDSAbs_ElementType theElementType)
1486 {
1487   initData();
1488
1489   TIDSortedElemSet inElements, copyElements;
1490   arrayToSet(theIDsOfElements, GetMeshDS(), inElements, theElementType);
1491
1492   TIDSortedElemSet* workElements = & inElements;
1493   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1494   SMESH_Mesh*       mesh = 0;
1495   bool              makeWalls=true;
1496   if ( myPreviewMode )
1497   {
1498     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1499     tmpMesh.Copy( inElements, copyElements, select, avoid );
1500     mesh = &tmpMesh;
1501     workElements = & copyElements;
1502     //makeWalls = false;
1503   }
1504   else
1505   {
1506     mesh = myMesh;
1507   }
1508
1509   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1510               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1511
1512   ::SMESH_MeshEditor anEditor( mesh );
1513   ::SMESH_MeshEditor::PGroupIDs groupIds =
1514       anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1515                               theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
1516   storeResult(anEditor);
1517
1518   //  myMesh->SetIsModified( true ); -- it does not influence Compute()
1519
1520   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1521 }
1522
1523 //=======================================================================
1524 //function : RotationSweep
1525 //purpose  :
1526 //=======================================================================
1527
1528 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1529                                        const SMESH::AxisStruct & theAxis,
1530                                        CORBA::Double             theAngleInRadians,
1531                                        CORBA::Long               theNbOfSteps,
1532                                        CORBA::Double             theTolerance)
1533 {
1534   if ( !myPreviewMode ) {
1535     TPythonDump() << this << ".RotationSweep( "
1536                   << theIDsOfElements << ", "
1537                   << theAxis << ", "
1538                   << theAngleInRadians << ", "
1539                   << theNbOfSteps << ", "
1540                   << theTolerance << " )";
1541   }
1542   rotationSweep(theIDsOfElements,
1543                 theAxis,
1544                 theAngleInRadians,
1545                 theNbOfSteps,
1546                 theTolerance,
1547                 false);
1548 }
1549
1550 //=======================================================================
1551 //function : RotationSweepMakeGroups
1552 //purpose  : 
1553 //=======================================================================
1554
1555 SMESH::ListOfGroups*
1556 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1557                                             const SMESH::AxisStruct& theAxis,
1558                                             CORBA::Double            theAngleInRadians,
1559                                             CORBA::Long              theNbOfSteps,
1560                                             CORBA::Double            theTolerance)
1561 {
1562   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
1563                                                theAxis,
1564                                                theAngleInRadians,
1565                                                theNbOfSteps,
1566                                                theTolerance,
1567                                                true);
1568   if ( !myPreviewMode ) {
1569     TPythonDump aPythonDump;
1570     DumpGroupsList(aPythonDump,aGroups);
1571     aPythonDump<< this << ".RotationSweepMakeGroups( "
1572                << theIDsOfElements << ", "
1573                << theAxis << ", "
1574                << theAngleInRadians << ", "
1575                << theNbOfSteps << ", "
1576                << theTolerance << " )";
1577   }
1578   return aGroups;
1579 }
1580
1581 //=======================================================================
1582 //function : RotationSweepObject
1583 //purpose  :
1584 //=======================================================================
1585
1586 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1587                                              const SMESH::AxisStruct & theAxis,
1588                                              CORBA::Double             theAngleInRadians,
1589                                              CORBA::Long               theNbOfSteps,
1590                                              CORBA::Double             theTolerance)
1591 {
1592   if ( !myPreviewMode ) {
1593     TPythonDump() << this << ".RotationSweepObject( "
1594                   << theObject << ", "
1595                   << theAxis << ", "
1596                   << theAngleInRadians << ", "
1597                   << theNbOfSteps << ", "
1598                   << theTolerance << " )";
1599   }
1600   SMESH::long_array_var anElementsId = theObject->GetIDs();
1601   rotationSweep(anElementsId,
1602                 theAxis,
1603                 theAngleInRadians,
1604                 theNbOfSteps,
1605                 theTolerance,
1606                 false);
1607 }
1608
1609 //=======================================================================
1610 //function : RotationSweepObject1D
1611 //purpose  :
1612 //=======================================================================
1613
1614 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1615                                                const SMESH::AxisStruct & theAxis,
1616                                                CORBA::Double             theAngleInRadians,
1617                                                CORBA::Long               theNbOfSteps,
1618                                                CORBA::Double             theTolerance)
1619 {
1620   if ( !myPreviewMode ) {
1621     TPythonDump() << this << ".RotationSweepObject1D( "
1622                   << theObject << ", "
1623                   << theAxis << ", "
1624                   << theAngleInRadians << ", "
1625                   << theNbOfSteps << ", "
1626                   << theTolerance << " )";
1627   }
1628   SMESH::long_array_var anElementsId = theObject->GetIDs();
1629   rotationSweep(anElementsId,
1630                 theAxis,
1631                 theAngleInRadians,
1632                 theNbOfSteps,
1633                 theTolerance,
1634                 false,
1635                 SMDSAbs_Edge);
1636 }
1637
1638 //=======================================================================
1639 //function : RotationSweepObject2D
1640 //purpose  :
1641 //=======================================================================
1642
1643 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1644                                                const SMESH::AxisStruct & theAxis,
1645                                                CORBA::Double             theAngleInRadians,
1646                                                CORBA::Long               theNbOfSteps,
1647                                                CORBA::Double             theTolerance)
1648 {
1649   if ( !myPreviewMode ) {
1650     TPythonDump() << this << ".RotationSweepObject2D( "
1651                   << theObject << ", "
1652                   << theAxis << ", "
1653                   << theAngleInRadians << ", "
1654                   << theNbOfSteps << ", "
1655                   << theTolerance << " )";
1656   }
1657   SMESH::long_array_var anElementsId = theObject->GetIDs();
1658   rotationSweep(anElementsId,
1659                 theAxis,
1660                 theAngleInRadians,
1661                 theNbOfSteps,
1662                 theTolerance,
1663                 false,
1664                 SMDSAbs_Face);
1665 }
1666
1667 //=======================================================================
1668 //function : RotationSweepObjectMakeGroups
1669 //purpose  : 
1670 //=======================================================================
1671
1672 SMESH::ListOfGroups*
1673 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1674                                                   const SMESH::AxisStruct&  theAxis,
1675                                                   CORBA::Double             theAngleInRadians,
1676                                                   CORBA::Long               theNbOfSteps,
1677                                                   CORBA::Double             theTolerance)
1678 {
1679   SMESH::long_array_var anElementsId = theObject->GetIDs();
1680   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1681                                                theAxis,
1682                                                theAngleInRadians,
1683                                                theNbOfSteps,
1684                                                theTolerance,
1685                                                true);
1686   if ( !myPreviewMode ) {
1687     TPythonDump aPythonDump;
1688     DumpGroupsList(aPythonDump,aGroups);
1689     aPythonDump<< this << ".RotationSweepObjectMakeGroups( "
1690                << theObject << ", "
1691                << theAxis << ", "
1692                << theAngleInRadians << ", "
1693                << theNbOfSteps << ", "
1694                << theTolerance << " )";
1695   }
1696   return aGroups;
1697 }
1698
1699 //=======================================================================
1700 //function : RotationSweepObject1DMakeGroups
1701 //purpose  : 
1702 //=======================================================================
1703
1704 SMESH::ListOfGroups*
1705 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1706                                                     const SMESH::AxisStruct&  theAxis,
1707                                                     CORBA::Double             theAngleInRadians,
1708                                                     CORBA::Long               theNbOfSteps,
1709                                                     CORBA::Double             theTolerance)
1710 {
1711   SMESH::long_array_var anElementsId = theObject->GetIDs();
1712   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1713                                                theAxis,
1714                                                theAngleInRadians,
1715                                                theNbOfSteps,
1716                                                theTolerance,
1717                                                true,
1718                                                SMDSAbs_Edge);
1719   if ( !myPreviewMode ) {
1720     TPythonDump aPythonDump;
1721     DumpGroupsList(aPythonDump,aGroups);
1722     aPythonDump<< this << ".RotationSweepObject1DMakeGroups( "
1723                << theObject << ", "
1724                << theAxis << ", "
1725                << theAngleInRadians << ", "
1726                << theNbOfSteps << ", "
1727                << theTolerance << " )";
1728   }
1729   return aGroups;
1730 }
1731
1732 //=======================================================================
1733 //function : RotationSweepObject2DMakeGroups
1734 //purpose  : 
1735 //=======================================================================
1736
1737 SMESH::ListOfGroups*
1738 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1739                                                     const SMESH::AxisStruct&  theAxis,
1740                                                     CORBA::Double             theAngleInRadians,
1741                                                     CORBA::Long               theNbOfSteps,
1742                                                     CORBA::Double             theTolerance)
1743 {
1744   SMESH::long_array_var anElementsId = theObject->GetIDs();
1745   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1746                                                theAxis,
1747                                                theAngleInRadians,
1748                                                theNbOfSteps,
1749                                                theTolerance,
1750                                                true,
1751                                                SMDSAbs_Face);
1752   if ( !myPreviewMode ) {
1753     TPythonDump aPythonDump;
1754     DumpGroupsList(aPythonDump,aGroups);
1755     aPythonDump<< this << ".RotationSweepObject2DMakeGroups( "
1756                << theObject << ", "
1757                << theAxis << ", "
1758                << theAngleInRadians << ", "
1759                << theNbOfSteps << ", "
1760                << theTolerance << " )";
1761   }
1762   return aGroups;
1763 }
1764
1765
1766 //=======================================================================
1767 //function : extrusionSweep
1768 //purpose  : 
1769 //=======================================================================
1770
1771 SMESH::ListOfGroups*
1772 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
1773                                    const SMESH::DirStruct &  theStepVector,
1774                                    CORBA::Long               theNbOfSteps,
1775                                    const bool                theMakeGroups,
1776                                    const SMDSAbs_ElementType theElementType)
1777 {
1778   initData();
1779
1780   try {   
1781 #ifdef NO_CAS_CATCH
1782     OCC_CATCH_SIGNALS;
1783 #endif
1784     TIDSortedElemSet elements;
1785     arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
1786
1787     const SMESH::PointStruct * P = &theStepVector.PS;
1788     gp_Vec stepVec( P->x, P->y, P->z );
1789
1790     TElemOfElemListMap aHystory;
1791     ::SMESH_MeshEditor anEditor( myMesh );
1792     ::SMESH_MeshEditor::PGroupIDs groupIds =
1793         anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
1794
1795     storeResult(anEditor);
1796
1797     return theMakeGroups ? getGroups(groupIds.get()) : 0;
1798
1799   } catch(Standard_Failure) {
1800     Handle(Standard_Failure) aFail = Standard_Failure::Caught();          
1801     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1802   }
1803   return 0;
1804 }
1805
1806 //=======================================================================
1807 //function : ExtrusionSweep
1808 //purpose  :
1809 //=======================================================================
1810
1811 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1812                                         const SMESH::DirStruct &  theStepVector,
1813                                         CORBA::Long               theNbOfSteps)
1814 {
1815   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
1816   if ( !myPreviewMode ) {
1817     TPythonDump() << this << ".ExtrusionSweep( "
1818                   << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1819   }
1820 }
1821
1822
1823 //=======================================================================
1824 //function : ExtrusionSweepObject
1825 //purpose  :
1826 //=======================================================================
1827
1828 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1829                                               const SMESH::DirStruct &  theStepVector,
1830                                               CORBA::Long               theNbOfSteps)
1831 {
1832   SMESH::long_array_var anElementsId = theObject->GetIDs();
1833   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
1834   if ( !myPreviewMode ) {
1835     TPythonDump() << this << ".ExtrusionSweepObject( "
1836                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1837   }
1838 }
1839
1840 //=======================================================================
1841 //function : ExtrusionSweepObject1D
1842 //purpose  :
1843 //=======================================================================
1844
1845 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1846                                                 const SMESH::DirStruct &  theStepVector,
1847                                                 CORBA::Long               theNbOfSteps)
1848 {
1849   SMESH::long_array_var anElementsId = theObject->GetIDs();
1850   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
1851   if ( !myPreviewMode ) {
1852     TPythonDump() << this << ".ExtrusionSweepObject1D( "
1853                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1854   }
1855 }
1856
1857 //=======================================================================
1858 //function : ExtrusionSweepObject2D
1859 //purpose  :
1860 //=======================================================================
1861
1862 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1863                                                 const SMESH::DirStruct &  theStepVector,
1864                                                 CORBA::Long               theNbOfSteps)
1865 {
1866   SMESH::long_array_var anElementsId = theObject->GetIDs();
1867   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
1868   if ( !myPreviewMode ) {
1869     TPythonDump() << this << ".ExtrusionSweepObject2D( "
1870                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1871   }
1872 }
1873
1874 //=======================================================================
1875 //function : ExtrusionSweepMakeGroups
1876 //purpose  : 
1877 //=======================================================================
1878
1879 SMESH::ListOfGroups*
1880 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1881                                              const SMESH::DirStruct&  theStepVector,
1882                                              CORBA::Long              theNbOfSteps)
1883 {
1884   SMESH::ListOfGroups* aGroups = extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, true );
1885
1886   if ( !myPreviewMode ) {
1887     TPythonDump aPythonDump;
1888     DumpGroupsList(aPythonDump,aGroups);
1889     aPythonDump  << this << ".ExtrusionSweepMakeGroups( "
1890                  << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1891   }
1892   return aGroups;
1893 }
1894 //=======================================================================
1895 //function : ExtrusionSweepObjectMakeGroups
1896 //purpose  : 
1897 //=======================================================================
1898
1899 SMESH::ListOfGroups*
1900 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1901                                                    const SMESH::DirStruct&   theStepVector,
1902                                                    CORBA::Long               theNbOfSteps)
1903 {
1904   SMESH::long_array_var anElementsId = theObject->GetIDs();
1905   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true );
1906
1907   if ( !myPreviewMode ) {
1908     TPythonDump aPythonDump;
1909     DumpGroupsList(aPythonDump,aGroups);
1910     aPythonDump<< this << ".ExtrusionSweepObjectMakeGroups( "
1911                << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1912   }
1913   return aGroups;
1914 }
1915
1916 //=======================================================================
1917 //function : ExtrusionSweepObject1DMakeGroups
1918 //purpose  : 
1919 //=======================================================================
1920
1921 SMESH::ListOfGroups*
1922 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1923                                                      const SMESH::DirStruct&   theStepVector,
1924                                                      CORBA::Long               theNbOfSteps)
1925 {
1926   SMESH::long_array_var anElementsId = theObject->GetIDs();
1927   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Edge );
1928   if ( !myPreviewMode ) {
1929     TPythonDump aPythonDump;
1930     DumpGroupsList(aPythonDump,aGroups);
1931     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( "
1932                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1933   }
1934   return aGroups;
1935 }
1936
1937 //=======================================================================
1938 //function : ExtrusionSweepObject2DMakeGroups
1939 //purpose  : 
1940 //=======================================================================
1941
1942 SMESH::ListOfGroups*
1943 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1944                                                      const SMESH::DirStruct&   theStepVector,
1945                                                      CORBA::Long               theNbOfSteps)
1946 {
1947   SMESH::long_array_var anElementsId = theObject->GetIDs();
1948   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Face );
1949   if ( !myPreviewMode ) {
1950     TPythonDump aPythonDump;
1951     DumpGroupsList(aPythonDump,aGroups);
1952     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( "
1953                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1954   }
1955   return aGroups;
1956 }
1957
1958
1959 //=======================================================================
1960 //function : advancedExtrusion
1961 //purpose  : 
1962 //=======================================================================
1963
1964 SMESH::ListOfGroups*
1965 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
1966                                       const SMESH::DirStruct &  theStepVector,
1967                                       CORBA::Long               theNbOfSteps,
1968                                       CORBA::Long               theExtrFlags,
1969                                       CORBA::Double             theSewTolerance,
1970                                       const bool                theMakeGroups)
1971 {
1972   initData();
1973
1974   TIDSortedElemSet elements;
1975   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
1976
1977   const SMESH::PointStruct * P = &theStepVector.PS;
1978   gp_Vec stepVec( P->x, P->y, P->z );
1979
1980   ::SMESH_MeshEditor anEditor( myMesh );
1981   TElemOfElemListMap aHystory;
1982   ::SMESH_MeshEditor::PGroupIDs groupIds =
1983       anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
1984                                theMakeGroups, theExtrFlags, theSewTolerance);
1985   storeResult(anEditor);
1986
1987   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1988 }
1989
1990 //=======================================================================
1991 //function : AdvancedExtrusion
1992 //purpose  :
1993 //=======================================================================
1994
1995 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
1996                                            const SMESH::DirStruct &  theStepVector,
1997                                            CORBA::Long               theNbOfSteps,
1998                                            CORBA::Long               theExtrFlags,
1999                                            CORBA::Double             theSewTolerance)
2000 {
2001   if ( !myPreviewMode ) {
2002     TPythonDump() << "stepVector = " << theStepVector;
2003     TPythonDump() << this << ".AdvancedExtrusion("
2004                   << theIDsOfElements
2005                   << ", stepVector, "
2006                   << theNbOfSteps << ","
2007                   << theExtrFlags << ", "
2008                   << theSewTolerance <<  " )";
2009   }
2010   advancedExtrusion( theIDsOfElements,
2011                      theStepVector,
2012                      theNbOfSteps,
2013                      theExtrFlags,
2014                      theSewTolerance,
2015                      false);
2016 }
2017
2018 //=======================================================================
2019 //function : AdvancedExtrusionMakeGroups
2020 //purpose  : 
2021 //=======================================================================
2022
2023 SMESH::ListOfGroups*
2024 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
2025                                                 const SMESH::DirStruct&  theStepVector,
2026                                                 CORBA::Long              theNbOfSteps,
2027                                                 CORBA::Long              theExtrFlags,
2028                                                 CORBA::Double            theSewTolerance)
2029 {
2030   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
2031                                                      theStepVector,
2032                                                      theNbOfSteps,
2033                                                      theExtrFlags,
2034                                                      theSewTolerance,
2035                                                      true);
2036
2037   if ( !myPreviewMode ) {
2038     TPythonDump() << "stepVector = " << theStepVector;
2039     TPythonDump aPythonDump;
2040     DumpGroupsList(aPythonDump,aGroups);
2041     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
2042                 << theIDsOfElements
2043                 << ", stepVector, "
2044                 << theNbOfSteps << ","
2045                 << theExtrFlags << ", "
2046                 << theSewTolerance <<  " )";
2047   }
2048   return aGroups;
2049 }
2050
2051
2052 //================================================================================
2053 /*!
2054  * \brief Convert extrusion error to IDL enum
2055  */
2056 //================================================================================
2057
2058 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2059
2060 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
2061 {
2062   switch ( e ) {
2063     RETCASE( EXTR_OK );
2064     RETCASE( EXTR_NO_ELEMENTS );
2065     RETCASE( EXTR_PATH_NOT_EDGE );
2066     RETCASE( EXTR_BAD_PATH_SHAPE );
2067     RETCASE( EXTR_BAD_STARTING_NODE );
2068     RETCASE( EXTR_BAD_ANGLES_NUMBER );
2069     RETCASE( EXTR_CANT_GET_TANGENT );
2070   }
2071   return SMESH::SMESH_MeshEditor::EXTR_OK;
2072 }
2073
2074
2075 //=======================================================================
2076 //function : extrusionAlongPath
2077 //purpose  : 
2078 //=======================================================================
2079
2080 SMESH::ListOfGroups*
2081 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2082                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2083                                        GEOM::GEOM_Object_ptr       thePathShape,
2084                                        CORBA::Long                 theNodeStart,
2085                                        CORBA::Boolean              theHasAngles,
2086                                        const SMESH::double_array & theAngles,
2087                                        CORBA::Boolean              theHasRefPoint,
2088                                        const SMESH::PointStruct &  theRefPoint,
2089                                        const bool                  theMakeGroups,
2090                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
2091                                        const SMDSAbs_ElementType   theElementType)
2092 {
2093   initData();
2094
2095   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
2096     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2097     return 0;
2098   }
2099   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2100
2101   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2102   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2103
2104   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
2105     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2106     return 0;
2107   }
2108
2109   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2110   if ( !nodeStart ) {
2111     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2112     return 0;
2113   }
2114
2115   TIDSortedElemSet elements;
2116   arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
2117
2118   list<double> angles;
2119   for (int i = 0; i < theAngles.length(); i++) {
2120     angles.push_back( theAngles[i] );
2121   }
2122
2123   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2124
2125   int nbOldGroups = myMesh->NbGroup();
2126
2127   ::SMESH_MeshEditor anEditor( myMesh );
2128   ::SMESH_MeshEditor::Extrusion_Error error =
2129       anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
2130                                     theHasAngles, angles, false,
2131                                     theHasRefPoint, refPnt, theMakeGroups );
2132   storeResult(anEditor);
2133   theError = convExtrError( error );
2134
2135   if ( theMakeGroups ) {
2136     list<int> groupIDs = myMesh->GetGroupIds();
2137     list<int>::iterator newBegin = groupIDs.begin();
2138     std::advance( newBegin, nbOldGroups ); // skip old groups
2139     groupIDs.erase( groupIDs.begin(), newBegin );
2140     return getGroups( & groupIDs );
2141   }
2142   return 0;
2143 }
2144
2145
2146 //=======================================================================
2147 //function : extrusionAlongPathX
2148 //purpose  : 
2149 //=======================================================================
2150
2151 SMESH::ListOfGroups*
2152 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
2153                                         SMESH::SMESH_IDSource_ptr  Path,
2154                                         CORBA::Long                NodeStart,
2155                                         CORBA::Boolean             HasAngles,
2156                                         const SMESH::double_array& Angles,
2157                                         CORBA::Boolean             LinearVariation,
2158                                         CORBA::Boolean             HasRefPoint,
2159                                         const SMESH::PointStruct&  RefPoint,
2160                                         const bool                 MakeGroups,
2161                                         const SMDSAbs_ElementType  ElementType,
2162                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
2163 {
2164   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
2165
2166   initData();
2167
2168   list<double> angles;
2169   for (int i = 0; i < Angles.length(); i++) {
2170     angles.push_back( Angles[i] );
2171   }
2172   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
2173   int nbOldGroups = myMesh->NbGroup();
2174
2175   if ( Path->_is_nil() ) {
2176     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2177     return EmptyGr;
2178   }
2179
2180   TIDSortedElemSet elements;
2181   arrayToSet(IDsOfElements, GetMeshDS(), elements, ElementType);
2182
2183   ::SMESH_MeshEditor anEditor( myMesh );
2184   ::SMESH_MeshEditor::Extrusion_Error error;
2185
2186   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path );
2187   if(aMeshImp) {
2188     // path as mesh
2189     SMDS_MeshNode* aNodeStart = 
2190       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2191     if ( !aNodeStart ) {
2192       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2193       return EmptyGr;
2194     }
2195     error = anEditor.ExtrusionAlongTrack( elements, &(aMeshImp->GetImpl()), aNodeStart,
2196                                           HasAngles, angles, LinearVariation,
2197                                           HasRefPoint, refPnt, MakeGroups );
2198   }
2199   else {
2200     SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path );
2201     if(aSubMeshImp) {
2202       // path as submesh
2203       SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
2204       aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
2205       SMDS_MeshNode* aNodeStart = 
2206         (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2207       if ( !aNodeStart ) {
2208         Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2209         return EmptyGr;
2210       }
2211       SMESH_subMesh* aSubMesh = 
2212         aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
2213       error = anEditor.ExtrusionAlongTrack( elements, aSubMesh, aNodeStart,
2214                                             HasAngles, angles, LinearVariation,
2215                                             HasRefPoint, refPnt, MakeGroups );
2216     }
2217     else {
2218       SMESH_Group_i* aGroupImp = SMESH::DownCast<SMESH_Group_i*>( Path );
2219       if(aGroupImp) {
2220         // path as group of 1D elements
2221       }
2222       else {
2223         // invalid path
2224         Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2225         return EmptyGr;
2226       }
2227     }
2228   }
2229
2230   storeResult(anEditor);
2231   Error = convExtrError( error );
2232
2233   if ( MakeGroups ) {
2234     list<int> groupIDs = myMesh->GetGroupIds();
2235     list<int>::iterator newBegin = groupIDs.begin();
2236     std::advance( newBegin, nbOldGroups ); // skip old groups
2237     groupIDs.erase( groupIDs.begin(), newBegin );
2238     return getGroups( & groupIDs );
2239   }
2240   return EmptyGr;
2241 }
2242
2243
2244 //=======================================================================
2245 //function : ExtrusionAlongPath
2246 //purpose  :
2247 //=======================================================================
2248
2249 SMESH::SMESH_MeshEditor::Extrusion_Error
2250 SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2251                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2252                                        GEOM::GEOM_Object_ptr       thePathShape,
2253                                        CORBA::Long                 theNodeStart,
2254                                        CORBA::Boolean              theHasAngles,
2255                                        const SMESH::double_array & theAngles,
2256                                        CORBA::Boolean              theHasRefPoint,
2257                                        const SMESH::PointStruct &  theRefPoint)
2258 {
2259   if ( !myPreviewMode ) {
2260     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
2261                   << theIDsOfElements << ", "
2262                   << thePathMesh      << ", "
2263                   << thePathShape     << ", "
2264                   << theNodeStart     << ", "
2265                   << theHasAngles     << ", "
2266                   << theAngles        << ", "
2267                   << theHasRefPoint   << ", "
2268                   << "SMESH.PointStruct( "
2269                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2270                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2271                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2272   }
2273   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2274   extrusionAlongPath( theIDsOfElements,
2275                       thePathMesh,
2276                       thePathShape,
2277                       theNodeStart,
2278                       theHasAngles,
2279                       theAngles,
2280                       theHasRefPoint,
2281                       theRefPoint,
2282                       false,
2283                       anError);
2284   return anError;
2285 }
2286
2287 //=======================================================================
2288 //function : ExtrusionAlongPathObject
2289 //purpose  :
2290 //=======================================================================
2291
2292 SMESH::SMESH_MeshEditor::Extrusion_Error
2293 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
2294                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
2295                                              GEOM::GEOM_Object_ptr       thePathShape,
2296                                              CORBA::Long                 theNodeStart,
2297                                              CORBA::Boolean              theHasAngles,
2298                                              const SMESH::double_array & theAngles,
2299                                              CORBA::Boolean              theHasRefPoint,
2300                                              const SMESH::PointStruct &  theRefPoint)
2301 {
2302   if ( !myPreviewMode ) {
2303     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
2304                   << theObject        << ", "
2305                   << thePathMesh      << ", "
2306                   << thePathShape     << ", "
2307                   << theNodeStart     << ", "
2308                   << theHasAngles     << ", "
2309                   << theAngles        << ", "
2310                   << theHasRefPoint   << ", "
2311                   << "SMESH.PointStruct( "
2312                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2313                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2314                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2315   }
2316   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2317   SMESH::long_array_var anElementsId = theObject->GetIDs();
2318   extrusionAlongPath( anElementsId,
2319                       thePathMesh,
2320                       thePathShape,
2321                       theNodeStart,
2322                       theHasAngles,
2323                       theAngles,
2324                       theHasRefPoint,
2325                       theRefPoint,
2326                       false,
2327                       anError);
2328   return anError;
2329 }
2330
2331 //=======================================================================
2332 //function : ExtrusionAlongPathObject1D
2333 //purpose  :
2334 //=======================================================================
2335
2336 SMESH::SMESH_MeshEditor::Extrusion_Error
2337 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
2338                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2339                                                GEOM::GEOM_Object_ptr       thePathShape,
2340                                                CORBA::Long                 theNodeStart,
2341                                                CORBA::Boolean              theHasAngles,
2342                                                const SMESH::double_array & theAngles,
2343                                                CORBA::Boolean              theHasRefPoint,
2344                                                const SMESH::PointStruct &  theRefPoint)
2345 {
2346   if ( !myPreviewMode ) {
2347     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
2348                   << theObject        << ", "
2349                   << thePathMesh      << ", "
2350                   << thePathShape     << ", "
2351                   << theNodeStart     << ", "
2352                   << theHasAngles     << ", "
2353                   << theAngles        << ", "
2354                   << theHasRefPoint   << ", "
2355                   << "SMESH.PointStruct( "
2356                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2357                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2358                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2359   }
2360   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2361   SMESH::long_array_var anElementsId = theObject->GetIDs();
2362   extrusionAlongPath( anElementsId,
2363                       thePathMesh,
2364                       thePathShape,
2365                       theNodeStart,
2366                       theHasAngles,
2367                       theAngles,
2368                       theHasRefPoint,
2369                       theRefPoint,
2370                       false,
2371                       anError,
2372                       SMDSAbs_Edge);
2373   return anError;
2374 }
2375
2376 //=======================================================================
2377 //function : ExtrusionAlongPathObject2D
2378 //purpose  :
2379 //=======================================================================
2380
2381 SMESH::SMESH_MeshEditor::Extrusion_Error
2382 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
2383                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2384                                                GEOM::GEOM_Object_ptr       thePathShape,
2385                                                CORBA::Long                 theNodeStart,
2386                                                CORBA::Boolean              theHasAngles,
2387                                                const SMESH::double_array & theAngles,
2388                                                CORBA::Boolean              theHasRefPoint,
2389                                                const SMESH::PointStruct &  theRefPoint)
2390 {
2391   if ( !myPreviewMode ) {
2392     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
2393                   << theObject        << ", "
2394                   << thePathMesh      << ", "
2395                   << thePathShape     << ", "
2396                   << theNodeStart     << ", "
2397                   << theHasAngles     << ", "
2398                   << theAngles        << ", "
2399                   << theHasRefPoint   << ", "
2400                   << "SMESH.PointStruct( "
2401                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2402                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2403                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2404   }
2405   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2406   SMESH::long_array_var anElementsId = theObject->GetIDs();
2407   extrusionAlongPath( anElementsId,
2408                       thePathMesh,
2409                       thePathShape,
2410                       theNodeStart,
2411                       theHasAngles,
2412                       theAngles,
2413                       theHasRefPoint,
2414                       theRefPoint,
2415                       false,
2416                       anError,
2417                       SMDSAbs_Face);
2418   return anError;
2419 }
2420
2421
2422 //=======================================================================
2423 //function : ExtrusionAlongPathMakeGroups
2424 //purpose  : 
2425 //=======================================================================
2426
2427 SMESH::ListOfGroups*
2428 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
2429                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
2430                                                  GEOM::GEOM_Object_ptr      thePathShape,
2431                                                  CORBA::Long                theNodeStart,
2432                                                  CORBA::Boolean             theHasAngles,
2433                                                  const SMESH::double_array& theAngles,
2434                                                  CORBA::Boolean             theHasRefPoint,
2435                                                  const SMESH::PointStruct&  theRefPoint,
2436                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2437 {
2438   SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
2439                                                        thePathMesh,
2440                                                        thePathShape,
2441                                                        theNodeStart,
2442                                                        theHasAngles,
2443                                                        theAngles,
2444                                                        theHasRefPoint,
2445                                                        theRefPoint,
2446                                                        true,
2447                                                        Error);
2448   if ( !myPreviewMode ) {
2449     bool isDumpGroups = aGroups && aGroups->length() > 0;
2450     TPythonDump aPythonDump;
2451     if(isDumpGroups) {
2452       aPythonDump << "("<<aGroups;
2453     }
2454     if(isDumpGroups)
2455       aPythonDump << ", error)";
2456     else
2457       aPythonDump <<"error";
2458
2459     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
2460                << theIDsOfElements << ", "
2461                << thePathMesh      << ", "
2462                << thePathShape     << ", "
2463                << theNodeStart     << ", "
2464                << theHasAngles     << ", "
2465                << theAngles        << ", "
2466                << theHasRefPoint   << ", "
2467                << "SMESH.PointStruct( "
2468                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2469                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2470                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2471   }
2472   return aGroups;
2473 }
2474
2475 //=======================================================================
2476 //function : ExtrusionAlongPathObjectMakeGroups
2477 //purpose  : 
2478 //=======================================================================
2479
2480 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2481 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2482                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
2483                                    GEOM::GEOM_Object_ptr      thePathShape,
2484                                    CORBA::Long                theNodeStart,
2485                                    CORBA::Boolean             theHasAngles,
2486                                    const SMESH::double_array& theAngles,
2487                                    CORBA::Boolean             theHasRefPoint,
2488                                    const SMESH::PointStruct&  theRefPoint,
2489                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2490 {
2491   SMESH::long_array_var anElementsId = theObject->GetIDs();
2492   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2493                                                       thePathMesh,
2494                                                       thePathShape,
2495                                                       theNodeStart,
2496                                                       theHasAngles,
2497                                                       theAngles,
2498                                                       theHasRefPoint,
2499                                                       theRefPoint,
2500                                                       true,
2501                                                       Error);
2502
2503   if ( !myPreviewMode ) {
2504     bool isDumpGroups = aGroups && aGroups->length() > 0;
2505     TPythonDump aPythonDump;
2506     if(isDumpGroups) {
2507       aPythonDump << "("<<aGroups;
2508     }
2509     if(isDumpGroups)
2510       aPythonDump << ", error)";
2511     else
2512       aPythonDump <<"error";
2513
2514     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
2515                 << theObject << ", "
2516                 << thePathMesh      << ", "
2517                 << thePathShape     << ", "
2518                 << theNodeStart     << ", "
2519                 << theHasAngles     << ", "
2520                 << theAngles        << ", "
2521                 << theHasRefPoint   << ", "
2522                 << "SMESH.PointStruct( "
2523                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2524                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2525                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2526   }
2527   return aGroups;
2528 }
2529
2530 //=======================================================================
2531 //function : ExtrusionAlongPathObject1DMakeGroups
2532 //purpose  : 
2533 //=======================================================================
2534
2535 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2536 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2537                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2538                                      GEOM::GEOM_Object_ptr      thePathShape,
2539                                      CORBA::Long                theNodeStart,
2540                                      CORBA::Boolean             theHasAngles,
2541                                      const SMESH::double_array& theAngles,
2542                                      CORBA::Boolean             theHasRefPoint,
2543                                      const SMESH::PointStruct&  theRefPoint,
2544                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2545 {
2546   SMESH::long_array_var anElementsId = theObject->GetIDs();
2547   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2548                                                       thePathMesh,
2549                                                       thePathShape,
2550                                                       theNodeStart,
2551                                                       theHasAngles,
2552                                                       theAngles,
2553                                                       theHasRefPoint,
2554                                                       theRefPoint,
2555                                                       true,
2556                                                       Error,
2557                                                       SMDSAbs_Edge);
2558
2559   if ( !myPreviewMode ) {
2560     bool isDumpGroups = aGroups && aGroups->length() > 0;
2561     TPythonDump aPythonDump;
2562     if(isDumpGroups) {
2563       aPythonDump << "("<<aGroups;
2564     }
2565     if(isDumpGroups)
2566       aPythonDump << ", error)";
2567     else
2568       aPythonDump <<"error";
2569
2570     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
2571                 << theObject << ", "
2572                 << thePathMesh      << ", "
2573                 << thePathShape     << ", "
2574                 << theNodeStart     << ", "
2575                 << theHasAngles     << ", "
2576                 << theAngles        << ", "
2577                 << theHasRefPoint   << ", "
2578                 << "SMESH.PointStruct( "
2579                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2580                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2581                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2582   }
2583   return aGroups;
2584 }
2585
2586 //=======================================================================
2587 //function : ExtrusionAlongPathObject2DMakeGroups
2588 //purpose  : 
2589 //=======================================================================
2590
2591 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2592 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2593                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2594                                      GEOM::GEOM_Object_ptr      thePathShape,
2595                                      CORBA::Long                theNodeStart,
2596                                      CORBA::Boolean             theHasAngles,
2597                                      const SMESH::double_array& theAngles,
2598                                      CORBA::Boolean             theHasRefPoint,
2599                                      const SMESH::PointStruct&  theRefPoint,
2600                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2601 {
2602   SMESH::long_array_var anElementsId = theObject->GetIDs();
2603   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2604                                                       thePathMesh,
2605                                                       thePathShape,
2606                                                       theNodeStart,
2607                                                       theHasAngles,
2608                                                       theAngles,
2609                                                       theHasRefPoint,
2610                                                       theRefPoint,
2611                                                       true,
2612                                                       Error,
2613                                                       SMDSAbs_Face);
2614
2615   if ( !myPreviewMode ) {
2616     bool isDumpGroups = aGroups && aGroups->length() > 0;
2617     TPythonDump aPythonDump;
2618     if(isDumpGroups) {
2619       aPythonDump << "("<<aGroups;
2620     }
2621     if(isDumpGroups)
2622       aPythonDump << ", error)";
2623     else
2624       aPythonDump <<"error";
2625
2626     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
2627                 << theObject << ", "
2628                 << thePathMesh      << ", "
2629                 << thePathShape     << ", "
2630                 << theNodeStart     << ", "
2631                 << theHasAngles     << ", "
2632                 << theAngles        << ", "
2633                 << theHasRefPoint   << ", "
2634                 << "SMESH.PointStruct( "
2635                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2636                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2637                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2638   }
2639   return aGroups;
2640 }
2641
2642
2643 //=======================================================================
2644 //function : ExtrusionAlongPathObjX
2645 //purpose  : 
2646 //=======================================================================
2647 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2648 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
2649                        SMESH::SMESH_IDSource_ptr  Path,
2650                        CORBA::Long                NodeStart,
2651                        CORBA::Boolean             HasAngles,
2652                        const SMESH::double_array& Angles,
2653                        CORBA::Boolean             LinearVariation,
2654                        CORBA::Boolean             HasRefPoint,
2655                        const SMESH::PointStruct&  RefPoint,
2656                        CORBA::Boolean             MakeGroups,
2657                        SMESH::ElementType         ElemType,
2658                        SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2659 {
2660   SMESH::long_array_var anElementsId = Object->GetIDs();
2661   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
2662                                                       Path,
2663                                                       NodeStart,
2664                                                       HasAngles,
2665                                                       Angles,
2666                                                       LinearVariation,
2667                                                       HasRefPoint,
2668                                                       RefPoint,
2669                                                       MakeGroups,
2670                                                       (SMDSAbs_ElementType)ElemType,
2671                                                       Error);
2672
2673   if ( !myPreviewMode ) {
2674     bool isDumpGroups = aGroups && aGroups->length() > 0;
2675     TPythonDump aPythonDump;
2676     if(isDumpGroups) {
2677       aPythonDump << "("<<aGroups;
2678     }
2679     if(isDumpGroups)
2680       aPythonDump << ", error)";
2681     else
2682       aPythonDump <<"error";
2683
2684     aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
2685                 << Object      << ", "
2686                 << Path        << ", "
2687                 << NodeStart   << ", "
2688                 << HasAngles   << ", "
2689                 << Angles      << ", "
2690                 << LinearVariation << ", "
2691                 << HasRefPoint << ", "
2692                 << "SMESH.PointStruct( "
2693                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2694                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2695                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2696                 << MakeGroups << ", "
2697                 << ElemType << " )";
2698   }
2699   return aGroups;
2700 }
2701
2702
2703 //=======================================================================
2704 //function : ExtrusionAlongPathX
2705 //purpose  : 
2706 //=======================================================================
2707 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2708 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
2709                     SMESH::SMESH_IDSource_ptr  Path,
2710                     CORBA::Long                NodeStart,
2711                     CORBA::Boolean             HasAngles,
2712                     const SMESH::double_array& Angles,
2713                     CORBA::Boolean             LinearVariation,
2714                     CORBA::Boolean             HasRefPoint,
2715                     const SMESH::PointStruct&  RefPoint,
2716                     CORBA::Boolean             MakeGroups,
2717                     SMESH::ElementType         ElemType,
2718                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2719 {
2720   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
2721                                                       Path,
2722                                                       NodeStart,
2723                                                       HasAngles,
2724                                                       Angles,
2725                                                       LinearVariation,
2726                                                       HasRefPoint,
2727                                                       RefPoint,
2728                                                       MakeGroups,
2729                                                       (SMDSAbs_ElementType)ElemType,
2730                                                       Error);
2731
2732   if ( !myPreviewMode ) {
2733     bool isDumpGroups = aGroups && aGroups->length() > 0;
2734     TPythonDump aPythonDump;
2735     if(isDumpGroups) {
2736       aPythonDump << "("<<aGroups;
2737     }
2738     if(isDumpGroups)
2739       aPythonDump << ", error)";
2740     else
2741       aPythonDump <<"error";
2742
2743     aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
2744                 << IDsOfElements << ", "
2745                 << Path        << ", "
2746                 << NodeStart   << ", "
2747                 << HasAngles   << ", "
2748                 << Angles      << ", "
2749                 << LinearVariation << ", "
2750                 << HasRefPoint << ", "
2751                 << "SMESH.PointStruct( "
2752                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2753                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2754                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2755                 << ElemType << " )";
2756   }
2757   return aGroups;
2758 }
2759
2760
2761 //================================================================================
2762 /*!
2763  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2764  * of given angles along path steps
2765  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
2766  *                which proceeds the extrusion
2767  * \param PathShape is shape(edge); as the mesh can be complex, the edge 
2768  *                 is used to define the sub-mesh for the path
2769  */
2770 //================================================================================
2771
2772 SMESH::double_array*
2773 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
2774                                           GEOM::GEOM_Object_ptr       thePathShape,
2775                                           const SMESH::double_array & theAngles)
2776 {
2777   SMESH::double_array_var aResult = new SMESH::double_array();
2778   int nbAngles = theAngles.length();
2779   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2780   {
2781     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2782     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2783     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2784     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2785       return aResult._retn();
2786     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2787     if ( nbSteps == nbAngles )
2788     {
2789       aResult.inout() = theAngles;
2790     }
2791     else
2792     {
2793       aResult->length( nbSteps );
2794       double rAn2St = double( nbAngles ) / double( nbSteps );
2795       double angPrev = 0, angle;
2796       for ( int iSt = 0; iSt < nbSteps; ++iSt )
2797       {
2798         double angCur = rAn2St * ( iSt+1 );
2799         double angCurFloor  = floor( angCur );
2800         double angPrevFloor = floor( angPrev );
2801         if ( angPrevFloor == angCurFloor )
2802           angle = rAn2St * theAngles[ int( angCurFloor ) ];
2803         else
2804         {
2805           int iP = int( angPrevFloor );
2806           double angPrevCeil = ceil(angPrev);
2807           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2808
2809           int iC = int( angCurFloor );
2810           if ( iC < nbAngles )
2811             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2812
2813           iP = int( angPrevCeil );
2814           while ( iC-- > iP )
2815             angle += theAngles[ iC ];
2816         }
2817         aResult[ iSt ] = angle;
2818         angPrev = angCur;
2819       }
2820     }
2821   }
2822   // Update Python script
2823   TPythonDump() << "rotAngles = " << theAngles;
2824   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2825                 << thePathMesh  << ", "
2826                 << thePathShape << ", "
2827                 << "rotAngles )";
2828
2829   return aResult._retn();
2830 }
2831
2832
2833 //=======================================================================
2834 //function : mirror
2835 //purpose  : 
2836 //=======================================================================
2837
2838 SMESH::ListOfGroups*
2839 SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
2840                            const SMESH::AxisStruct &           theAxis,
2841                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2842                            CORBA::Boolean                      theCopy,
2843                            const bool                          theMakeGroups,
2844                            ::SMESH_Mesh*                       theTargetMesh)
2845 {
2846   initData();
2847
2848   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2849   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2850
2851   gp_Trsf aTrsf;
2852   switch ( theMirrorType ) {
2853   case  SMESH::SMESH_MeshEditor::POINT:
2854     aTrsf.SetMirror( P );
2855     break;
2856   case  SMESH::SMESH_MeshEditor::AXIS:
2857     aTrsf.SetMirror( gp_Ax1( P, V ));
2858     break;
2859   default:
2860     aTrsf.SetMirror( gp_Ax2( P, V ));
2861   }
2862
2863   ::SMESH_MeshEditor anEditor( myMesh );
2864   ::SMESH_MeshEditor::PGroupIDs groupIds =
2865       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2866
2867   if(theCopy)
2868     storeResult(anEditor);
2869   else
2870     myMesh->SetIsModified( true );
2871
2872   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2873 }
2874
2875 //=======================================================================
2876 //function : Mirror
2877 //purpose  :
2878 //=======================================================================
2879
2880 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
2881                                 const SMESH::AxisStruct &           theAxis,
2882                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2883                                 CORBA::Boolean                      theCopy)
2884 {
2885   if ( !myPreviewMode ) {
2886     TPythonDump() << this << ".Mirror( "
2887                   << theIDsOfElements << ", "
2888                   << theAxis          << ", "
2889                   << mirrorTypeName(theMirrorType) << ", "
2890                   << theCopy          << " )";
2891   }
2892   if ( theIDsOfElements.length() > 0 )
2893   {
2894     TIDSortedElemSet elements;
2895     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2896     mirror(elements, theAxis, theMirrorType, theCopy, false);
2897   }
2898 }
2899
2900
2901 //=======================================================================
2902 //function : MirrorObject
2903 //purpose  :
2904 //=======================================================================
2905
2906 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
2907                                       const SMESH::AxisStruct &           theAxis,
2908                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2909                                       CORBA::Boolean                      theCopy)
2910 {
2911   if ( !myPreviewMode ) {
2912     TPythonDump() << this << ".MirrorObject( "
2913                   << theObject << ", "
2914                   << theAxis   << ", "
2915                   << mirrorTypeName(theMirrorType) << ", "
2916                   << theCopy   << " )";
2917   }
2918   TIDSortedElemSet elements;
2919   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
2920     mirror(elements, theAxis, theMirrorType, theCopy, false);
2921 }
2922
2923 //=======================================================================
2924 //function : MirrorMakeGroups
2925 //purpose  : 
2926 //=======================================================================
2927
2928 SMESH::ListOfGroups*
2929 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
2930                                      const SMESH::AxisStruct&            theMirror,
2931                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2932 {
2933   SMESH::ListOfGroups * aGroups = 0;
2934   if ( theIDsOfElements.length() > 0 )
2935   {
2936     TIDSortedElemSet elements;
2937     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2938     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
2939   }
2940   if ( !myPreviewMode ) {
2941     TPythonDump aPythonDump;
2942     DumpGroupsList(aPythonDump,aGroups);
2943     aPythonDump << this << ".MirrorMakeGroups( "
2944                 << theIDsOfElements << ", "
2945                 << theMirror << ", "
2946                 << mirrorTypeName(theMirrorType) << " )";
2947   }
2948   return aGroups;
2949 }
2950
2951 //=======================================================================
2952 //function : MirrorObjectMakeGroups
2953 //purpose  : 
2954 //=======================================================================
2955
2956 SMESH::ListOfGroups*
2957 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
2958                                            const SMESH::AxisStruct&            theMirror,
2959                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2960 {
2961   SMESH::ListOfGroups * aGroups = 0;
2962   TIDSortedElemSet elements;
2963   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
2964     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
2965
2966   if ( !myPreviewMode )
2967   {
2968     TPythonDump aPythonDump;
2969     DumpGroupsList(aPythonDump,aGroups);
2970     aPythonDump << this << ".MirrorObjectMakeGroups( "
2971                 << theObject << ", "
2972                 << theMirror << ", "
2973                 << mirrorTypeName(theMirrorType) << " )";
2974   }
2975   return aGroups;
2976 }
2977
2978 //=======================================================================
2979 //function : MirrorMakeMesh
2980 //purpose  : 
2981 //=======================================================================
2982
2983 SMESH::SMESH_Mesh_ptr
2984 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
2985                                    const SMESH::AxisStruct&            theMirror,
2986                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2987                                    CORBA::Boolean                      theCopyGroups,
2988                                    const char*                         theMeshName)
2989 {
2990   SMESH_Mesh_i* mesh_i;
2991   SMESH::SMESH_Mesh_var mesh;
2992   { // open new scope to dump "MakeMesh" command
2993     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2994
2995     TPythonDump pydump; // to prevent dump at mesh creation
2996
2997     mesh = makeMesh( theMeshName );
2998     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2999     if (mesh_i && theIDsOfElements.length() > 0 )
3000     {
3001       TIDSortedElemSet elements;
3002       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3003       mirror(elements, theMirror, theMirrorType,
3004              false, theCopyGroups, & mesh_i->GetImpl());
3005       mesh_i->CreateGroupServants();
3006     }
3007
3008     if ( !myPreviewMode ) {
3009       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3010              << theIDsOfElements << ", "
3011              << theMirror   << ", "
3012              << mirrorTypeName(theMirrorType) << ", "
3013              << theCopyGroups << ", '"
3014              << theMeshName << "' )";
3015     }
3016   }
3017
3018   //dump "GetGroups"
3019   if(!myPreviewMode && mesh_i)
3020     mesh_i->GetGroups();
3021
3022   return mesh._retn();
3023 }
3024
3025 //=======================================================================
3026 //function : MirrorObjectMakeMesh
3027 //purpose  : 
3028 //=======================================================================
3029
3030 SMESH::SMESH_Mesh_ptr
3031 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
3032                                          const SMESH::AxisStruct&            theMirror,
3033                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3034                                          CORBA::Boolean                      theCopyGroups,
3035                                          const char*                         theMeshName)
3036 {
3037   SMESH_Mesh_i* mesh_i;
3038   SMESH::SMESH_Mesh_var mesh;
3039   { // open new scope to dump "MakeMesh" command
3040     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3041
3042     TPythonDump pydump; // to prevent dump at mesh creation
3043
3044     mesh = makeMesh( theMeshName );
3045     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3046     TIDSortedElemSet elements;
3047     if ( mesh_i &&
3048          idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3049     {
3050       mirror(elements, theMirror, theMirrorType,
3051              false, theCopyGroups, & mesh_i->GetImpl());
3052       mesh_i->CreateGroupServants();
3053     }
3054     if ( !myPreviewMode ) {
3055       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3056              << theObject << ", "
3057              << theMirror   << ", "
3058              << mirrorTypeName(theMirrorType) << ", "
3059              << theCopyGroups << ", '"
3060              << theMeshName << "' )";
3061     }
3062   }
3063
3064   //dump "GetGroups"
3065   if(!myPreviewMode && mesh_i)
3066     mesh_i->GetGroups();
3067
3068   return mesh._retn();
3069 }
3070
3071 //=======================================================================
3072 //function : translate
3073 //purpose  : 
3074 //=======================================================================
3075
3076 SMESH::ListOfGroups*
3077 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
3078                               const SMESH::DirStruct &  theVector,
3079                               CORBA::Boolean            theCopy,
3080                               const bool                theMakeGroups,
3081                               ::SMESH_Mesh*             theTargetMesh)
3082 {
3083   initData();
3084
3085   gp_Trsf aTrsf;
3086   const SMESH::PointStruct * P = &theVector.PS;
3087   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3088
3089   ::SMESH_MeshEditor anEditor( myMesh );
3090   ::SMESH_MeshEditor::PGroupIDs groupIds =
3091       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3092
3093   if(theCopy)
3094     storeResult(anEditor);
3095   else
3096     myMesh->SetIsModified( true );
3097
3098   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3099 }
3100
3101 //=======================================================================
3102 //function : Translate
3103 //purpose  :
3104 //=======================================================================
3105
3106 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3107                                    const SMESH::DirStruct &  theVector,
3108                                    CORBA::Boolean            theCopy)
3109 {
3110   if ( !myPreviewMode ) {
3111     TPythonDump() << this << ".Translate( "
3112                   << theIDsOfElements << ", "
3113                   << theVector << ", "
3114                   << theCopy << " )";
3115   }
3116   if ( theIDsOfElements.length() )
3117   {
3118     TIDSortedElemSet elements;
3119     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3120     translate(elements,theVector,theCopy,false);
3121   }
3122 }
3123
3124 //=======================================================================
3125 //function : TranslateObject
3126 //purpose  :
3127 //=======================================================================
3128
3129 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3130                                          const SMESH::DirStruct &  theVector,
3131                                          CORBA::Boolean            theCopy)
3132 {
3133   if ( !myPreviewMode ) {
3134     TPythonDump() << this << ".TranslateObject( "
3135                   << theObject << ", "
3136                   << theVector << ", "
3137                   << theCopy << " )";
3138   }
3139   TIDSortedElemSet elements;
3140   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3141     translate( elements, theVector, theCopy, false);
3142 }
3143
3144 //=======================================================================
3145 //function : TranslateMakeGroups
3146 //purpose  : 
3147 //=======================================================================
3148
3149 SMESH::ListOfGroups*
3150 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3151                                         const SMESH::DirStruct&  theVector)
3152 {
3153   SMESH::ListOfGroups * aGroups = 0;
3154   if ( theIDsOfElements.length() )
3155   {
3156     TIDSortedElemSet elements;
3157     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3158     aGroups = translate(elements,theVector,true,true);
3159   }
3160   if ( !myPreviewMode ) {
3161     TPythonDump aPythonDump;
3162     DumpGroupsList(aPythonDump,aGroups);
3163     aPythonDump << this << ".TranslateMakeGroups( "
3164                 << theIDsOfElements << ", "
3165                 << theVector << " )";
3166   }
3167   return aGroups;
3168 }
3169
3170 //=======================================================================
3171 //function : TranslateObjectMakeGroups
3172 //purpose  : 
3173 //=======================================================================
3174
3175 SMESH::ListOfGroups*
3176 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3177                                               const SMESH::DirStruct&   theVector)
3178 {
3179   SMESH::ListOfGroups * aGroups = 0;
3180   TIDSortedElemSet elements;
3181   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3182     aGroups = translate(elements, theVector, true, true);
3183
3184   if ( !myPreviewMode ) {
3185
3186     TPythonDump aPythonDump;
3187     DumpGroupsList(aPythonDump,aGroups);
3188     aPythonDump << this << ".TranslateObjectMakeGroups( "
3189                 << theObject << ", "
3190                 << theVector << " )";
3191   }
3192   return aGroups;
3193 }
3194
3195 //=======================================================================
3196 //function : TranslateMakeMesh
3197 //purpose  : 
3198 //=======================================================================
3199
3200 SMESH::SMESH_Mesh_ptr
3201 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3202                                       const SMESH::DirStruct&  theVector,
3203                                       CORBA::Boolean           theCopyGroups,
3204                                       const char*              theMeshName)
3205 {
3206   SMESH_Mesh_i* mesh_i;
3207   SMESH::SMESH_Mesh_var mesh;
3208
3209   { // open new scope to dump "MakeMesh" command
3210     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3211
3212     TPythonDump pydump; // to prevent dump at mesh creation
3213
3214     mesh = makeMesh( theMeshName );
3215     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3216
3217     if ( mesh_i && theIDsOfElements.length() )
3218     {
3219       TIDSortedElemSet elements;
3220       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3221       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3222       mesh_i->CreateGroupServants();
3223     }
3224
3225     if ( !myPreviewMode ) {
3226       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3227              << theIDsOfElements << ", "
3228              << theVector   << ", "
3229              << theCopyGroups << ", '"
3230              << theMeshName << "' )";
3231     }
3232   }
3233
3234   //dump "GetGroups"
3235   if(!myPreviewMode && mesh_i)
3236     mesh_i->GetGroups();
3237
3238   return mesh._retn();
3239 }
3240
3241 //=======================================================================
3242 //function : TranslateObjectMakeMesh
3243 //purpose  : 
3244 //=======================================================================
3245
3246 SMESH::SMESH_Mesh_ptr
3247 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3248                                             const SMESH::DirStruct&   theVector,
3249                                             CORBA::Boolean            theCopyGroups,
3250                                             const char*               theMeshName)
3251 {
3252   SMESH_Mesh_i* mesh_i;
3253   SMESH::SMESH_Mesh_var mesh;
3254   { // open new scope to dump "MakeMesh" command
3255     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3256
3257     TPythonDump pydump; // to prevent dump at mesh creation
3258     mesh = makeMesh( theMeshName );
3259     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3260
3261     TIDSortedElemSet elements;
3262     if ( mesh_i &&
3263       idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3264     {
3265       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3266       mesh_i->CreateGroupServants();
3267     }
3268     if ( !myPreviewMode ) {
3269       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3270              << theObject << ", "
3271              << theVector   << ", "
3272              << theCopyGroups << ", '"
3273              << theMeshName << "' )";
3274     }
3275   }
3276
3277   //dump "GetGroups"
3278   if(!myPreviewMode && mesh_i)
3279     mesh_i->GetGroups();
3280
3281   return mesh._retn();
3282 }
3283
3284 //=======================================================================
3285 //function : rotate
3286 //purpose  : 
3287 //=======================================================================
3288
3289 SMESH::ListOfGroups*
3290 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
3291                            const SMESH::AxisStruct & theAxis,
3292                            CORBA::Double             theAngle,
3293                            CORBA::Boolean            theCopy,
3294                            const bool                theMakeGroups,
3295                            ::SMESH_Mesh*             theTargetMesh)
3296 {
3297   initData();
3298
3299   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3300   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3301
3302   gp_Trsf aTrsf;
3303   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3304
3305   ::SMESH_MeshEditor anEditor( myMesh );
3306   ::SMESH_MeshEditor::PGroupIDs groupIds =
3307       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3308
3309   if(theCopy) 
3310     storeResult(anEditor);
3311   else
3312     myMesh->SetIsModified( true );
3313
3314   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3315 }
3316
3317 //=======================================================================
3318 //function : Rotate
3319 //purpose  :
3320 //=======================================================================
3321
3322 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3323                                 const SMESH::AxisStruct & theAxis,
3324                                 CORBA::Double             theAngle,
3325                                 CORBA::Boolean            theCopy)
3326 {
3327   if ( !myPreviewMode ) {
3328     TPythonDump() << this << ".Rotate( "
3329                   << theIDsOfElements << ", "
3330                   << theAxis << ", "
3331                   << theAngle << ", "
3332                   << theCopy << " )";
3333   }
3334   if ( theIDsOfElements.length() > 0 )
3335   {
3336     TIDSortedElemSet elements;
3337     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3338     rotate(elements,theAxis,theAngle,theCopy,false);
3339   }
3340 }
3341
3342 //=======================================================================
3343 //function : RotateObject
3344 //purpose  :
3345 //=======================================================================
3346
3347 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3348                                       const SMESH::AxisStruct & theAxis,
3349                                       CORBA::Double             theAngle,
3350                                       CORBA::Boolean            theCopy)
3351 {
3352   if ( !myPreviewMode ) {
3353     TPythonDump() << this << ".RotateObject( "
3354                   << theObject << ", "
3355                   << theAxis << ", "
3356                   << theAngle << ", "
3357                   << theCopy << " )";
3358   }
3359   TIDSortedElemSet elements;
3360   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3361     rotate(elements,theAxis,theAngle,theCopy,false);
3362 }
3363
3364 //=======================================================================
3365 //function : RotateMakeGroups
3366 //purpose  : 
3367 //=======================================================================
3368
3369 SMESH::ListOfGroups*
3370 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3371                                      const SMESH::AxisStruct& theAxis,
3372                                      CORBA::Double            theAngle)
3373 {
3374   SMESH::ListOfGroups * aGroups = 0;
3375   if ( theIDsOfElements.length() > 0 )
3376   {
3377     TIDSortedElemSet elements;
3378     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3379     aGroups = rotate(elements,theAxis,theAngle,true,true);
3380   }
3381   if ( !myPreviewMode ) {
3382     TPythonDump aPythonDump;
3383     DumpGroupsList(aPythonDump,aGroups);
3384     aPythonDump << this << ".RotateMakeGroups( "
3385                 << theIDsOfElements << ", "
3386                 << theAxis << ", "
3387                 << theAngle << " )";
3388   }
3389   return aGroups;
3390 }
3391
3392 //=======================================================================
3393 //function : RotateObjectMakeGroups
3394 //purpose  : 
3395 //=======================================================================
3396
3397 SMESH::ListOfGroups*
3398 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3399                                            const SMESH::AxisStruct&  theAxis,
3400                                            CORBA::Double             theAngle)
3401 {
3402   SMESH::ListOfGroups * aGroups = 0;
3403   TIDSortedElemSet elements;
3404   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3405     aGroups =  rotate(elements,theAxis,theAngle,true,true);
3406
3407   if ( !myPreviewMode ) {
3408     TPythonDump aPythonDump;
3409     DumpGroupsList(aPythonDump,aGroups);
3410     aPythonDump << this << ".RotateObjectMakeGroups( "
3411                 << theObject << ", "
3412                 << theAxis << ", "
3413                 << theAngle << " )";
3414   }
3415   return aGroups;
3416 }
3417
3418 //=======================================================================
3419 //function : RotateMakeMesh
3420 //purpose  : 
3421 //=======================================================================
3422
3423 SMESH::SMESH_Mesh_ptr 
3424 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3425                                    const SMESH::AxisStruct& theAxis,
3426                                    CORBA::Double            theAngleInRadians,
3427                                    CORBA::Boolean           theCopyGroups,
3428                                    const char*              theMeshName)
3429 {
3430   SMESH::SMESH_Mesh_var mesh;
3431   SMESH_Mesh_i* mesh_i;
3432
3433   { // open new scope to dump "MakeMesh" command
3434     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3435
3436     TPythonDump pydump; // to prevent dump at mesh creation
3437
3438     mesh = makeMesh( theMeshName );
3439     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3440
3441     if ( mesh_i && theIDsOfElements.length() > 0 )
3442     {
3443       TIDSortedElemSet elements;
3444       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3445       rotate(elements, theAxis, theAngleInRadians,
3446              false, theCopyGroups, & mesh_i->GetImpl());
3447       mesh_i->CreateGroupServants();
3448     }
3449     if ( !myPreviewMode ) {
3450       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3451              << theIDsOfElements << ", "
3452              << theAxis << ", "
3453              << theAngleInRadians   << ", "
3454              << theCopyGroups << ", '"
3455              << theMeshName << "' )";
3456     }
3457   }
3458
3459   //dump "GetGroups"
3460   if(!myPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3461     mesh_i->GetGroups();
3462
3463   return mesh._retn();
3464 }
3465
3466 //=======================================================================
3467 //function : RotateObjectMakeMesh
3468 //purpose  : 
3469 //=======================================================================
3470
3471 SMESH::SMESH_Mesh_ptr
3472 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3473                                          const SMESH::AxisStruct&  theAxis,
3474                                          CORBA::Double             theAngleInRadians,
3475                                          CORBA::Boolean            theCopyGroups,
3476                                          const char*               theMeshName)
3477 {
3478   SMESH::SMESH_Mesh_var mesh;
3479   SMESH_Mesh_i* mesh_i;
3480
3481   {// open new scope to dump "MakeMesh" command
3482    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3483
3484     TPythonDump pydump; // to prevent dump at mesh creation
3485     mesh = makeMesh( theMeshName );
3486     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3487
3488     TIDSortedElemSet elements;
3489     if (mesh_i &&
3490         idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3491     {
3492       rotate(elements, theAxis, theAngleInRadians,
3493              false, theCopyGroups, & mesh_i->GetImpl());
3494       mesh_i->CreateGroupServants();
3495     }
3496     if ( !myPreviewMode ) {
3497       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3498              << theObject << ", "
3499              << theAxis << ", "
3500              << theAngleInRadians   << ", "
3501              << theCopyGroups << ", '"
3502              << theMeshName << "' )";
3503     }
3504   }
3505
3506   //dump "GetGroups"
3507   if(!myPreviewMode && mesh_i)
3508     mesh_i->GetGroups();
3509
3510   return mesh._retn();
3511 }
3512
3513 //=======================================================================
3514 //function : scale
3515 //purpose  : 
3516 //=======================================================================
3517
3518 SMESH::ListOfGroups*
3519 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
3520                           const SMESH::PointStruct&  thePoint,
3521                           const SMESH::double_array& theScaleFact,
3522                           CORBA::Boolean             theCopy,
3523                           const bool                 theMakeGroups,
3524                           ::SMESH_Mesh*              theTargetMesh)
3525 {
3526   initData();
3527   if ( theScaleFact.length() < 1 )
3528     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3529   if ( theScaleFact.length() == 2 )
3530     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3531
3532   TIDSortedElemSet elements;
3533   if ( !idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/true))
3534     return 0;
3535
3536   vector<double> S(3);
3537   S[0] = theScaleFact[0];
3538   S[1] = (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1];
3539   S[2] = (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2];
3540   double tol = std::numeric_limits<double>::max();
3541   gp_Trsf aTrsf;
3542   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
3543                    0,    S[1], 0,    thePoint.y * (1-S[1]),
3544                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
3545
3546   ::SMESH_MeshEditor anEditor( myMesh );
3547   ::SMESH_MeshEditor::PGroupIDs groupIds =
3548       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3549
3550   if(theCopy)
3551     storeResult(anEditor);
3552   else
3553     myMesh->SetIsModified( true );
3554
3555   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3556 }
3557
3558 //=======================================================================
3559 //function : Scale
3560 //purpose  :
3561 //=======================================================================
3562
3563 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
3564                                const SMESH::PointStruct&  thePoint,
3565                                const SMESH::double_array& theScaleFact,
3566                                CORBA::Boolean             theCopy)
3567 {
3568   if ( !myPreviewMode ) {
3569     TPythonDump() << this << ".Scale( "
3570                   << theObject << ", "
3571                   << "SMESH.PointStruct( "  << thePoint.x << ", "
3572                   << thePoint.y << ", " << thePoint.z << " ) ,"
3573                   << theScaleFact << ", "
3574                   << theCopy << " )";
3575   }
3576   scale(theObject, thePoint, theScaleFact, theCopy, false);
3577 }
3578
3579
3580 //=======================================================================
3581 //function : ScaleMakeGroups
3582 //purpose  : 
3583 //=======================================================================
3584
3585 SMESH::ListOfGroups*
3586 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3587                                     const SMESH::PointStruct&  thePoint,
3588                                     const SMESH::double_array& theScaleFact)
3589 {
3590   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3591   if ( !myPreviewMode ) {
3592
3593     TPythonDump aPythonDump;
3594     DumpGroupsList(aPythonDump,aGroups);
3595     aPythonDump << this << ".Scale("
3596                 << theObject << ","
3597                 << "SMESH.PointStruct(" <<thePoint.x << ","
3598                 << thePoint.y << "," << thePoint.z << "),"
3599                 << theScaleFact << ",True,True)";
3600   }
3601   return aGroups;
3602 }
3603
3604
3605 //=======================================================================
3606 //function : ScaleMakeMesh
3607 //purpose  : 
3608 //=======================================================================
3609
3610 SMESH::SMESH_Mesh_ptr
3611 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
3612                                   const SMESH::PointStruct&  thePoint,
3613                                   const SMESH::double_array& theScaleFact,
3614                                   CORBA::Boolean             theCopyGroups,
3615                                   const char*                theMeshName)
3616 {
3617   SMESH_Mesh_i* mesh_i;
3618   SMESH::SMESH_Mesh_var mesh;
3619   { // open new scope to dump "MakeMesh" command
3620     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3621
3622     TPythonDump pydump; // to prevent dump at mesh creation
3623     mesh = makeMesh( theMeshName );
3624     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3625
3626     if ( mesh_i )
3627     {
3628       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3629       mesh_i->CreateGroupServants();
3630     }
3631     if ( !myPreviewMode )
3632       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3633              << theObject << ", "
3634              << "SMESH.PointStruct( "  << thePoint.x << ", "
3635              << thePoint.y << ", " << thePoint.z << " ) ,"
3636              << theScaleFact << ", "
3637              << theCopyGroups << ", '"
3638              << theMeshName << "' )";
3639   }
3640
3641   //dump "GetGroups"
3642   if(!myPreviewMode && mesh_i)
3643     mesh_i->GetGroups();
3644
3645   return mesh._retn();
3646 }
3647
3648
3649 //=======================================================================
3650 //function : FindCoincidentNodes
3651 //purpose  :
3652 //=======================================================================
3653
3654 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
3655                                               SMESH::array_of_long_array_out GroupsOfNodes)
3656 {
3657   initData();
3658
3659   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3660   ::SMESH_MeshEditor anEditor( myMesh );
3661   TIDSortedNodeSet nodes; // no input nodes
3662   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3663
3664   GroupsOfNodes = new SMESH::array_of_long_array;
3665   GroupsOfNodes->length( aListOfListOfNodes.size() );
3666   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3667   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3668     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3669     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3670     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3671     aGroup.length( aListOfNodes.size() );
3672     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3673       aGroup[ j ] = (*lIt)->GetID();
3674   }
3675   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3676                 << Tolerance << " )";
3677 }
3678
3679 //=======================================================================
3680 //function : FindCoincidentNodesOnPart
3681 //purpose  :
3682 //=======================================================================
3683 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
3684                                                    CORBA::Double                  Tolerance,
3685                                                    SMESH::array_of_long_array_out GroupsOfNodes)
3686 {
3687   initData();
3688
3689   TIDSortedNodeSet nodes;
3690   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3691
3692   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3693   ::SMESH_MeshEditor anEditor( myMesh );
3694   if(!nodes.empty())
3695     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3696
3697   GroupsOfNodes = new SMESH::array_of_long_array;
3698   GroupsOfNodes->length( aListOfListOfNodes.size() );
3699   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3700   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3701   {
3702     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3703     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3704     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3705     aGroup.length( aListOfNodes.size() );
3706     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3707       aGroup[ j ] = (*lIt)->GetID();
3708   }
3709   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3710                 <<theObject<<", "
3711                 << Tolerance << " )";
3712 }
3713
3714 //================================================================================
3715 /*!
3716  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3717  *        ExceptSubMeshOrGroups
3718  */
3719 //================================================================================
3720
3721 void SMESH_MeshEditor_i::
3722 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
3723                              CORBA::Double                  theTolerance,
3724                              SMESH::array_of_long_array_out theGroupsOfNodes,
3725                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
3726 {
3727   initData();
3728
3729   TIDSortedNodeSet nodes;
3730   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3731
3732   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3733   {
3734     TIDSortedNodeSet exceptNodes;
3735     idSourceToNodeSet( theExceptSubMeshOrGroups[i], GetMeshDS(), exceptNodes );
3736     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3737     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3738       nodes.erase( *avoidNode );
3739   }
3740   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3741   ::SMESH_MeshEditor anEditor( myMesh );
3742   if(!nodes.empty())
3743     anEditor.FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3744
3745   theGroupsOfNodes = new SMESH::array_of_long_array;
3746   theGroupsOfNodes->length( aListOfListOfNodes.size() );
3747   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3748   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3749   {
3750     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3751     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3752     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
3753     aGroup.length( aListOfNodes.size() );
3754     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3755       aGroup[ j ] = (*lIt)->GetID();
3756   }
3757   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
3758                 << theObject<<", "
3759                 << theTolerance << ", "
3760                 << theExceptSubMeshOrGroups << " )";
3761 }
3762
3763 //=======================================================================
3764 //function : MergeNodes
3765 //purpose  :
3766 //=======================================================================
3767
3768 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
3769 {
3770   initData();
3771
3772   SMESHDS_Mesh* aMesh = GetMeshDS();
3773
3774   TPythonDump aTPythonDump;
3775   aTPythonDump << this << ".MergeNodes([";
3776   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3777   for (int i = 0; i < GroupsOfNodes.length(); i++)
3778   {
3779     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
3780     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
3781     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
3782     for ( int j = 0; j < aNodeGroup.length(); j++ )
3783     {
3784       CORBA::Long index = aNodeGroup[ j ];
3785       const SMDS_MeshNode * node = aMesh->FindNode(index);
3786       if ( node )
3787         aListOfNodes.push_back( node );
3788     }
3789     if ( aListOfNodes.size() < 2 )
3790       aListOfListOfNodes.pop_back();
3791
3792     if ( i > 0 ) aTPythonDump << ", ";
3793     aTPythonDump << aNodeGroup;
3794   }
3795   ::SMESH_MeshEditor anEditor( myMesh );
3796   anEditor.MergeNodes( aListOfListOfNodes );
3797
3798   aTPythonDump <<  "])";
3799
3800   myMesh->SetIsModified( true );
3801 }
3802
3803 //=======================================================================
3804 //function : FindEqualElements
3805 //purpose  :
3806 //=======================================================================
3807 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
3808                                            SMESH::array_of_long_array_out GroupsOfElementsID)
3809 {
3810   initData();
3811
3812   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
3813   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
3814   {
3815     typedef list<int> TListOfIDs;
3816     set<const SMDS_MeshElement*> elems;
3817     SMESH::long_array_var aElementsId = theObject->GetIDs();
3818     SMESHDS_Mesh* aMesh = GetMeshDS();
3819
3820     for(int i = 0; i < aElementsId->length(); i++) {
3821       CORBA::Long anID = aElementsId[i];
3822       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
3823       if (elem) {
3824         elems.insert(elem);
3825       }
3826     }
3827
3828     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3829     ::SMESH_MeshEditor anEditor( myMesh );
3830     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
3831
3832     GroupsOfElementsID = new SMESH::array_of_long_array;
3833     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
3834
3835     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
3836     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
3837       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
3838       TListOfIDs& listOfIDs = *arraysIt;
3839       aGroup.length( listOfIDs.size() );
3840       TListOfIDs::iterator idIt = listOfIDs.begin();
3841       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
3842         aGroup[ k ] = *idIt;
3843       }
3844     }
3845
3846     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
3847                   <<theObject<<" )";
3848   }
3849 }
3850
3851 //=======================================================================
3852 //function : MergeElements
3853 //purpose  :
3854 //=======================================================================
3855
3856 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
3857 {
3858   initData();
3859
3860   TPythonDump aTPythonDump;
3861   aTPythonDump << this << ".MergeElements( [";
3862
3863   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3864
3865   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
3866     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
3867     aListOfListOfElementsID.push_back( list< int >() );
3868     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
3869     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
3870       CORBA::Long id = anElemsIDGroup[ j ];
3871       aListOfElemsID.push_back( id );
3872     }
3873     if ( aListOfElemsID.size() < 2 )
3874       aListOfListOfElementsID.pop_back();
3875     if ( i > 0 ) aTPythonDump << ", ";
3876     aTPythonDump << anElemsIDGroup;
3877   }
3878
3879   ::SMESH_MeshEditor anEditor( myMesh );
3880   anEditor.MergeElements(aListOfListOfElementsID);
3881
3882   myMesh->SetIsModified( true );
3883
3884   aTPythonDump << "] )";
3885 }
3886
3887 //=======================================================================
3888 //function : MergeEqualElements
3889 //purpose  :
3890 //=======================================================================
3891
3892 void SMESH_MeshEditor_i::MergeEqualElements()
3893 {
3894   initData();
3895
3896   ::SMESH_MeshEditor anEditor( myMesh );
3897   anEditor.MergeEqualElements();
3898
3899   TPythonDump() << this << ".MergeEqualElements()";
3900 }
3901
3902 //=============================================================================
3903 /*!
3904  * Move the node to a given point
3905  */
3906 //=============================================================================
3907
3908 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
3909                                             CORBA::Double x,
3910                                             CORBA::Double y,
3911                                             CORBA::Double z)
3912 {
3913   initData(/*deleteSearchers=*/false);
3914
3915   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
3916   if ( !node )
3917     return false;
3918
3919   if ( theNodeSearcher )
3920     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3921
3922   if ( myPreviewMode ) // make preview data
3923   {
3924     // in a preview mesh, make edges linked to a node
3925     TPreviewMesh tmpMesh;
3926     TIDSortedElemSet linkedNodes;
3927     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3928     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3929     for ( ; nIt != linkedNodes.end(); ++nIt )
3930     {
3931       SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3932       tmpMesh.Copy( &edge );
3933     }
3934     // move copied node
3935     node = tmpMesh.GetMeshDS()->FindNode( NodeID );
3936     if ( node )
3937       tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3938     // fill preview data
3939     ::SMESH_MeshEditor anEditor( & tmpMesh );
3940     storeResult( anEditor );
3941   }
3942   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3943     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3944   else
3945     GetMeshDS()->MoveNode(node, x, y, z);
3946
3947   if ( !myPreviewMode )
3948   {
3949     // Update Python script
3950     TPythonDump() << "isDone = " << this << ".MoveNode( "
3951                   << NodeID << ", " << x << ", " << y << ", " << z << " )";
3952
3953     myMesh->SetIsModified( true );
3954   }
3955
3956   return true;
3957 }
3958
3959 //================================================================================
3960 /*!
3961  * \brief Return ID of node closest to a given point
3962  */
3963 //================================================================================
3964
3965 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
3966                                                   CORBA::Double y,
3967                                                   CORBA::Double z)
3968 {
3969   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3970
3971   if ( !theNodeSearcher ) {
3972     ::SMESH_MeshEditor anEditor( myMesh );
3973     theNodeSearcher = anEditor.GetNodeSearcher();
3974   }
3975   gp_Pnt p( x,y,z );
3976   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
3977     return node->GetID();
3978
3979   return 0;
3980 }
3981
3982 //================================================================================
3983 /*!
3984  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
3985  * move the node closest to the point to point's location and return ID of the node
3986  */
3987 //================================================================================
3988
3989 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
3990                                                        CORBA::Double y,
3991                                                        CORBA::Double z,
3992                                                        CORBA::Long   theNodeID)
3993 {
3994   // We keep theNodeSearcher until any mesh modification:
3995   // 1) initData() deletes theNodeSearcher at any edition,
3996   // 2) TSearchersDeleter - at any mesh compute event and mesh change
3997
3998   initData(/*deleteSearchers=*/false);
3999
4000   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4001
4002   int nodeID = theNodeID;
4003   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
4004   if ( !node ) // preview moving node
4005   {
4006     if ( !theNodeSearcher ) {
4007       ::SMESH_MeshEditor anEditor( myMesh );
4008       theNodeSearcher = anEditor.GetNodeSearcher();
4009     }
4010     gp_Pnt p( x,y,z );
4011     node = theNodeSearcher->FindClosestTo( p );
4012   }
4013   if ( node ) {
4014     nodeID = node->GetID();
4015     if ( myPreviewMode ) // make preview data
4016     {
4017       // in a preview mesh, make edges linked to a node
4018       TPreviewMesh tmpMesh;
4019       TIDSortedElemSet linkedNodes;
4020       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4021       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4022       for ( ; nIt != linkedNodes.end(); ++nIt )
4023       {
4024         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
4025         tmpMesh.Copy( &edge );
4026       }
4027       // move copied node
4028       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4029       if ( node )
4030         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4031       // fill preview data
4032       ::SMESH_MeshEditor anEditor( & tmpMesh );
4033       storeResult( anEditor );
4034     }
4035     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4036     {
4037       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4038     }
4039     else
4040     {
4041       GetMeshDS()->MoveNode(node, x, y, z);
4042     }
4043   }
4044
4045   if ( !myPreviewMode )
4046   {
4047     TPythonDump() << "nodeID = " << this
4048                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4049                   << ", " << nodeID << " )";
4050
4051     myMesh->SetIsModified( true );
4052   }
4053
4054   return nodeID;
4055 }
4056
4057 //=======================================================================
4058 /*!
4059  * Return elements of given type where the given point is IN or ON.
4060  *
4061  * 'ALL' type means elements of any type excluding nodes
4062  */
4063 //=======================================================================
4064
4065 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
4066                                                            CORBA::Double      y,
4067                                                            CORBA::Double      z,
4068                                                            SMESH::ElementType type)
4069 {
4070   SMESH::long_array_var res = new SMESH::long_array;
4071   vector< const SMDS_MeshElement* > foundElems;
4072
4073   theSearchersDeleter.Set( myMesh );
4074   if ( !theElementSearcher ) {
4075     ::SMESH_MeshEditor anEditor( myMesh );
4076     theElementSearcher = anEditor.GetElementSearcher();
4077   }
4078   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4079                                            SMDSAbs_ElementType( type ),
4080                                            foundElems);
4081   res->length( foundElems.size() );
4082   for ( int i = 0; i < foundElems.size(); ++i )
4083     res[i] = foundElems[i]->GetID();
4084
4085   if ( !myPreviewMode ) // call from tui
4086     TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
4087                   << x << ", "
4088                   << y << ", "
4089                   << z << ", "
4090                   << type << " )";
4091
4092   return res._retn();
4093 }
4094
4095 //=======================================================================
4096 //function : GetPointState
4097 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4098 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4099 //=======================================================================
4100
4101 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4102                                                CORBA::Double y,
4103                                                CORBA::Double z)
4104 {
4105   theSearchersDeleter.Set( myMesh );
4106   if ( !theElementSearcher ) {
4107     ::SMESH_MeshEditor anEditor( myMesh );
4108     theElementSearcher = anEditor.GetElementSearcher();
4109   }
4110   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4111 }
4112
4113 //=======================================================================
4114 //function : convError
4115 //purpose  :
4116 //=======================================================================
4117
4118 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4119
4120 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4121 {
4122   switch ( e ) {
4123     RETCASE( SEW_OK );
4124     RETCASE( SEW_BORDER1_NOT_FOUND );
4125     RETCASE( SEW_BORDER2_NOT_FOUND );
4126     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4127     RETCASE( SEW_BAD_SIDE_NODES );
4128     RETCASE( SEW_VOLUMES_TO_SPLIT );
4129     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4130     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4131     RETCASE( SEW_BAD_SIDE1_NODES );
4132     RETCASE( SEW_BAD_SIDE2_NODES );
4133   }
4134   return SMESH::SMESH_MeshEditor::SEW_OK;
4135 }
4136
4137 //=======================================================================
4138 //function : SewFreeBorders
4139 //purpose  :
4140 //=======================================================================
4141
4142 SMESH::SMESH_MeshEditor::Sew_Error
4143 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4144                                    CORBA::Long SecondNodeID1,
4145                                    CORBA::Long LastNodeID1,
4146                                    CORBA::Long FirstNodeID2,
4147                                    CORBA::Long SecondNodeID2,
4148                                    CORBA::Long LastNodeID2,
4149                                    CORBA::Boolean CreatePolygons,
4150                                    CORBA::Boolean CreatePolyedrs)
4151 {
4152   initData();
4153
4154   SMESHDS_Mesh* aMesh = GetMeshDS();
4155
4156   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4157   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4158   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4159   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4160   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4161   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
4162
4163   if (!aBorderFirstNode ||
4164       !aBorderSecondNode||
4165       !aBorderLastNode)
4166     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4167   if (!aSide2FirstNode  ||
4168       !aSide2SecondNode ||
4169       !aSide2ThirdNode)
4170     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4171
4172   TPythonDump() << "error = " << this << ".SewFreeBorders( "
4173                 << FirstNodeID1  << ", "
4174                 << SecondNodeID1 << ", "
4175                 << LastNodeID1   << ", "
4176                 << FirstNodeID2  << ", "
4177                 << SecondNodeID2 << ", "
4178                 << LastNodeID2   << ", "
4179                 << CreatePolygons<< ", "
4180                 << CreatePolyedrs<< " )";
4181
4182   ::SMESH_MeshEditor anEditor( myMesh );
4183   SMESH::SMESH_MeshEditor::Sew_Error error =
4184     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4185                                        aBorderSecondNode,
4186                                        aBorderLastNode,
4187                                        aSide2FirstNode,
4188                                        aSide2SecondNode,
4189                                        aSide2ThirdNode,
4190                                        true,
4191                                        CreatePolygons,
4192                                        CreatePolyedrs) );
4193
4194   storeResult(anEditor);
4195
4196   myMesh->SetIsModified( true );
4197
4198   return error;
4199 }
4200
4201
4202 //=======================================================================
4203 //function : SewConformFreeBorders
4204 //purpose  :
4205 //=======================================================================
4206
4207 SMESH::SMESH_MeshEditor::Sew_Error
4208 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4209                                           CORBA::Long SecondNodeID1,
4210                                           CORBA::Long LastNodeID1,
4211                                           CORBA::Long FirstNodeID2,
4212                                           CORBA::Long SecondNodeID2)
4213 {
4214   initData();
4215
4216   SMESHDS_Mesh* aMesh = GetMeshDS();
4217
4218   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4219   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4220   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4221   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4222   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4223   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4224
4225   if (!aBorderFirstNode ||
4226       !aBorderSecondNode||
4227       !aBorderLastNode )
4228     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4229   if (!aSide2FirstNode  ||
4230       !aSide2SecondNode)
4231     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4232
4233   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4234                 << FirstNodeID1  << ", "
4235                 << SecondNodeID1 << ", "
4236                 << LastNodeID1   << ", "
4237                 << FirstNodeID2  << ", "
4238                 << SecondNodeID2 << " )";
4239
4240   ::SMESH_MeshEditor anEditor( myMesh );
4241   SMESH::SMESH_MeshEditor::Sew_Error error =
4242     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4243                                        aBorderSecondNode,
4244                                        aBorderLastNode,
4245                                        aSide2FirstNode,
4246                                        aSide2SecondNode,
4247                                        aSide2ThirdNode,
4248                                        true,
4249                                        false, false) );
4250
4251   storeResult(anEditor);
4252
4253   myMesh->SetIsModified( true );
4254
4255   return error;
4256 }
4257
4258
4259 //=======================================================================
4260 //function : SewBorderToSide
4261 //purpose  :
4262 //=======================================================================
4263
4264 SMESH::SMESH_MeshEditor::Sew_Error
4265 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4266                                     CORBA::Long SecondNodeIDOnFreeBorder,
4267                                     CORBA::Long LastNodeIDOnFreeBorder,
4268                                     CORBA::Long FirstNodeIDOnSide,
4269                                     CORBA::Long LastNodeIDOnSide,
4270                                     CORBA::Boolean CreatePolygons,
4271                                     CORBA::Boolean CreatePolyedrs)
4272 {
4273   initData();
4274
4275   SMESHDS_Mesh* aMesh = GetMeshDS();
4276
4277   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
4278   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4279   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
4280   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
4281   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
4282   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4283
4284   if (!aBorderFirstNode ||
4285       !aBorderSecondNode||
4286       !aBorderLastNode  )
4287     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4288   if (!aSide2FirstNode  ||
4289       !aSide2SecondNode)
4290     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4291
4292   TPythonDump() << "error = " << this << ".SewBorderToSide( "
4293                 << FirstNodeIDOnFreeBorder  << ", "
4294                 << SecondNodeIDOnFreeBorder << ", "
4295                 << LastNodeIDOnFreeBorder   << ", "
4296                 << FirstNodeIDOnSide        << ", "
4297                 << LastNodeIDOnSide         << ", "
4298                 << CreatePolygons           << ", "
4299                 << CreatePolyedrs           << ") ";
4300
4301   ::SMESH_MeshEditor anEditor( myMesh );
4302   SMESH::SMESH_MeshEditor::Sew_Error error =
4303     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4304                                        aBorderSecondNode,
4305                                        aBorderLastNode,
4306                                        aSide2FirstNode,
4307                                        aSide2SecondNode,
4308                                        aSide2ThirdNode,
4309                                        false,
4310                                        CreatePolygons,
4311                                        CreatePolyedrs) );
4312
4313   storeResult(anEditor);
4314
4315   myMesh->SetIsModified( true );
4316
4317   return error;
4318 }
4319
4320
4321 //=======================================================================
4322 //function : SewSideElements
4323 //purpose  :
4324 //=======================================================================
4325
4326 SMESH::SMESH_MeshEditor::Sew_Error
4327 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4328                                     const SMESH::long_array& IDsOfSide2Elements,
4329                                     CORBA::Long NodeID1OfSide1ToMerge,
4330                                     CORBA::Long NodeID1OfSide2ToMerge,
4331                                     CORBA::Long NodeID2OfSide1ToMerge,
4332                                     CORBA::Long NodeID2OfSide2ToMerge)
4333 {
4334   initData();
4335
4336   SMESHDS_Mesh* aMesh = GetMeshDS();
4337
4338   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
4339   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
4340   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4341   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4342
4343   if (!aFirstNode1ToMerge ||
4344       !aFirstNode2ToMerge )
4345     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4346   if (!aSecondNode1ToMerge||
4347       !aSecondNode2ToMerge)
4348     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4349
4350   TIDSortedElemSet aSide1Elems, aSide2Elems;
4351   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4352   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4353
4354   TPythonDump() << "error = " << this << ".SewSideElements( "
4355                 << IDsOfSide1Elements << ", "
4356                 << IDsOfSide2Elements << ", "
4357                 << NodeID1OfSide1ToMerge << ", "
4358                 << NodeID1OfSide2ToMerge << ", "
4359                 << NodeID2OfSide1ToMerge << ", "
4360                 << NodeID2OfSide2ToMerge << ")";
4361
4362   ::SMESH_MeshEditor anEditor( myMesh );
4363   SMESH::SMESH_MeshEditor::Sew_Error error =
4364     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
4365                                          aFirstNode1ToMerge,
4366                                          aFirstNode2ToMerge,
4367                                          aSecondNode1ToMerge,
4368                                          aSecondNode2ToMerge));
4369
4370   storeResult(anEditor);
4371
4372   myMesh->SetIsModified( true );
4373
4374   return error;
4375 }
4376
4377 //================================================================================
4378 /*!
4379  * \brief Set new nodes for given element
4380  * \param ide - element id
4381  * \param newIDs - new node ids
4382  * \retval CORBA::Boolean - true if result is OK
4383  */
4384 //================================================================================
4385
4386 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4387                                                    const SMESH::long_array& newIDs)
4388 {
4389   initData();
4390
4391   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4392   if(!elem) return false;
4393
4394   int nbn = newIDs.length();
4395   int i=0;
4396   vector<const SMDS_MeshNode*> aNodes(nbn);
4397   int nbn1=-1;
4398   for(; i<nbn; i++) {
4399     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4400     if(aNode) {
4401       nbn1++;
4402       aNodes[nbn1] = aNode;
4403     }
4404   }
4405   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4406                 << ide << ", " << newIDs << " )";
4407
4408   bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4409
4410   if ( res )
4411     myMesh->SetIsModified( true );
4412
4413   return res;
4414 }
4415
4416 //================================================================================
4417 /*!
4418  * \brief Update myLastCreated* or myPreviewData
4419  * \param anEditor - it contains last modification results
4420  */
4421 //================================================================================
4422
4423 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4424 {
4425   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
4426
4427     list<int> aNodesConnectivity;
4428     typedef map<int, int> TNodesMap;
4429     TNodesMap nodesMap;
4430
4431     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4432     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4433
4434     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4435     int nbEdges = aMeshDS->NbEdges();
4436     int nbFaces = aMeshDS->NbFaces();
4437     int nbVolum = aMeshDS->NbVolumes();
4438     switch ( previewType ) {
4439     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4440     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4441     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4442     default:;
4443     }
4444     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4445     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4446     int i = 0, j = 0;
4447     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4448
4449     while ( itMeshElems->more() ) {
4450       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4451       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4452         continue;
4453
4454       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4455       while ( itElemNodes->more() ) {
4456         const SMDS_MeshNode* aMeshNode = 
4457           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4458         int aNodeID = aMeshNode->GetID();
4459         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4460         if ( anIter == nodesMap.end() ) {
4461           // filling the nodes coordinates
4462           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4463           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4464           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4465           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4466           j++;
4467         }
4468         aNodesConnectivity.push_back(anIter->second);
4469       }
4470
4471       // filling the elements types
4472       SMDSAbs_ElementType aType;
4473       bool isPoly;
4474       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4475         aType = SMDSAbs_Node;
4476         isPoly = false;
4477         }
4478         else*/ {
4479         aType = aMeshElem->GetType();
4480         isPoly = aMeshElem->IsPoly();
4481       }
4482
4483       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4484       myPreviewData->elementTypes[i].isPoly = isPoly;
4485       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4486       i++;
4487
4488     }
4489     myPreviewData->nodesXYZ.length( j );
4490
4491     // filling the elements connectivities
4492     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4493     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4494     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4495       myPreviewData->elementConnectivities[i] = *aConnIter;
4496
4497     return;
4498   }
4499
4500   {
4501     // add new nodes into myLastCreatedNodes
4502     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4503     myLastCreatedNodes->length(aSeq.Length());
4504     for(int i=0; i<aSeq.Length(); i++)
4505       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
4506   }
4507   {
4508     // add new elements into myLastCreatedElems
4509     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4510     myLastCreatedElems->length(aSeq.Length());
4511     for(int i=0; i<aSeq.Length(); i++)
4512       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
4513   }
4514 }
4515
4516 //================================================================================
4517 /*!
4518  * Return data of mesh edition preview
4519  */
4520 //================================================================================
4521
4522 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4523 {
4524   return myPreviewData._retn();
4525 }
4526
4527 //================================================================================
4528 /*!
4529  * \brief Returns list of it's IDs of created nodes
4530  * \retval SMESH::long_array* - list of node ID
4531  */
4532 //================================================================================
4533
4534 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4535 {
4536   return myLastCreatedNodes._retn();
4537 }
4538
4539 //================================================================================
4540 /*!
4541  * \brief Returns list of it's IDs of created elements
4542  * \retval SMESH::long_array* - list of elements' ID
4543  */
4544 //================================================================================
4545
4546 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4547 {
4548   return myLastCreatedElems._retn();
4549 }
4550
4551 //=======================================================================
4552 //function : ConvertToQuadratic
4553 //purpose  :
4554 //=======================================================================
4555
4556 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4557 {
4558   ::SMESH_MeshEditor anEditor( myMesh );
4559   anEditor.ConvertToQuadratic(theForce3d);
4560   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4561   myMesh->SetIsModified( true );
4562 }
4563
4564 //=======================================================================
4565 //function : ConvertFromQuadratic
4566 //purpose  : 
4567 //=======================================================================
4568
4569 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4570 {
4571   ::SMESH_MeshEditor anEditor( myMesh );
4572   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
4573   TPythonDump() << this << ".ConvertFromQuadratic()";
4574   if ( isDone )
4575     myMesh->SetIsModified( true );
4576   return isDone;
4577 }
4578
4579 //=======================================================================
4580 //function : makeMesh
4581 //purpose  : create a named imported mesh 
4582 //=======================================================================
4583
4584 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4585 {
4586   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4587   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4588   SALOMEDS::Study_var study = gen->GetCurrentStudy();
4589   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
4590   gen->SetName( meshSO, theMeshName, "Mesh" );
4591   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4592
4593   return mesh._retn();
4594 }
4595
4596 //=======================================================================
4597 //function : DumpGroupsList
4598 //purpose  :
4599 //=======================================================================
4600 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython, 
4601                                         const SMESH::ListOfGroups * theGroupList)
4602 {
4603   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
4604   if(isDumpGroupList) {
4605     theDumpPython << theGroupList << " = ";
4606   }
4607 }
4608
4609 //================================================================================
4610 /*!
4611   \brief Generates the unique group name.
4612   \param thePrefix name prefix
4613   \return unique name
4614 */
4615 //================================================================================
4616 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4617 {
4618   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4619   set<string> groupNames;
4620   
4621   // Get existing group names
4622   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4623     SMESH::SMESH_GroupBase_var aGroup = groups[i];
4624     if (CORBA::is_nil(aGroup))
4625       continue;
4626
4627     groupNames.insert(aGroup->GetName());
4628   }
4629
4630   // Find new name
4631   string name = thePrefix;
4632   int index = 0;
4633
4634   while (!groupNames.insert(name).second) {
4635     if (index == 0) {
4636       name += "_1";
4637     }
4638     else {
4639       TCollection_AsciiString nbStr(index+1);
4640       name.resize( name.rfind('_')+1 );
4641       name += nbStr.ToCString();
4642     }
4643     ++index;
4644   }
4645   
4646   return name;
4647 }
4648
4649 //================================================================================
4650 /*!
4651   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4652   \param theNodes - identifiers of nodes to be doubled
4653   \param theModifiedElems - identifiers of elements to be updated by the new (doubled) 
4654          nodes. If list of element identifiers is empty then nodes are doubled but 
4655          they not assigned to elements
4656   \return TRUE if operation has been completed successfully, FALSE otherwise
4657   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
4658 */
4659 //================================================================================
4660
4661 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes, 
4662                                                 const SMESH::long_array& theModifiedElems )
4663 {
4664   initData();
4665
4666   ::SMESH_MeshEditor aMeshEditor( myMesh );
4667   list< int > aListOfNodes;
4668   int i, n;
4669   for ( i = 0, n = theNodes.length(); i < n; i++ )
4670     aListOfNodes.push_back( theNodes[ i ] );
4671
4672   list< int > aListOfElems;
4673   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4674     aListOfElems.push_back( theModifiedElems[ i ] );
4675
4676   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
4677
4678   storeResult( aMeshEditor) ;
4679   if ( aResult )
4680     myMesh->SetIsModified( true );
4681
4682   // Update Python script
4683   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
4684
4685   return aResult;
4686 }
4687
4688 //================================================================================
4689 /*!
4690   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4691   This method provided for convenience works as DoubleNodes() described above.
4692   \param theNodeId - identifier of node to be doubled.
4693   \param theModifiedElems - identifiers of elements to be updated.
4694   \return TRUE if operation has been completed successfully, FALSE otherwise
4695   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
4696 */
4697 //================================================================================
4698
4699 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId, 
4700                                                const SMESH::long_array& theModifiedElems )
4701 {
4702   SMESH::long_array_var aNodes = new SMESH::long_array;
4703   aNodes->length( 1 );
4704   aNodes[ 0 ] = theNodeId;
4705
4706   TPythonDump pyDump; // suppress dump by the next line
4707
4708   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
4709
4710   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
4711
4712   return done;
4713 }
4714
4715 //================================================================================
4716 /*!
4717   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4718   This method provided for convenience works as DoubleNodes() described above.
4719   \param theNodes - group of nodes to be doubled.
4720   \param theModifiedElems - group of elements to be updated.
4721   \return TRUE if operation has been completed successfully, FALSE otherwise
4722   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
4723 */
4724 //================================================================================
4725
4726 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
4727                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
4728 {
4729   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4730     return false;
4731
4732   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4733   SMESH::long_array_var aModifiedElems;
4734   if ( !CORBA::is_nil( theModifiedElems ) )
4735     aModifiedElems = theModifiedElems->GetListOfID();
4736   else 
4737   {
4738     aModifiedElems = new SMESH::long_array;
4739     aModifiedElems->length( 0 );
4740   }
4741
4742   TPythonDump pyDump; // suppress dump by the next line
4743
4744   bool done = DoubleNodes( aNodes, aModifiedElems );
4745
4746   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
4747
4748   return done;
4749 }
4750
4751 /*!
4752  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
4753  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
4754  * \param theNodes - group of nodes to be doubled.
4755  * \param theModifiedElems - group of elements to be updated.
4756  * \return a new group with newly created nodes
4757  * \sa DoubleNodeGroup()
4758  */
4759 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
4760                                                                SMESH::SMESH_GroupBase_ptr theModifiedElems )
4761 {
4762   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4763     return false;
4764   
4765   SMESH::SMESH_Group_var aNewGroup;
4766
4767   // Duplicate nodes
4768   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4769   SMESH::long_array_var aModifiedElems;
4770   if ( !CORBA::is_nil( theModifiedElems ) )
4771     aModifiedElems = theModifiedElems->GetListOfID();
4772   else {
4773     aModifiedElems = new SMESH::long_array;
4774     aModifiedElems->length( 0 );
4775   }
4776   
4777   TPythonDump pyDump; // suppress dump by the next line
4778
4779   bool aResult = DoubleNodes( aNodes, aModifiedElems );
4780
4781   if ( aResult )
4782   {
4783     // Create group with newly created nodes
4784     SMESH::long_array_var anIds = GetLastCreatedNodes();
4785     if (anIds->length() > 0) {
4786       string anUnindexedName (theNodes->GetName());
4787       string aNewName = generateGroupName(anUnindexedName + "_double");
4788       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
4789       aNewGroup->Add(anIds);
4790     }
4791   }
4792   
4793   pyDump << "createdNodes = " << this << ".DoubleNodeGroupNew( " << theNodes << ", "
4794     << theModifiedElems << " )";
4795
4796   return aNewGroup._retn();
4797 }
4798
4799 //================================================================================
4800 /*!
4801   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4802   This method provided for convenience works as DoubleNodes() described above.
4803   \param theNodes - list of groups of nodes to be doubled
4804   \param theModifiedElems - list of groups of elements to be updated.
4805   \return TRUE if operation has been completed successfully, FALSE otherwise
4806   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
4807 */
4808 //================================================================================
4809
4810 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
4811                                                     const SMESH::ListOfGroups& theModifiedElems )
4812 {
4813   initData();
4814
4815   ::SMESH_MeshEditor aMeshEditor( myMesh );
4816
4817   std::list< int > aNodes;
4818   int i, n, j, m;
4819   for ( i = 0, n = theNodes.length(); i < n; i++ )
4820   {
4821     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
4822     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
4823     {
4824       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4825       for ( j = 0, m = aCurr->length(); j < m; j++ )
4826         aNodes.push_back( aCurr[ j ] );
4827     }
4828   }
4829
4830   std::list< int > anElems;
4831   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4832   {
4833     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
4834     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
4835     {
4836       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4837       for ( j = 0, m = aCurr->length(); j < m; j++ )
4838         anElems.push_back( aCurr[ j ] );
4839     }
4840   }
4841
4842   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
4843
4844   storeResult( aMeshEditor) ;
4845
4846   if ( aResult )
4847     myMesh->SetIsModified( true );
4848
4849
4850   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
4851
4852   return aResult;
4853 }
4854
4855 //================================================================================
4856 /*!
4857   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4858   \param theElems - the list of elements (edges or faces) to be replicated
4859   The nodes for duplication could be found from these elements
4860   \param theNodesNot - list of nodes to NOT replicate
4861   \param theAffectedElems - the list of elements (cells and edges) to which the 
4862   replicated nodes should be associated to.
4863   \return TRUE if operation has been completed successfully, FALSE otherwise
4864   \sa DoubleNodeGroup(), DoubleNodeGroups()
4865 */
4866 //================================================================================
4867
4868 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems, 
4869                                                    const SMESH::long_array& theNodesNot,
4870                                                    const SMESH::long_array& theAffectedElems )
4871
4872 {
4873   initData();
4874
4875   ::SMESH_MeshEditor aMeshEditor( myMesh );
4876
4877   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4878   TIDSortedElemSet anElems, aNodes, anAffected;
4879   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4880   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4881   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
4882
4883   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4884
4885   storeResult( aMeshEditor) ;
4886
4887   if ( aResult )
4888     myMesh->SetIsModified( true );
4889
4890   // Update Python script
4891   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
4892                 << theNodesNot << ", " << theAffectedElems << " )";
4893   return aResult;
4894 }
4895
4896 //================================================================================
4897 /*!
4898   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4899   \param theElems - the list of elements (edges or faces) to be replicated
4900   The nodes for duplication could be found from these elements
4901   \param theNodesNot - list of nodes to NOT replicate
4902   \param theShape - shape to detect affected elements (element which geometric center
4903   located on or inside shape).
4904   The replicated nodes should be associated to affected elements.
4905   \return TRUE if operation has been completed successfully, FALSE otherwise
4906   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
4907 */
4908 //================================================================================
4909
4910 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems, 
4911                                                             const SMESH::long_array& theNodesNot,
4912                                                             GEOM::GEOM_Object_ptr    theShape )
4913
4914 {
4915   initData();
4916
4917   ::SMESH_MeshEditor aMeshEditor( myMesh );
4918
4919   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4920   TIDSortedElemSet anElems, aNodes;
4921   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4922   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4923
4924   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4925   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4926
4927   storeResult( aMeshEditor) ;
4928
4929   if ( aResult )
4930     myMesh->SetIsModified( true );
4931
4932   // Update Python script
4933   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
4934                 << theNodesNot << ", " << theShape << " )";
4935   return aResult;
4936 }
4937
4938 //================================================================================
4939 /*!
4940   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4941   \param theElems - group of of elements (edges or faces) to be replicated
4942   \param theNodesNot - group of nodes not to replicated
4943   \param theAffectedElems - group of elements to which the replicated nodes
4944   should be associated to.
4945   \return TRUE if operation has been completed successfully, FALSE otherwise
4946   \sa DoubleNodes(), DoubleNodeGroups()
4947 */
4948 //================================================================================
4949
4950 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
4951                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
4952                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
4953 {
4954   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4955     return false;
4956
4957   initData();
4958
4959   ::SMESH_MeshEditor aMeshEditor( myMesh );
4960
4961   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4962   TIDSortedElemSet anElems, aNodes, anAffected;
4963   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4964   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4965   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
4966
4967   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4968
4969   storeResult( aMeshEditor) ;
4970
4971   if ( aResult )
4972     myMesh->SetIsModified( true );
4973
4974   // Update Python script
4975   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
4976                 << theNodesNot << ", " << theAffectedElems << " )";
4977   return aResult;
4978 }
4979
4980 /*!
4981  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4982  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
4983  * \param theElems - group of of elements (edges or faces) to be replicated
4984  * \param theNodesNot - group of nodes not to replicated
4985  * \param theAffectedElems - group of elements to which the replicated nodes
4986  *        should be associated to.
4987  * \return a new group with newly created elements
4988  * \sa DoubleNodeElemGroup()
4989  */
4990 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
4991                                                                   SMESH::SMESH_GroupBase_ptr theNodesNot,
4992                                                                   SMESH::SMESH_GroupBase_ptr theAffectedElems)
4993 {
4994   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4995     return false;
4996
4997   SMESH::SMESH_Group_var aNewGroup;
4998
4999   initData();
5000
5001   ::SMESH_MeshEditor aMeshEditor( myMesh );
5002
5003   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5004   TIDSortedElemSet anElems, aNodes, anAffected;
5005   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
5006   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
5007   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5008
5009   
5010   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5011   
5012   storeResult( aMeshEditor) ;
5013
5014   if ( aResult ) {
5015     myMesh->SetIsModified( true );
5016
5017     // Create group with newly created elements
5018     SMESH::long_array_var anIds = GetLastCreatedElems();
5019     if (anIds->length() > 0) {
5020       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5021       string anUnindexedName (theElems->GetName());
5022       string aNewName = generateGroupName(anUnindexedName + "_double");
5023       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5024       aNewGroup->Add(anIds);
5025     }
5026   }
5027
5028   // Update Python script
5029   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupNew( " << theElems << ", "
5030     << theNodesNot << ", " << theAffectedElems << " )";
5031   return aNewGroup._retn();
5032 }
5033
5034 //================================================================================
5035 /*!
5036   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5037   \param theElems - group of of elements (edges or faces) to be replicated
5038   \param theNodesNot - group of nodes not to replicated
5039   \param theShape - shape to detect affected elements (element which geometric center
5040   located on or inside shape).
5041   The replicated nodes should be associated to affected elements.
5042   \return TRUE if operation has been completed successfully, FALSE otherwise
5043   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5044 */
5045 //================================================================================
5046
5047 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5048                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
5049                                                                GEOM::GEOM_Object_ptr      theShape )
5050
5051 {
5052   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5053     return false;
5054
5055   initData();
5056
5057   ::SMESH_MeshEditor aMeshEditor( myMesh );
5058
5059   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5060   TIDSortedElemSet anElems, aNodes, anAffected;
5061   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
5062   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
5063
5064   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5065   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5066
5067   storeResult( aMeshEditor) ;
5068
5069   if ( aResult )
5070     myMesh->SetIsModified( true );
5071
5072   // Update Python script
5073   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5074                 << theNodesNot << ", " << theShape << " )";
5075   return aResult;
5076 }
5077
5078 //================================================================================
5079 /*!
5080   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5081   This method provided for convenience works as DoubleNodes() described above.
5082   \param theElems - list of groups of elements (edges or faces) to be replicated
5083   \param theNodesNot - list of groups of nodes not to replicated
5084   \param theAffectedElems - group of elements to which the replicated nodes
5085   should be associated to.
5086   \return TRUE if operation has been completed successfully, FALSE otherwise
5087   \sa DoubleNodeGroup(), DoubleNodes()
5088 */
5089 //================================================================================
5090
5091 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5092                              SMESHDS_Mesh*              theMeshDS,
5093                              TIDSortedElemSet&          theElemSet,
5094                              const bool                 theIsNodeGrp)
5095 {
5096   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5097   {
5098     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5099     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE 
5100                                     : aGrp->GetType() != SMESH::NODE ) )
5101     {
5102       SMESH::long_array_var anIDs = aGrp->GetIDs();
5103       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5104     }
5105   }
5106 }
5107
5108 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5109                                                         const SMESH::ListOfGroups& theNodesNot,
5110                                                         const SMESH::ListOfGroups& theAffectedElems)
5111 {
5112   initData();
5113
5114   ::SMESH_MeshEditor aMeshEditor( myMesh );
5115
5116   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5117   TIDSortedElemSet anElems, aNodes, anAffected;
5118   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5119   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5120   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5121
5122   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5123
5124   storeResult( aMeshEditor) ;
5125
5126   if ( aResult )
5127     myMesh->SetIsModified( true );
5128
5129   // Update Python script
5130   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5131                 << &theNodesNot << ", " << &theAffectedElems << " )";
5132   return aResult;
5133 }
5134
5135 //================================================================================
5136 /*!
5137   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5138   This method provided for convenience works as DoubleNodes() described above.
5139   \param theElems - list of groups of elements (edges or faces) to be replicated
5140   \param theNodesNot - list of groups of nodes not to replicated
5141   \param theShape - shape to detect affected elements (element which geometric center
5142   located on or inside shape).
5143   The replicated nodes should be associated to affected elements.
5144   \return TRUE if operation has been completed successfully, FALSE otherwise
5145   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5146 */
5147 //================================================================================
5148
5149 CORBA::Boolean
5150 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5151                                                  const SMESH::ListOfGroups& theNodesNot,
5152                                                  GEOM::GEOM_Object_ptr      theShape )
5153 {
5154   initData();
5155
5156   ::SMESH_MeshEditor aMeshEditor( myMesh );
5157
5158   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5159   TIDSortedElemSet anElems, aNodes;
5160   listOfGroupToSet(theElems, aMeshDS, anElems,false );
5161   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5162
5163   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5164   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5165
5166   storeResult( aMeshEditor) ;
5167
5168   if ( aResult )
5169     myMesh->SetIsModified( true );
5170
5171   // Update Python script
5172   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5173                 << &theNodesNot << ", " << theShape << " )";
5174   return aResult;
5175 }
5176
5177 //================================================================================
5178 /*!
5179   \brief Generated skin mesh (containing 2D cells) from 3D mesh
5180    The created 2D mesh elements based on nodes of free faces of boundary volumes
5181   \return TRUE if operation has been completed successfully, FALSE otherwise
5182 */
5183 //================================================================================
5184
5185 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5186 {
5187   initData();
5188
5189   ::SMESH_MeshEditor aMeshEditor( myMesh );
5190   bool aResult = aMeshEditor.Make2DMeshFrom3D();
5191   storeResult( aMeshEditor) ;
5192
5193   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
5194   return aResult;
5195 }
5196
5197 // issue 20749 ===================================================================
5198 /*!
5199  * \brief Creates missing boundary elements
5200  *  \param elements - elements whose boundary is to be checked
5201  *  \param dimension - defines type of boundary elements to create
5202  *  \param groupName - a name of group to store created boundary elements in,
5203  *                     "" means not to create the group
5204  *  \param meshName - a name of new mesh to store created boundary elements in,
5205  *                     "" means not to create the new mesh
5206  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
5207  *  \param toCopyExistingBondary - if true, not only new but also pre-existing 
5208  *                                boundary elements will be copied into the new mesh
5209  *  \param group - returns the create group, if any
5210  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
5211  */
5212 // ================================================================================
5213
5214 SMESH::SMESH_Mesh_ptr
5215 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
5216                                      SMESH::Bnd_Dimension      dim,
5217                                      const char*               groupName,
5218                                      const char*               meshName,
5219                                      CORBA::Boolean            toCopyElements,
5220                                      CORBA::Boolean            toCopyExistingBondary,
5221                                      SMESH::SMESH_Group_out    group)
5222 {
5223   initData();
5224
5225   if ( dim > SMESH::BND_1DFROM2D )
5226     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
5227
5228   
5229   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5230
5231   SMESH::SMESH_Mesh_var mesh_var;
5232   SMESH::SMESH_Group_var group_var;
5233
5234   TPythonDump pyDump;
5235
5236   TIDSortedElemSet elements;
5237   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
5238   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
5239   {
5240     // mesh to fill in
5241     mesh_var =
5242       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
5243     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
5244     // other mesh
5245     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
5246
5247     // group of new boundary elements
5248     SMESH_Group* smesh_group = 0;
5249     if ( strlen(groupName) )
5250     {
5251       group_var = mesh_i->CreateGroup( SMESH::ElementType(elemType),groupName);
5252       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
5253         smesh_group = group_i->GetSmeshGroup();
5254     }
5255
5256     // do it
5257     ::SMESH_MeshEditor aMeshEditor( myMesh );
5258     aMeshEditor.MakeBoundaryMesh( elements,
5259                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
5260                                   smesh_group,
5261                                   smesh_mesh,
5262                                   toCopyElements,
5263                                   toCopyExistingBondary);
5264     storeResult( aMeshEditor );
5265   }
5266
5267   // result of MakeBoundaryMesh() is a tuple (mesh, group)
5268   if ( mesh_var->_is_nil() )
5269     pyDump << myMesh_i->_this() << ", ";
5270   else
5271     pyDump << mesh_var << ", ";
5272   if ( group_var->_is_nil() )
5273     pyDump << "_NoneGroup = "; // assignment to None is forbiden
5274   else
5275     pyDump << group_var << " = ";
5276   pyDump << this << ".MakeBoundaryMesh( "
5277          << idSource << ", "
5278          << dim << ", "
5279          << groupName << ", "
5280          << meshName<< ", "
5281          << toCopyElements << ", "
5282          << toCopyExistingBondary << ")";
5283
5284   group = group_var._retn();
5285   return mesh_var._retn();
5286 }