Salome HOME
fix PAL15156 (Mesh to pass through a point works wrong for the second mesh)
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  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 //
24 //  File   : SMESH_MeshEditor_i.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_MeshEditor_i.hxx"
30
31 #include "SMDS_MeshEdge.hxx"
32 #include "SMDS_MeshFace.hxx"
33 #include "SMDS_MeshVolume.hxx"
34 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
35 #include "SMESH_MeshEditor.hxx"
36 #include "SMESH_subMeshEventListener.hxx"
37 #include "SMESH_Gen_i.hxx"
38 #include "SMESH_Filter_i.hxx"
39 #include "SMESH_PythonDump.hxx"
40
41 #include "utilities.h"
42
43 #include <gp_Ax1.hxx>
44 #include <gp_Ax2.hxx>
45 #include <gp_Vec.hxx>
46
47 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
48 #define NO_CAS_CATCH
49 #endif
50
51 #include <Standard_Failure.hxx>
52
53 #ifdef NO_CAS_CATCH
54 #include <Standard_ErrorHandler.hxx>
55 #else
56 #include "CASCatch.hxx"
57 #endif
58
59 #include <sstream>
60
61 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
62
63 using namespace std;
64 using SMESH::TPythonDump;
65
66 namespace {
67
68   //=============================================================================
69   /*!
70    * \brief Mesh to apply modifications for preview purposes
71    */
72   //=============================================================================
73
74   struct TPreviewMesh: public SMESH_Mesh
75   {
76     SMDSAbs_ElementType myPreviewType; // type to show
77     //!< Constructor
78     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
79       _isShapeToMesh = _id =_studyId =_idDoc = 0;
80       _myMeshDS  = new SMESHDS_Mesh( _id, true );
81       myPreviewType = previewElements;
82     }
83     //!< Destructor
84     virtual ~TPreviewMesh() { delete _myMeshDS; }
85     //!< Copy a set of elements
86     void Copy(const TIDSortedElemSet & theElements,
87               TIDSortedElemSet&        theCopyElements,
88               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
89               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
90     {
91       // loop on theIDsOfElements
92       TIDSortedElemSet::const_iterator eIt = theElements.begin();
93       for ( ; eIt != theElements.end(); ++eIt )
94       {
95         const SMDS_MeshElement* anElem = *eIt;
96         if ( !anElem ) continue;
97         SMDSAbs_ElementType type = anElem->GetType();
98         if ( type == theAvoidType ||
99              ( theSelectType != SMDSAbs_All && type != theSelectType ))
100           continue;
101
102         if ( const SMDS_MeshElement* anElemCopy = Copy( anElem ))
103           theCopyElements.insert( theCopyElements.end(), anElemCopy );
104       }
105     }
106     //!< Copy an element
107     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
108     {
109       // copy element nodes
110       int anElemNbNodes = anElem->NbNodes();
111       vector< int > anElemNodesID( anElemNbNodes ) ;
112       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
113       for ( int i = 0; itElemNodes->more(); i++)
114       {
115         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
116         Copy( anElemNode );
117         anElemNodesID[i] = anElemNode->GetID();
118       }
119
120       // creates a corresponding element on copied nodes
121       SMDS_MeshElement* anElemCopy = 0;
122       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
123       {
124         const SMDS_PolyhedralVolumeOfNodes* ph =
125           dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem);
126         if ( ph )
127           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
128             (anElemNodesID, ph->GetQuanities(),anElem->GetID());
129       }
130       else {
131         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
132                                                           anElem->GetType(),
133                                                           anElem->IsPoly() );
134       }
135       return anElemCopy;
136     }
137     //!< Copy a node
138     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
139     {
140       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(), 
141                                       anElemNode->GetID());
142     }
143   };// struct TPreviewMesh
144
145   static SMESH_NodeSearcher * myNodeSearcher = 0;
146
147   //=============================================================================
148   /*!
149    * \brief Deleter of myNodeSearcher at any compute event occured
150    */
151   //=============================================================================
152
153   struct TNodeSearcherDeleter : public SMESH_subMeshEventListener
154   {
155     SMESH_Mesh* myMesh;
156     //!< Constructor
157     TNodeSearcherDeleter(): SMESH_subMeshEventListener( false ), // won't be deleted by submesh
158     myMesh(0) {}
159     //!< Delete myNodeSearcher
160     static void Delete()
161     {
162       if ( myNodeSearcher ) { delete myNodeSearcher; myNodeSearcher = 0; }
163     }
164     typedef map < int, SMESH_subMesh * > TDependsOnMap;
165     //!< The meshod called by submesh: do my main job
166     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
167                       SMESH_subMeshEventListenerData*,SMESH_Hypothesis*)
168     {
169       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
170         Delete();
171         Unset( sm->GetFather() );
172       }
173     }
174     //!< set self on all submeshes and delete myNodeSearcher if other mesh is set
175     void Set(SMESH_Mesh* mesh)
176     {
177       if ( myMesh && myMesh != mesh ) {
178         Delete();
179         Unset( myMesh );
180       }
181       myMesh = mesh;
182       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
183         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
184         TDependsOnMap::const_iterator sm;
185         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
186           sm->second->SetEventListener( this, 0, sm->second );
187       }
188     }
189     //!<  delete self from all submeshes
190     void Unset(SMESH_Mesh* mesh)
191     {
192       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
193         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
194         TDependsOnMap::const_iterator sm;
195         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
196           sm->second->DeleteEventListener( this );
197       }
198     }
199   };
200 }
201
202 //=============================================================================
203 /*!
204  *
205  */
206 //=============================================================================
207
208 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh* theMesh, bool isPreview)
209 {
210   myMesh = theMesh;
211   myPreviewMode = isPreview;
212 }
213
214 //================================================================================
215 /*!
216  * \brief Destructor
217  */
218 //================================================================================
219
220 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
221 {
222 }
223
224 //================================================================================
225 /*!
226  * \brief Clear members
227  */
228 //================================================================================
229
230 void SMESH_MeshEditor_i::initData()
231 {
232   if ( myPreviewMode ) {
233     myPreviewData = new SMESH::MeshPreviewStruct();
234   }
235   else {
236     myLastCreatedElems = new SMESH::long_array();
237     myLastCreatedNodes = new SMESH::long_array();
238     TNodeSearcherDeleter::Delete();
239   }
240 }
241
242 //=============================================================================
243 /*!
244  *
245  */
246 //=============================================================================
247
248 CORBA::Boolean
249   SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
250 {
251   initData();
252
253   ::SMESH_MeshEditor anEditor( myMesh );
254   list< int > IdList;
255
256   for (int i = 0; i < IDsOfElements.length(); i++)
257     IdList.push_back( IDsOfElements[i] );
258
259   // Update Python script
260   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
261 #ifdef _DEBUG_
262   TPythonDump() << "print 'RemoveElements: ', isDone";
263 #endif
264   // Remove Elements
265   return anEditor.Remove( IdList, false );
266 }
267
268 //=============================================================================
269 /*!
270  *
271  */
272 //=============================================================================
273
274 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
275 {
276   initData();
277
278   ::SMESH_MeshEditor anEditor( myMesh );
279   list< int > IdList;
280   for (int i = 0; i < IDsOfNodes.length(); i++)
281     IdList.push_back( IDsOfNodes[i] );
282
283   // Update Python script
284   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
285 #ifdef _DEBUG_
286   TPythonDump() << "print 'RemoveNodes: ', isDone";
287 #endif
288
289   return anEditor.Remove( IdList, true );
290 }
291
292 //=============================================================================
293 /*!
294  *
295  */
296 //=============================================================================
297
298 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
299 {
300   initData();
301
302   int NbNodes = IDsOfNodes.length();
303   SMDS_MeshElement* elem = 0;
304   if (NbNodes == 2)
305   {
306     CORBA::Long index1 = IDsOfNodes[0];
307     CORBA::Long index2 = IDsOfNodes[1];
308     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(index1), GetMeshDS()->FindNode(index2));
309
310     // Update Python script
311     TPythonDump() << "edge = " << this << ".AddEdge([ "
312                   << index1 << ", " << index2 <<" ])";
313   }
314   if (NbNodes == 3) {
315     CORBA::Long n1 = IDsOfNodes[0];
316     CORBA::Long n2 = IDsOfNodes[1];
317     CORBA::Long n12 = IDsOfNodes[2];
318     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(n1),
319                                 GetMeshDS()->FindNode(n2),
320                                 GetMeshDS()->FindNode(n12));
321     // Update Python script
322     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
323                   <<n1<<", "<<n2<<", "<<n12<<" ])";
324   }
325
326   if(elem)
327     return elem->GetID();
328
329   return 0;
330 }
331
332 //=============================================================================
333 /*!
334  *
335  */
336 //=============================================================================
337
338 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
339                                         CORBA::Double y, CORBA::Double z)
340 {
341   initData();
342
343   const SMDS_MeshNode* N = GetMeshDS()->AddNode(x, y, z);
344
345   // Update Python script
346   TPythonDump() << "nodeID = " << this << ".AddNode( "
347                 << x << ", " << y << ", " << z << " )";
348
349   return N->GetID();
350 }
351
352 //=============================================================================
353 /*!
354  *  AddFace
355  */
356 //=============================================================================
357
358 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
359 {
360   initData();
361
362   int NbNodes = IDsOfNodes.length();
363   if (NbNodes < 3)
364   {
365     return false;
366   }
367
368   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
369   for (int i = 0; i < NbNodes; i++)
370     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
371
372   SMDS_MeshElement* elem = 0;
373   if (NbNodes == 3) {
374     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
375   }
376   else if (NbNodes == 4) {
377     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
378   }
379   else if (NbNodes == 6) {
380     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
381                                 nodes[4], nodes[5]);
382   }
383   else if (NbNodes == 8) {
384     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
385                                 nodes[4], nodes[5], nodes[6], nodes[7]);
386   }
387
388   // Update Python script
389   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
390
391   if(elem)
392     return elem->GetID();
393
394   return 0;
395 }
396
397 //=============================================================================
398 /*!
399  *  AddPolygonalFace
400  */
401 //=============================================================================
402 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace
403                                    (const SMESH::long_array & IDsOfNodes)
404 {
405   initData();
406
407   int NbNodes = IDsOfNodes.length();
408   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
409   for (int i = 0; i < NbNodes; i++)
410     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
411
412   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
413   
414   // Update Python script
415   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
416 #ifdef _DEBUG_
417   TPythonDump() << "print 'AddPolygonalFace: ', faceID";
418 #endif
419
420   if(elem)
421     return elem->GetID();
422
423   return 0;
424 }
425
426 //=============================================================================
427 /*!
428  *
429  */
430 //=============================================================================
431
432 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
433 {
434   initData();
435
436   int NbNodes = IDsOfNodes.length();
437   vector< const SMDS_MeshNode*> n(NbNodes);
438   for(int i=0;i<NbNodes;i++)
439     n[i]=GetMeshDS()->FindNode(IDsOfNodes[i]);
440
441   SMDS_MeshElement* elem = 0;
442   switch(NbNodes)
443   {
444   case 4 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
445   case 5 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
446   case 6 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
447   case 8 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
448   case 10:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
449                                         n[6],n[7],n[8],n[9]);
450     break;
451   case 13:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
452                                         n[7],n[8],n[9],n[10],n[11],n[12]);
453     break;
454   case 15:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
455                                         n[9],n[10],n[11],n[12],n[13],n[14]);
456     break;
457   case 20:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
458                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
459                                         n[15],n[16],n[17],n[18],n[19]);
460     break;
461   }
462
463   // Update Python script
464   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
465 #ifdef _DEBUG_
466   TPythonDump() << "print 'AddVolume: ', volID";
467 #endif
468
469   if(elem)
470     return elem->GetID();
471
472   return 0;
473 }
474
475 //=============================================================================
476 /*!
477  *  AddPolyhedralVolume
478  */
479 //=============================================================================
480 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
481                                    (const SMESH::long_array & IDsOfNodes,
482                                     const SMESH::long_array & Quantities)
483 {
484   initData();
485
486   int NbNodes = IDsOfNodes.length();
487   std::vector<const SMDS_MeshNode*> n (NbNodes);
488   for (int i = 0; i < NbNodes; i++)
489     n[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
490
491   int NbFaces = Quantities.length();
492   std::vector<int> q (NbFaces);
493   for (int j = 0; j < NbFaces; j++)
494     q[j] = Quantities[j];
495
496   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(n, q);
497
498   // Update Python script
499   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
500                 << IDsOfNodes << ", " << Quantities << " )";
501 #ifdef _DEBUG_
502   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
503 #endif
504
505   if(elem)
506     return elem->GetID();
507
508   return 0;
509 }
510
511 //=============================================================================
512 /*!
513  *  AddPolyhedralVolumeByFaces
514  */
515 //=============================================================================
516 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces
517                                    (const SMESH::long_array & IdsOfFaces)
518 {
519   initData();
520
521   int NbFaces = IdsOfFaces.length();
522   std::vector<const SMDS_MeshNode*> poly_nodes;
523   std::vector<int> quantities (NbFaces);
524
525   for (int i = 0; i < NbFaces; i++) {
526     const SMDS_MeshElement* aFace = GetMeshDS()->FindElement(IdsOfFaces[i]);
527     quantities[i] = aFace->NbNodes();
528
529     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
530     while (It->more()) {
531       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
532     }
533   }
534
535   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
536
537   // Update Python script
538   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
539                 << IdsOfFaces << " )";
540 #ifdef _DEBUG_
541   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
542 #endif
543
544   if(elem)
545     return elem->GetID();
546
547   return 0;
548 }
549
550 //=============================================================================
551 /*!
552  *
553  */
554 //=============================================================================
555
556 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
557                                             CORBA::Double x,
558                                             CORBA::Double y,
559                                             CORBA::Double z)
560 {
561   initData();
562
563   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
564   if ( !node )
565     return false;
566
567   GetMeshDS()->MoveNode(node, x, y, z);
568
569   // Update Python script
570   TPythonDump() << "isDone = " << this << ".MoveNode( "
571                 << NodeID << ", " << x << ", " << y << ", " << z << " )";
572
573   return true;
574 }
575
576 //=============================================================================
577 /*!
578  *
579  */
580 //=============================================================================
581
582 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
583                                                CORBA::Long NodeID2)
584 {
585   initData();
586
587   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
588   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
589   if ( !n1 || !n2 )
590     return false;
591
592   // Update Python script
593   TPythonDump() << "isDone = " << this << ".InverseDiag( "
594                 << NodeID1 << ", " << NodeID2 << " )";
595
596   ::SMESH_MeshEditor aMeshEditor( myMesh );
597   return aMeshEditor.InverseDiag ( n1, n2 );
598 }
599
600 //=============================================================================
601 /*!
602  *
603  */
604 //=============================================================================
605
606 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
607                                               CORBA::Long NodeID2)
608 {
609   initData();
610
611   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
612   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
613   if ( !n1 || !n2 )
614     return false;
615
616   // Update Python script
617   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
618                 << NodeID1 << ", " << NodeID2 <<  " )";
619
620   ::SMESH_MeshEditor aMeshEditor( myMesh );
621
622   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
623
624   StoreResult(aMeshEditor);
625
626   return stat;
627 }
628
629 //=============================================================================
630 /*!
631  *
632  */
633 //=============================================================================
634
635 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
636 {
637   initData();
638
639   ::SMESH_MeshEditor anEditor( myMesh );
640   for (int i = 0; i < IDsOfElements.length(); i++)
641   {
642     CORBA::Long index = IDsOfElements[i];
643     const SMDS_MeshElement * elem = GetMeshDS()->FindElement(index);
644     if ( elem )
645       anEditor.Reorient( elem );
646   }
647   // Update Python script
648   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
649
650   return true;
651 }
652
653
654 //=============================================================================
655 /*!
656  *
657  */
658 //=============================================================================
659
660 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
661 {
662   initData();
663
664   SMESH::long_array_var anElementsId = theObject->GetIDs();
665   CORBA::Boolean isDone = Reorient(anElementsId);
666
667   // Clear python line, created by Reorient()
668   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
669   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
670
671   // Update Python script
672   TPythonDump() << "isDone = " << this << ".ReorientObject( " << theObject << " )";
673
674   return isDone;
675 }
676
677 namespace
678 {
679   //================================================================================
680   /*!
681    * \brief function for conversion long_array to TIDSortedElemSet
682     * \param IDs - array of IDs
683     * \param aMesh - mesh
684     * \param aMap - collection to fill
685     * \param aType - element type
686    */
687   //================================================================================
688
689   void ToMap(const SMESH::long_array & IDs,
690              const SMESHDS_Mesh*       aMesh,
691              TIDSortedElemSet&         aMap,
692              const SMDSAbs_ElementType aType = SMDSAbs_All )
693   { 
694     for (int i=0; i<IDs.length(); i++) {
695       CORBA::Long ind = IDs[i];
696       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
697       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
698         aMap.insert( elem );
699     }
700   }
701 }
702
703 //=============================================================================
704 /*!
705  *
706  */
707 //=============================================================================
708 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
709                                               SMESH::NumericalFunctor_ptr Criterion,
710                                               CORBA::Double               MaxAngle)
711 {
712   initData();
713
714   SMESHDS_Mesh* aMesh = GetMeshDS();
715   TIDSortedElemSet faces;
716   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
717
718   SMESH::NumericalFunctor_i* aNumericalFunctor =
719     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
720   SMESH::Controls::NumericalFunctorPtr aCrit;
721   if ( !aNumericalFunctor )
722     aCrit.reset( new SMESH::Controls::AspectRatio() );
723   else
724     aCrit = aNumericalFunctor->GetNumericalFunctor();
725
726   // Update Python script
727   TPythonDump() << "isDone = " << this << ".TriToQuad( "
728                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
729 #ifdef _DEBUG_
730   TPythonDump() << "print 'TriToQuad: ', isDone";
731 #endif
732
733   ::SMESH_MeshEditor anEditor( myMesh );
734
735   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
736
737   StoreResult(anEditor);
738
739   return stat;
740 }
741
742
743 //=============================================================================
744 /*!
745  *
746  */
747 //=============================================================================
748 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
749                                                     SMESH::NumericalFunctor_ptr Criterion,
750                                                     CORBA::Double               MaxAngle)
751 {
752   initData();
753
754   SMESH::long_array_var anElementsId = theObject->GetIDs();
755   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
756
757   // Clear python line(s), created by TriToQuad()
758   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
759   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
760 #ifdef _DEBUG_
761   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
762 #endif
763
764   SMESH::NumericalFunctor_i* aNumericalFunctor =
765     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
766
767   // Update Python script
768   TPythonDump() << "isDone = " << this << ".TriToQuadObject("
769                 << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
770 #ifdef _DEBUG_
771   TPythonDump() << "print 'TriToQuadObject: ', isDone";
772 #endif
773
774   return isDone;
775 }
776
777
778 //=============================================================================
779 /*!
780  *
781  */
782 //=============================================================================
783 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
784                                               SMESH::NumericalFunctor_ptr Criterion)
785 {
786   initData();
787
788   SMESHDS_Mesh* aMesh = GetMeshDS();
789   TIDSortedElemSet faces;
790   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
791
792   SMESH::NumericalFunctor_i* aNumericalFunctor =
793     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
794   SMESH::Controls::NumericalFunctorPtr aCrit;
795   if ( !aNumericalFunctor )
796     aCrit.reset( new SMESH::Controls::AspectRatio() );
797   else
798     aCrit = aNumericalFunctor->GetNumericalFunctor();
799
800
801   // Update Python script
802   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
803 #ifdef _DEBUG_
804   TPythonDump() << "print 'QuadToTri: ', isDone";
805 #endif
806
807   ::SMESH_MeshEditor anEditor( myMesh );
808   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
809
810   StoreResult(anEditor);
811
812   return stat;
813 }
814
815
816 //=============================================================================
817 /*!
818  *
819  */
820 //=============================================================================
821 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
822                                                     SMESH::NumericalFunctor_ptr Criterion)
823 {
824   initData();
825
826   SMESH::long_array_var anElementsId = theObject->GetIDs();
827   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
828
829   // Clear python line(s), created by QuadToTri()
830   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
831   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
832 #ifdef _DEBUG_
833   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
834 #endif
835
836   SMESH::NumericalFunctor_i* aNumericalFunctor =
837     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
838
839   // Update Python script
840   TPythonDump() << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
841 #ifdef _DEBUG_
842   TPythonDump() << "print 'QuadToTriObject: ', isDone";
843 #endif
844
845   return isDone;
846 }
847
848
849 //=============================================================================
850 /*!
851  *
852  */
853 //=============================================================================
854 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
855                                               CORBA::Boolean            Diag13)
856 {
857   initData();
858
859   SMESHDS_Mesh* aMesh = GetMeshDS();
860   TIDSortedElemSet faces;
861   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
862
863   // Update Python script
864   TPythonDump() << "isDone = " << this << ".SplitQuad( "
865                 << IDsOfElements << ", " << Diag13 << " )";
866 #ifdef _DEBUG_
867   TPythonDump() << "print 'SplitQuad: ', isDone";
868 #endif
869
870   ::SMESH_MeshEditor anEditor( myMesh );
871   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
872
873   StoreResult(anEditor);
874
875   return stat;
876 }
877
878
879 //=============================================================================
880 /*!
881  *
882  */
883 //=============================================================================
884 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
885                                                     CORBA::Boolean            Diag13)
886 {
887   initData();
888
889   SMESH::long_array_var anElementsId = theObject->GetIDs();
890   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
891
892   // Clear python line(s), created by SplitQuad()
893   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
894   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
895 #ifdef _DEBUG_
896   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
897 #endif
898
899   // Update Python script
900   TPythonDump() << "isDone = " << this << ".SplitQuadObject( "
901                 << theObject << ", " << Diag13 << " )";
902 #ifdef _DEBUG_
903   TPythonDump() << "print 'SplitQuadObject: ', isDone";
904 #endif
905
906   return isDone;
907 }
908
909
910 //=============================================================================
911 /*!
912  *  BestSplit
913  */
914 //=============================================================================
915 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
916                                            SMESH::NumericalFunctor_ptr Criterion)
917 {
918   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
919   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
920   {
921     SMESH::NumericalFunctor_i* aNumericalFunctor =
922       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
923     SMESH::Controls::NumericalFunctorPtr aCrit;
924     if (aNumericalFunctor)
925       aCrit = aNumericalFunctor->GetNumericalFunctor();
926     else
927       aCrit.reset(new SMESH::Controls::AspectRatio());
928
929     ::SMESH_MeshEditor anEditor (myMesh);
930     return anEditor.BestSplit(quad, aCrit);
931   }
932   return -1;
933 }
934
935
936 //=======================================================================
937 //function : Smooth
938 //purpose  :
939 //=======================================================================
940
941 CORBA::Boolean
942   SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
943                              const SMESH::long_array &              IDsOfFixedNodes,
944                              CORBA::Long                            MaxNbOfIterations,
945                              CORBA::Double                          MaxAspectRatio,
946                              SMESH::SMESH_MeshEditor::Smooth_Method Method)
947 {
948   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
949                 MaxAspectRatio, Method, false );
950 }
951
952
953 //=======================================================================
954 //function : SmoothParametric
955 //purpose  :
956 //=======================================================================
957
958 CORBA::Boolean
959   SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
960                                        const SMESH::long_array &              IDsOfFixedNodes,
961                                        CORBA::Long                            MaxNbOfIterations,
962                                        CORBA::Double                          MaxAspectRatio,
963                                        SMESH::SMESH_MeshEditor::Smooth_Method Method)
964 {
965   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
966                 MaxAspectRatio, Method, true );
967 }
968
969
970 //=======================================================================
971 //function : SmoothObject
972 //purpose  :
973 //=======================================================================
974
975 CORBA::Boolean
976   SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
977                                    const SMESH::long_array &              IDsOfFixedNodes,
978                                    CORBA::Long                            MaxNbOfIterations,
979                                    CORBA::Double                          MaxAspectRatio,
980                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
981 {
982   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
983                        MaxAspectRatio, Method, false);
984 }
985
986
987 //=======================================================================
988 //function : SmoothParametricObject
989 //purpose  :
990 //=======================================================================
991
992 CORBA::Boolean
993   SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
994                                    const SMESH::long_array &              IDsOfFixedNodes,
995                                    CORBA::Long                            MaxNbOfIterations,
996                                    CORBA::Double                          MaxAspectRatio,
997                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
998 {
999   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1000                        MaxAspectRatio, Method, true);
1001 }
1002
1003
1004 //=============================================================================
1005 /*!
1006  *
1007  */
1008 //=============================================================================
1009
1010 CORBA::Boolean
1011   SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1012                              const SMESH::long_array &              IDsOfFixedNodes,
1013                              CORBA::Long                            MaxNbOfIterations,
1014                              CORBA::Double                          MaxAspectRatio,
1015                              SMESH::SMESH_MeshEditor::Smooth_Method Method,
1016                              bool                                   IsParametric)
1017 {
1018   initData();
1019
1020   SMESHDS_Mesh* aMesh = GetMeshDS();
1021
1022   TIDSortedElemSet elements;
1023   ToMap(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1024
1025   set<const SMDS_MeshNode*> fixedNodes;
1026   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1027     CORBA::Long index = IDsOfFixedNodes[i];
1028     const SMDS_MeshNode * node = aMesh->FindNode(index);
1029     if ( node )
1030       fixedNodes.insert( node );
1031   }
1032   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1033   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1034     method = ::SMESH_MeshEditor::CENTROIDAL;
1035
1036   ::SMESH_MeshEditor anEditor( myMesh );
1037   anEditor.Smooth(elements, fixedNodes, method,
1038                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1039
1040   StoreResult(anEditor);
1041
1042   // Update Python script
1043   TPythonDump() << "isDone = " << this << "."
1044                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1045                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1046                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1047                 << "SMESH.SMESH_MeshEditor."
1048                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1049                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1050 #ifdef _DEBUG_
1051   TPythonDump() << "print 'Smooth: ', isDone";
1052 #endif
1053
1054   return true;
1055 }
1056
1057
1058 //=============================================================================
1059 /*!
1060  *
1061  */
1062 //=============================================================================
1063
1064 CORBA::Boolean
1065 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1066                                  const SMESH::long_array &              IDsOfFixedNodes,
1067                                  CORBA::Long                            MaxNbOfIterations,
1068                                  CORBA::Double                          MaxAspectRatio,
1069                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1070                                  bool                                   IsParametric)
1071 {
1072   initData();
1073
1074   SMESH::long_array_var anElementsId = theObject->GetIDs();
1075   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1076                                   MaxAspectRatio, Method, IsParametric);
1077
1078   // Clear python line(s), created by Smooth()
1079   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1080   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1081 #ifdef _DEBUG_
1082   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1083 #endif
1084
1085   // Update Python script
1086   TPythonDump() << "isDone = " << this << "."
1087                 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1088                 << theObject << ", " << IDsOfFixedNodes << ", "
1089                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1090                 << "SMESH.SMESH_MeshEditor."
1091                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1092                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1093 #ifdef _DEBUG_
1094   TPythonDump() << "print 'SmoothObject: ', isDone";
1095 #endif
1096
1097   return isDone;
1098 }
1099
1100
1101 //=============================================================================
1102 /*!
1103  *
1104  */
1105 //=============================================================================
1106
1107 void SMESH_MeshEditor_i::RenumberNodes()
1108 {
1109   // Update Python script
1110   TPythonDump() << this << ".RenumberNodes()";
1111
1112   GetMeshDS()->Renumber( true );
1113 }
1114
1115
1116 //=============================================================================
1117 /*!
1118  *
1119  */
1120 //=============================================================================
1121
1122 void SMESH_MeshEditor_i::RenumberElements()
1123 {
1124   // Update Python script
1125   TPythonDump() << this << ".RenumberElements()";
1126
1127   GetMeshDS()->Renumber( false );
1128 }
1129
1130
1131 //=======================================================================
1132 //function : RotationSweep
1133 //purpose  :
1134 //=======================================================================
1135
1136 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1137                                        const SMESH::AxisStruct & theAxis,
1138                                        CORBA::Double             theAngleInRadians,
1139                                        CORBA::Long               theNbOfSteps,
1140                                        CORBA::Double             theTolerance)
1141 {
1142   initData();
1143
1144   TIDSortedElemSet inElements, copyElements;
1145   ToMap(theIDsOfElements, GetMeshDS(), inElements);
1146
1147   TIDSortedElemSet* workElements = & inElements;
1148   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1149   SMESH_Mesh*       mesh = 0;
1150   bool              makeWalls=true;
1151   if ( myPreviewMode )
1152   {
1153     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1154     tmpMesh.Copy( inElements, copyElements, select, avoid );
1155     mesh = &tmpMesh;
1156     workElements = & copyElements;
1157     //makeWalls = false;
1158   }
1159   else
1160   {
1161     mesh = myMesh;
1162   }
1163
1164   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1165               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1166
1167   ::SMESH_MeshEditor anEditor( mesh );
1168   anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1169                           theNbOfSteps, theTolerance, makeWalls);
1170
1171   StoreResult(anEditor);
1172
1173   if ( !myPreviewMode ) {
1174     // Update Python script
1175     TPythonDump() << "axis = " << theAxis;
1176     TPythonDump() << this << ".RotationSweep( "
1177                   << theIDsOfElements
1178                   << ", axis, "
1179                   << theAngleInRadians << ", "
1180                   << theNbOfSteps << ", "
1181                   << theTolerance << " )";
1182   }
1183 }
1184
1185 //=======================================================================
1186 //function : RotationSweepObject
1187 //purpose  :
1188 //=======================================================================
1189
1190 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1191                                              const SMESH::AxisStruct & theAxis,
1192                                              CORBA::Double             theAngleInRadians,
1193                                              CORBA::Long               theNbOfSteps,
1194                                              CORBA::Double             theTolerance)
1195 {
1196   initData();
1197
1198   SMESH::long_array_var anElementsId = theObject->GetIDs();
1199   RotationSweep(anElementsId, theAxis, theAngleInRadians, theNbOfSteps, theTolerance);
1200
1201   // Clear python line, created by RotationSweep()
1202   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1203   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1204
1205   // Update Python script
1206   TPythonDump() << this << ".RotationSweepObject( "
1207                 << theObject
1208                 << ", axis, "
1209                 << theAngleInRadians << ", "
1210                 << theNbOfSteps << ", "
1211                 << theTolerance << " )";
1212 }
1213
1214 //=======================================================================
1215 //function : ExtrusionSweep
1216 //purpose  :
1217 //=======================================================================
1218
1219 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1220                                         const SMESH::DirStruct &  theStepVector,
1221                                         CORBA::Long               theNbOfSteps)
1222 {
1223   initData();
1224
1225 #ifdef NO_CAS_CATCH
1226   try {   
1227     OCC_CATCH_SIGNALS;
1228 #else
1229   CASCatch_TRY {
1230 #endif
1231     SMESHDS_Mesh* aMesh = GetMeshDS();
1232
1233     TIDSortedElemSet elements;
1234     ToMap(theIDsOfElements, aMesh, elements);
1235
1236     const SMESH::PointStruct * P = &theStepVector.PS;
1237     gp_Vec stepVec( P->x, P->y, P->z );
1238
1239     TElemOfElemListMap aHystory;
1240     ::SMESH_MeshEditor anEditor( myMesh );
1241     anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1242
1243     StoreResult(anEditor);
1244
1245     // Update Python script
1246     TPythonDump() << "stepVector = " << theStepVector;
1247     TPythonDump() << this << ".ExtrusionSweep( "
1248                   << theIDsOfElements << ", stepVector, " << theNbOfSteps << " )";
1249
1250 #ifdef NO_CAS_CATCH
1251   } catch(Standard_Failure) {
1252 #else
1253   } CASCatch_CATCH(Standard_Failure) {
1254 #endif
1255     Handle(Standard_Failure) aFail = Standard_Failure::Caught();          
1256     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1257   }
1258 }
1259
1260
1261 //=======================================================================
1262 //function : ExtrusionSweepObject
1263 //purpose  :
1264 //=======================================================================
1265
1266 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1267                                               const SMESH::DirStruct &  theStepVector,
1268                                               CORBA::Long               theNbOfSteps)
1269 {
1270   initData();
1271
1272   SMESH::long_array_var anElementsId = theObject->GetIDs();
1273   ExtrusionSweep(anElementsId, theStepVector, theNbOfSteps);
1274
1275   // Clear python line, created by ExtrusionSweep()
1276   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1277   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1278
1279   // Update Python script
1280   TPythonDump() << this << ".ExtrusionSweepObject( "
1281                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1282 }
1283
1284 //=======================================================================
1285 //function : ExtrusionSweepObject1D
1286 //purpose  :
1287 //=======================================================================
1288
1289 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1290                                                 const SMESH::DirStruct &  theStepVector,
1291                                                 CORBA::Long               theNbOfSteps)
1292 {
1293   initData();
1294
1295   SMESHDS_Mesh* aMesh = GetMeshDS();
1296
1297   SMESH::long_array_var allElementsId = theObject->GetIDs();
1298
1299   TIDSortedElemSet elements;
1300   ToMap(allElementsId, aMesh, elements);
1301
1302   const SMESH::PointStruct * P = &theStepVector.PS;
1303   gp_Vec stepVec( P->x, P->y, P->z );
1304
1305   ::SMESH_MeshEditor anEditor( myMesh );
1306   //anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps);
1307   TElemOfElemListMap aHystory;
1308   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1309
1310   StoreResult(anEditor);
1311
1312   // Update Python script
1313   TPythonDump() << "stepVector = " << theStepVector;
1314   TPythonDump() << this << ".ExtrusionSweepObject1D( "
1315                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1316 }
1317
1318 //=======================================================================
1319 //function : ExtrusionSweepObject2D
1320 //purpose  :
1321 //=======================================================================
1322
1323 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1324                                                 const SMESH::DirStruct &  theStepVector,
1325                                                 CORBA::Long               theNbOfSteps)
1326 {
1327   initData();
1328
1329   SMESHDS_Mesh* aMesh = GetMeshDS();
1330
1331   SMESH::long_array_var allElementsId = theObject->GetIDs();
1332
1333   TIDSortedElemSet elements;
1334   ToMap(allElementsId, aMesh, elements);
1335
1336   const SMESH::PointStruct * P = &theStepVector.PS;
1337   gp_Vec stepVec( P->x, P->y, P->z );
1338
1339   ::SMESH_MeshEditor anEditor( myMesh );
1340   //anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps);
1341   TElemOfElemListMap aHystory;
1342   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1343
1344   StoreResult(anEditor);
1345
1346   // Update Python script
1347   TPythonDump() << "stepVector = " << theStepVector;
1348   TPythonDump() << this << ".ExtrusionSweepObject2D( "
1349                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1350 }
1351
1352
1353 //=======================================================================
1354 //function : AdvancedExtrusion
1355 //purpose  :
1356 //=======================================================================
1357
1358 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
1359                                            const SMESH::DirStruct &  theStepVector,
1360                                            CORBA::Long               theNbOfSteps,
1361                                            CORBA::Long               theExtrFlags,
1362                                            CORBA::Double             theSewTolerance)
1363 {
1364   initData();
1365
1366   SMESHDS_Mesh* aMesh = GetMeshDS();
1367
1368   TIDSortedElemSet elements;
1369   ToMap(theIDsOfElements, aMesh, elements);
1370
1371   const SMESH::PointStruct * P = &theStepVector.PS;
1372   gp_Vec stepVec( P->x, P->y, P->z );
1373
1374   ::SMESH_MeshEditor anEditor( myMesh );
1375   TElemOfElemListMap aHystory;
1376   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
1377                            theExtrFlags, theSewTolerance);
1378
1379   StoreResult(anEditor);
1380
1381   // Update Python script
1382   TPythonDump() << "stepVector = " << theStepVector;
1383   TPythonDump() << this << ".AdvancedExtrusion("
1384                 << theIDsOfElements
1385                 << ", stepVector, "
1386                 << theNbOfSteps << ","
1387                 << theExtrFlags << ", "
1388                 << theSewTolerance <<  " )";
1389 }
1390
1391
1392 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
1393
1394 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
1395 {
1396   switch ( e ) {
1397   RETCASE( EXTR_OK );
1398   RETCASE( EXTR_NO_ELEMENTS );
1399   RETCASE( EXTR_PATH_NOT_EDGE );
1400   RETCASE( EXTR_BAD_PATH_SHAPE );
1401   RETCASE( EXTR_BAD_STARTING_NODE );
1402   RETCASE( EXTR_BAD_ANGLES_NUMBER );
1403   RETCASE( EXTR_CANT_GET_TANGENT );
1404   }
1405   return SMESH::SMESH_MeshEditor::EXTR_OK;
1406 }
1407
1408 //=======================================================================
1409 //function : ExtrusionAlongPath
1410 //purpose  :
1411 //=======================================================================
1412
1413 SMESH::SMESH_MeshEditor::Extrusion_Error
1414   SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
1415                                          SMESH::SMESH_Mesh_ptr       thePathMesh,
1416                                          GEOM::GEOM_Object_ptr       thePathShape,
1417                                          CORBA::Long                 theNodeStart,
1418                                          CORBA::Boolean              theHasAngles,
1419                                          const SMESH::double_array & theAngles,
1420                                          CORBA::Boolean              theHasRefPoint,
1421                                          const SMESH::PointStruct &  theRefPoint)
1422 {
1423   initData();
1424
1425   SMESHDS_Mesh*  aMesh = GetMeshDS();
1426
1427   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() )
1428     return SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1429
1430   SMESH_Mesh_i* aMeshImp = dynamic_cast<SMESH_Mesh_i*>( SMESH_Gen_i::GetServant( thePathMesh ).in() );
1431   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
1432   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
1433
1434   if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
1435     return SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1436
1437   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
1438   if ( !nodeStart )
1439     return SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
1440
1441   TIDSortedElemSet elements;
1442   ToMap(theIDsOfElements, aMesh, elements);
1443
1444   list<double> angles;
1445   for (int i = 0; i < theAngles.length(); i++) {
1446     angles.push_back( theAngles[i] );
1447   }
1448
1449   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
1450
1451   // Update Python script
1452   TPythonDump() << "rotAngles = " << theAngles;
1453
1454   if ( theHasRefPoint )
1455     TPythonDump() << "refPoint = SMESH.PointStruct( "
1456                   << refPnt.X() << ", "
1457                   << refPnt.Y() << ", "
1458                   << refPnt.Z() << " )";
1459   else
1460     TPythonDump() << "refPoint = SMESH.PointStruct( 0,0,0 )";
1461
1462   TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
1463                 << theIDsOfElements << ", "
1464                 << thePathMesh      << ", "
1465                 << thePathShape     << ", "
1466                 << theNodeStart     << ", "
1467                 << theHasAngles     << ", "
1468                 << "rotAngles"      << ", "
1469                 << theHasRefPoint   << ", refPoint )";
1470
1471   ::SMESH_MeshEditor anEditor( myMesh );
1472   SMESH::SMESH_MeshEditor::Extrusion_Error error = 
1473     convExtrError( anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
1474                                                 theHasAngles, angles,
1475                                                 theHasRefPoint, refPnt ) );
1476
1477   StoreResult(anEditor);
1478
1479   return error;
1480 }
1481
1482 //=======================================================================
1483 //function : ExtrusionAlongPathObject
1484 //purpose  :
1485 //=======================================================================
1486
1487 SMESH::SMESH_MeshEditor::Extrusion_Error
1488 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
1489                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
1490                                              GEOM::GEOM_Object_ptr       thePathShape,
1491                                              CORBA::Long                 theNodeStart,
1492                                              CORBA::Boolean              theHasAngles,
1493                                              const SMESH::double_array & theAngles,
1494                                              CORBA::Boolean              theHasRefPoint,
1495                                              const SMESH::PointStruct &  theRefPoint)
1496 {
1497   initData();
1498
1499   SMESH::long_array_var anElementsId = theObject->GetIDs();
1500   SMESH::SMESH_MeshEditor::Extrusion_Error error = ExtrusionAlongPath
1501     (anElementsId, thePathMesh, thePathShape, theNodeStart,
1502      theHasAngles, theAngles, theHasRefPoint, theRefPoint);
1503
1504   // Clear python line, created by ExtrusionAlongPath()
1505   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1506   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1507
1508   // Update Python script
1509   TPythonDump() << "rotAngles = " << theAngles;
1510   TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
1511                 << theObject    << ", "
1512                 << thePathMesh  << ", "
1513                 << thePathShape << ", "
1514                 << theNodeStart << ", "
1515                 << theHasAngles << ", "
1516                 << "rotAngles"     << ", "
1517                 << theHasRefPoint<<", refPoint )";
1518
1519   return error;
1520 }
1521
1522 //================================================================================
1523 /*!
1524  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
1525  * of given angles along path steps
1526   * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
1527   *                which proceeds the extrusion
1528   * \param PathShape is shape(edge); as the mesh can be complex, the edge 
1529   *                 is used to define the sub-mesh for the path
1530  */
1531 //================================================================================
1532
1533 SMESH::double_array*
1534 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
1535                                           GEOM::GEOM_Object_ptr       thePathShape,
1536                                           const SMESH::double_array & theAngles)
1537 {
1538   SMESH::double_array_var aResult = new SMESH::double_array();
1539   return aResult._retn();
1540 }
1541
1542 //=======================================================================
1543 //function : Mirror
1544 //purpose  :
1545 //=======================================================================
1546
1547 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
1548                                 const SMESH::AxisStruct &           theAxis,
1549                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
1550                                 CORBA::Boolean                      theCopy)
1551 {
1552   initData();
1553
1554   SMESHDS_Mesh* aMesh = GetMeshDS();
1555
1556   TIDSortedElemSet elements;
1557   ToMap(theIDsOfElements, aMesh, elements);
1558
1559   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
1560   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
1561
1562   gp_Trsf aTrsf;
1563   TCollection_AsciiString typeStr;
1564   switch ( theMirrorType ) {
1565   case  SMESH::SMESH_MeshEditor::POINT:
1566     aTrsf.SetMirror( P );
1567     typeStr = "SMESH.SMESH_MeshEditor.POINT";
1568     break;
1569   case  SMESH::SMESH_MeshEditor::AXIS:
1570     aTrsf.SetMirror( gp_Ax1( P, V ));
1571     typeStr = "SMESH.SMESH_MeshEditor.AXIS";
1572     break;
1573   default:
1574     aTrsf.SetMirror( gp_Ax2( P, V ));
1575     typeStr = "SMESH.SMESH_MeshEditor.PLANE";
1576   }
1577
1578   // Update Python script
1579   TPythonDump() << this << ".Mirror( "
1580                 << theIDsOfElements << ", "
1581                 << theAxis           << ", "
1582                 << typeStr           << ", "
1583                 << theCopy           << " )";
1584
1585   ::SMESH_MeshEditor anEditor( myMesh );
1586   anEditor.Transform (elements, aTrsf, theCopy);
1587
1588   if(theCopy) {
1589     StoreResult(anEditor);
1590   }
1591 }
1592
1593
1594 //=======================================================================
1595 //function : MirrorObject
1596 //purpose  :
1597 //=======================================================================
1598
1599 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
1600                                       const SMESH::AxisStruct &           theAxis,
1601                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
1602                                       CORBA::Boolean                      theCopy)
1603 {
1604   initData();
1605
1606   SMESH::long_array_var anElementsId = theObject->GetIDs();
1607   Mirror(anElementsId, theAxis, theMirrorType, theCopy);
1608
1609   // Clear python line, created by Mirror()
1610   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1611   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1612
1613   // Update Python script
1614   TCollection_AsciiString typeStr;
1615   switch ( theMirrorType ) {
1616   case  SMESH::SMESH_MeshEditor::POINT:
1617     typeStr = "SMESH.SMESH_MeshEditor.POINT";
1618     break;
1619   case  SMESH::SMESH_MeshEditor::AXIS:
1620     typeStr = "SMESH.SMESH_MeshEditor.AXIS";
1621     break;
1622   default:
1623     typeStr = "SMESH.SMESH_MeshEditor.PLANE";
1624   }
1625   TPythonDump() << "axis = " << theAxis;
1626   TPythonDump() << this << ".MirrorObject( "
1627                 << theObject << ", "
1628                 << "axis, "
1629                 << typeStr << ", "
1630                 << theCopy << " )";
1631 }
1632
1633 //=======================================================================
1634 //function : Translate
1635 //purpose  :
1636 //=======================================================================
1637
1638 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
1639                                    const SMESH::DirStruct &  theVector,
1640                                    CORBA::Boolean            theCopy)
1641 {
1642   initData();
1643
1644   SMESHDS_Mesh* aMesh = GetMeshDS();
1645
1646   TIDSortedElemSet elements;
1647   ToMap(theIDsOfElements, aMesh, elements);
1648
1649   gp_Trsf aTrsf;
1650   const SMESH::PointStruct * P = &theVector.PS;
1651   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
1652
1653   ::SMESH_MeshEditor anEditor( myMesh );
1654   anEditor.Transform (elements, aTrsf, theCopy);
1655
1656   if(theCopy) {
1657     StoreResult(anEditor);
1658   }
1659
1660   // Update Python script
1661   TPythonDump() << "vector = " << theVector;
1662   TPythonDump() << this << ".Translate( "
1663                 << theIDsOfElements
1664                 << ", vector, "
1665                 << theCopy << " )";
1666 }
1667
1668 //=======================================================================
1669 //function : TranslateObject
1670 //purpose  :
1671 //=======================================================================
1672
1673 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
1674                                          const SMESH::DirStruct &  theVector,
1675                                          CORBA::Boolean            theCopy)
1676 {
1677   initData();
1678
1679   SMESH::long_array_var anElementsId = theObject->GetIDs();
1680   Translate(anElementsId, theVector, theCopy);
1681
1682   // Clear python line, created by Translate()
1683   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1684   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1685
1686   // Update Python script
1687   TPythonDump() << this << ".TranslateObject( "
1688                 << theObject
1689                 << ", vector, "
1690                 << theCopy << " )";
1691 }
1692
1693 //=======================================================================
1694 //function : Rotate
1695 //purpose  :
1696 //=======================================================================
1697
1698 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
1699                                 const SMESH::AxisStruct & theAxis,
1700                                 CORBA::Double             theAngle,
1701                                 CORBA::Boolean            theCopy)
1702 {
1703   initData();
1704
1705   SMESHDS_Mesh* aMesh = GetMeshDS();
1706
1707   TIDSortedElemSet elements;
1708   ToMap(theIDsOfElements, aMesh, elements);
1709
1710   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
1711   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
1712
1713   gp_Trsf aTrsf;
1714   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
1715
1716   ::SMESH_MeshEditor anEditor( myMesh );
1717   anEditor.Transform (elements, aTrsf, theCopy);
1718
1719   if(theCopy) {
1720     StoreResult(anEditor);
1721   }
1722
1723   // Update Python script
1724   TPythonDump() << "axis = " << theAxis;
1725   TPythonDump() << this << ".Rotate( "
1726                 << theIDsOfElements
1727                 << ", axis, "
1728                 << theAngle << ", "
1729                 << theCopy << " )";
1730 }
1731
1732 //=======================================================================
1733 //function : RotateObject
1734 //purpose  :
1735 //=======================================================================
1736
1737 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
1738                                       const SMESH::AxisStruct & theAxis,
1739                                       CORBA::Double             theAngle,
1740                                       CORBA::Boolean            theCopy)
1741 {
1742   initData();
1743
1744   SMESH::long_array_var anElementsId = theObject->GetIDs();
1745   Rotate(anElementsId, theAxis, theAngle, theCopy);
1746
1747   // Clear python line, created by Rotate()
1748   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1749   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1750
1751   // Update Python script
1752   TPythonDump() << this << ".RotateObject( "
1753                 << theObject
1754                 << ", axis, "
1755                 << theAngle << ", "
1756                 << theCopy << " )";
1757 }
1758
1759 //=======================================================================
1760 //function : FindCoincidentNodes
1761 //purpose  :
1762 //=======================================================================
1763
1764 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
1765                                               SMESH::array_of_long_array_out GroupsOfNodes)
1766 {
1767   initData();
1768
1769   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1770   ::SMESH_MeshEditor anEditor( myMesh );
1771   set<const SMDS_MeshNode*> nodes; // no input nodes
1772   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
1773
1774   GroupsOfNodes = new SMESH::array_of_long_array;
1775   GroupsOfNodes->length( aListOfListOfNodes.size() );
1776   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
1777   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
1778     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
1779     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
1780     SMESH::long_array& aGroup = GroupsOfNodes[ i ];
1781     aGroup.length( aListOfNodes.size() );
1782     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
1783       aGroup[ j ] = (*lIt)->GetID();
1784   }
1785   // Update Python script
1786   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
1787                 << Tolerance << " )";
1788 }
1789
1790 //=======================================================================
1791 //function : FindCoincidentNodesOnPart
1792 //purpose  :
1793 //=======================================================================
1794 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
1795                                                    CORBA::Double                  Tolerance,
1796                                                    SMESH::array_of_long_array_out GroupsOfNodes)
1797 {
1798   initData();
1799   SMESH::long_array_var aElementsId = theObject->GetIDs();
1800
1801   SMESHDS_Mesh* aMesh = GetMeshDS();
1802   set<const SMDS_MeshNode*> nodes;
1803
1804   if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
1805       SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) {
1806     for(int i = 0; i < aElementsId->length(); i++) {
1807       CORBA::Long ind = aElementsId[i];
1808       const SMDS_MeshNode * elem = aMesh->FindNode(ind);
1809       if(elem)
1810         nodes.insert(elem);
1811     }
1812   }
1813   else {
1814     for(int i = 0; i < aElementsId->length(); i++) {
1815       CORBA::Long ind = aElementsId[i];
1816       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
1817       if(elem) {
1818         SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
1819         while ( nIt->more() )
1820           nodes.insert( nodes.end(),static_cast<const SMDS_MeshNode*>(nIt->next()));
1821       }
1822     }
1823   }
1824     
1825   
1826   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1827   ::SMESH_MeshEditor anEditor( myMesh );
1828   if(!nodes.empty())
1829     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
1830   
1831   GroupsOfNodes = new SMESH::array_of_long_array;
1832   GroupsOfNodes->length( aListOfListOfNodes.size() );
1833   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
1834   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
1835     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
1836     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
1837     SMESH::long_array& aGroup = GroupsOfNodes[ i ];
1838     aGroup.length( aListOfNodes.size() );
1839     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
1840       aGroup[ j ] = (*lIt)->GetID();
1841   }
1842   // Update Python script
1843   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
1844                 <<theObject<<", "
1845                 << Tolerance << " )";
1846 }
1847
1848 //=======================================================================
1849 //function : MergeNodes
1850 //purpose  :
1851 //=======================================================================
1852
1853 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
1854 {
1855   initData();
1856
1857   SMESHDS_Mesh* aMesh = GetMeshDS();
1858
1859   TPythonDump aTPythonDump;
1860   aTPythonDump << this << ".MergeNodes([";
1861   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1862   for (int i = 0; i < GroupsOfNodes.length(); i++)
1863   {
1864     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
1865     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
1866     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
1867     for ( int j = 0; j < aNodeGroup.length(); j++ )
1868     {
1869       CORBA::Long index = aNodeGroup[ j ];
1870       const SMDS_MeshNode * node = aMesh->FindNode(index);
1871       if ( node )
1872         aListOfNodes.push_back( node );
1873     }
1874     if ( aListOfNodes.size() < 2 )
1875       aListOfListOfNodes.pop_back();
1876
1877     if ( i > 0 ) aTPythonDump << ", ";
1878     aTPythonDump << aNodeGroup;
1879   }
1880   ::SMESH_MeshEditor anEditor( myMesh );
1881   anEditor.MergeNodes( aListOfListOfNodes );
1882
1883   // Update Python script
1884   aTPythonDump <<  "])";
1885 }
1886
1887 //=======================================================================
1888 //function : MergeEqualElements
1889 //purpose  :
1890 //=======================================================================
1891
1892 void SMESH_MeshEditor_i::MergeEqualElements()
1893 {
1894   initData();
1895
1896   ::SMESH_MeshEditor anEditor( myMesh );
1897   anEditor.MergeEqualElements();
1898
1899   // Update Python script
1900   TPythonDump() << this << ".MergeEqualElements()";
1901 }
1902
1903 //================================================================================
1904 /*!
1905  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
1906  * move the node closest to the point to point's location and return ID of the node
1907  */
1908 //================================================================================
1909
1910 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
1911                                                        CORBA::Double y,
1912                                                        CORBA::Double z,
1913                                                        CORBA::Long   theNodeID)
1914 {
1915   // We keep myNodeSearcher until any mesh modification:
1916   // 1) initData() deletes myNodeSearcher at any edition,
1917   // 2) TNodeSearcherDeleter - at any mesh compute event and mesh change
1918
1919   initData();
1920
1921   int nodeID = theNodeID;
1922   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
1923   if ( !node )
1924   {
1925     static TNodeSearcherDeleter deleter;
1926     deleter.Set( myMesh );
1927     if ( !myNodeSearcher ) {
1928       ::SMESH_MeshEditor anEditor( myMesh );
1929       myNodeSearcher = anEditor.GetNodeSearcher();
1930     }
1931     gp_Pnt p( x,y,z );
1932     node = myNodeSearcher->FindClosestTo( p );
1933   }
1934   if ( node ) {
1935     nodeID = node->GetID();
1936     if ( myPreviewMode ) // make preview data
1937     {
1938       // in a preview mesh, make edges linked to a node
1939       TPreviewMesh tmpMesh;
1940       TIDSortedElemSet linkedNodes;
1941       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
1942       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
1943       for ( ; nIt != linkedNodes.end(); ++nIt )
1944       {
1945         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
1946         tmpMesh.Copy( &edge );
1947       }
1948       // move copied node
1949       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
1950       if ( node )
1951         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
1952       // fill preview data
1953       ::SMESH_MeshEditor anEditor( & tmpMesh );
1954       StoreResult( anEditor );
1955     }
1956     else
1957     {
1958       GetMeshDS()->MoveNode(node, x, y, z);
1959     }
1960   }
1961
1962   if ( !myPreviewMode ) {
1963     // Update Python script
1964     TPythonDump() << "nodeID = " << this
1965                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z << " )";
1966   }
1967
1968   return nodeID;
1969 }
1970
1971 //=======================================================================
1972 //function : convError
1973 //purpose  :
1974 //=======================================================================
1975
1976 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
1977
1978 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
1979 {
1980   switch ( e ) {
1981   RETCASE( SEW_OK );
1982   RETCASE( SEW_BORDER1_NOT_FOUND );
1983   RETCASE( SEW_BORDER2_NOT_FOUND );
1984   RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
1985   RETCASE( SEW_BAD_SIDE_NODES );
1986   RETCASE( SEW_VOLUMES_TO_SPLIT );
1987   RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
1988   RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
1989   RETCASE( SEW_BAD_SIDE1_NODES );
1990   RETCASE( SEW_BAD_SIDE2_NODES );
1991   }
1992   return SMESH::SMESH_MeshEditor::SEW_OK;
1993 }
1994
1995 //=======================================================================
1996 //function : SewFreeBorders
1997 //purpose  :
1998 //=======================================================================
1999
2000 SMESH::SMESH_MeshEditor::Sew_Error
2001   SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
2002                                      CORBA::Long SecondNodeID1,
2003                                      CORBA::Long LastNodeID1,
2004                                      CORBA::Long FirstNodeID2,
2005                                      CORBA::Long SecondNodeID2,
2006                                      CORBA::Long LastNodeID2,
2007                                      CORBA::Boolean CreatePolygons,
2008                                      CORBA::Boolean CreatePolyedrs)
2009 {
2010   initData();
2011
2012   SMESHDS_Mesh* aMesh = GetMeshDS();
2013
2014   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
2015   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
2016   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
2017   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
2018   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
2019   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
2020
2021   if (!aBorderFirstNode ||
2022       !aBorderSecondNode||
2023       !aBorderLastNode)
2024     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2025   if (!aSide2FirstNode  ||
2026       !aSide2SecondNode ||
2027       !aSide2ThirdNode)
2028     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
2029
2030   // Update Python script
2031   TPythonDump() << "error = " << this << ".SewFreeBorders( "
2032                 << FirstNodeID1  << ", "
2033                 << SecondNodeID1 << ", "
2034                 << LastNodeID1   << ", "
2035                 << FirstNodeID2  << ", "
2036                 << SecondNodeID2 << ", "
2037                 << LastNodeID2   << ", "
2038                 << CreatePolygons<< ", "
2039                 << CreatePolyedrs<< " )";
2040
2041   ::SMESH_MeshEditor anEditor( myMesh );
2042   SMESH::SMESH_MeshEditor::Sew_Error error =
2043     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2044                                        aBorderSecondNode,
2045                                        aBorderLastNode,
2046                                        aSide2FirstNode,
2047                                        aSide2SecondNode,
2048                                        aSide2ThirdNode,
2049                                        true,
2050                                        CreatePolygons,
2051                                        CreatePolyedrs) );
2052
2053   StoreResult(anEditor);
2054
2055   return error;
2056 }
2057
2058
2059 //=======================================================================
2060 //function : SewConformFreeBorders
2061 //purpose  :
2062 //=======================================================================
2063
2064 SMESH::SMESH_MeshEditor::Sew_Error
2065 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
2066                                           CORBA::Long SecondNodeID1,
2067                                           CORBA::Long LastNodeID1,
2068                                           CORBA::Long FirstNodeID2,
2069                                           CORBA::Long SecondNodeID2)
2070 {
2071   initData();
2072
2073   SMESHDS_Mesh* aMesh = GetMeshDS();
2074
2075   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
2076   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
2077   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
2078   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
2079   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
2080   const SMDS_MeshNode* aSide2ThirdNode   = 0;
2081
2082   if (!aBorderFirstNode ||
2083       !aBorderSecondNode||
2084       !aBorderLastNode )
2085     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2086   if (!aSide2FirstNode  ||
2087       !aSide2SecondNode)
2088     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
2089
2090   // Update Python script
2091   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
2092                 << FirstNodeID1  << ", "
2093                 << SecondNodeID1 << ", "
2094                 << LastNodeID1   << ", "
2095                 << FirstNodeID2  << ", "
2096                 << SecondNodeID2 << " )";
2097
2098   ::SMESH_MeshEditor anEditor( myMesh );
2099   SMESH::SMESH_MeshEditor::Sew_Error error =
2100     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2101                                        aBorderSecondNode,
2102                                        aBorderLastNode,
2103                                        aSide2FirstNode,
2104                                        aSide2SecondNode,
2105                                        aSide2ThirdNode,
2106                                        true,
2107                                        false, false) );
2108
2109   StoreResult(anEditor);
2110
2111   return error;
2112 }
2113
2114
2115 //=======================================================================
2116 //function : SewBorderToSide
2117 //purpose  :
2118 //=======================================================================
2119
2120 SMESH::SMESH_MeshEditor::Sew_Error
2121 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
2122                                     CORBA::Long SecondNodeIDOnFreeBorder,
2123                                     CORBA::Long LastNodeIDOnFreeBorder,
2124                                     CORBA::Long FirstNodeIDOnSide,
2125                                     CORBA::Long LastNodeIDOnSide,
2126                                     CORBA::Boolean CreatePolygons,
2127                                     CORBA::Boolean CreatePolyedrs)
2128 {
2129   initData();
2130
2131   SMESHDS_Mesh* aMesh = GetMeshDS();
2132
2133   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
2134   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
2135   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
2136   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
2137   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
2138   const SMDS_MeshNode* aSide2ThirdNode   = 0;
2139
2140   if (!aBorderFirstNode ||
2141       !aBorderSecondNode||
2142       !aBorderLastNode  )
2143     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2144   if (!aSide2FirstNode  ||
2145       !aSide2SecondNode)
2146     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
2147
2148   // Update Python script
2149   TPythonDump() << "error = " << this << ".SewBorderToSide( "
2150                 << FirstNodeIDOnFreeBorder  << ", "
2151                 << SecondNodeIDOnFreeBorder << ", "
2152                 << LastNodeIDOnFreeBorder   << ", "
2153                 << FirstNodeIDOnSide        << ", "
2154                 << LastNodeIDOnSide         << ", "
2155                 << CreatePolygons           << ", "
2156                 << CreatePolyedrs           << ") ";
2157
2158   ::SMESH_MeshEditor anEditor( myMesh );
2159   SMESH::SMESH_MeshEditor::Sew_Error error =
2160     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2161                                        aBorderSecondNode,
2162                                        aBorderLastNode,
2163                                        aSide2FirstNode,
2164                                        aSide2SecondNode,
2165                                        aSide2ThirdNode,
2166                                        false,
2167                                        CreatePolygons,
2168                                        CreatePolyedrs) );
2169
2170   StoreResult(anEditor);
2171
2172   return error;
2173 }
2174
2175
2176 //=======================================================================
2177 //function : SewSideElements
2178 //purpose  :
2179 //=======================================================================
2180
2181 SMESH::SMESH_MeshEditor::Sew_Error
2182 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
2183                                     const SMESH::long_array& IDsOfSide2Elements,
2184                                     CORBA::Long NodeID1OfSide1ToMerge,
2185                                     CORBA::Long NodeID1OfSide2ToMerge,
2186                                     CORBA::Long NodeID2OfSide1ToMerge,
2187                                     CORBA::Long NodeID2OfSide2ToMerge)
2188 {
2189   initData();
2190
2191   SMESHDS_Mesh* aMesh = GetMeshDS();
2192
2193   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
2194   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
2195   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
2196   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
2197
2198   if (!aFirstNode1ToMerge ||
2199       !aFirstNode2ToMerge )
2200     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
2201   if (!aSecondNode1ToMerge||
2202       !aSecondNode2ToMerge)
2203     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
2204
2205   TIDSortedElemSet aSide1Elems, aSide2Elems;
2206   ToMap(IDsOfSide1Elements, aMesh, aSide1Elems);
2207   ToMap(IDsOfSide2Elements, aMesh, aSide2Elems);
2208
2209   // Update Python script
2210   TPythonDump() << "error = " << this << ".SewSideElements( "
2211                 << IDsOfSide1Elements << ", "
2212                 << IDsOfSide2Elements << ", "
2213                 << NodeID1OfSide1ToMerge << ", "
2214                 << NodeID1OfSide2ToMerge << ", "
2215                 << NodeID2OfSide1ToMerge << ", "
2216                 << NodeID2OfSide2ToMerge << ")";
2217
2218   ::SMESH_MeshEditor anEditor( myMesh );
2219   SMESH::SMESH_MeshEditor::Sew_Error error =
2220     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
2221                                          aFirstNode1ToMerge,
2222                                          aFirstNode2ToMerge,
2223                                          aSecondNode1ToMerge,
2224                                          aSecondNode2ToMerge));
2225
2226   StoreResult(anEditor);
2227
2228   return error;
2229 }
2230
2231 //================================================================================
2232 /*!
2233  * \brief Set new nodes for given element
2234   * \param ide - element id
2235   * \param newIDs - new node ids
2236   * \retval CORBA::Boolean - true if result is OK
2237  */
2238 //================================================================================
2239
2240 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
2241                                                    const SMESH::long_array& newIDs)
2242 {
2243   initData();
2244
2245   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
2246   if(!elem) return false;
2247
2248   int nbn = newIDs.length();
2249   int i=0;
2250   const SMDS_MeshNode* aNodes [nbn];
2251   int nbn1=-1;
2252   for(; i<nbn; i++) {
2253     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
2254     if(aNode) {
2255       nbn1++;
2256       aNodes[nbn1] = aNode;
2257     }
2258   }
2259   // Update Python script
2260   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
2261                 << ide << ", " << newIDs << " )";
2262 #ifdef _DEBUG_
2263   TPythonDump() << "print 'ChangeElemNodes: ', isDone";
2264 #endif
2265
2266   return GetMeshDS()->ChangeElementNodes( elem, aNodes, nbn1+1 );
2267 }
2268   
2269 //================================================================================
2270 /*!
2271  * \brief Update myLastCreated* or myPreviewData
2272   * \param anEditor - it contains last modification results
2273  */
2274 //================================================================================
2275
2276 void SMESH_MeshEditor_i::StoreResult(::SMESH_MeshEditor& anEditor)
2277 {
2278   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
2279
2280     list<int> aNodesConnectivity;
2281     typedef map<int, int> TNodesMap;
2282     TNodesMap nodesMap;
2283
2284     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
2285     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
2286
2287     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
2288     int nbEdges = aMeshDS->NbEdges();
2289     int nbFaces = aMeshDS->NbFaces();
2290     int nbVolum = aMeshDS->NbVolumes();
2291     switch ( previewType ) {
2292     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
2293     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
2294     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
2295     default:;
2296     }
2297     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
2298     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
2299     int i = 0, j = 0;
2300     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
2301
2302     while ( itMeshElems->more() ) {
2303       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
2304       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
2305         continue;
2306
2307       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
2308       while ( itElemNodes->more() ) {
2309         const SMDS_MeshNode* aMeshNode = 
2310           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
2311         int aNodeID = aMeshNode->GetID();
2312         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
2313         if ( anIter == nodesMap.end() ) {
2314           // filling the nodes coordinates
2315           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
2316           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
2317           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
2318           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
2319           j++;
2320         }
2321         aNodesConnectivity.push_back(anIter->second);
2322       }
2323
2324       // filling the elements types
2325       SMDSAbs_ElementType aType;
2326       bool isPoly;
2327       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
2328         aType = SMDSAbs_Node;
2329         isPoly = false;
2330       }
2331       else*/ {
2332         aType = aMeshElem->GetType();
2333         isPoly = aMeshElem->IsPoly();
2334       }
2335
2336       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
2337       myPreviewData->elementTypes[i].isPoly = isPoly;
2338       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
2339       i++;
2340
2341     }
2342     myPreviewData->nodesXYZ.length( j );
2343
2344     // filling the elements connectivities
2345     list<int>::iterator aConnIter = aNodesConnectivity.begin();
2346     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
2347     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
2348       myPreviewData->elementConnectivities[i] = *aConnIter;
2349     
2350     return;
2351   }
2352
2353   {
2354     // add new nodes into myLastCreatedNodes
2355     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
2356     myLastCreatedNodes->length(aSeq.Length());
2357     for(int i=0; i<aSeq.Length(); i++)
2358       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
2359   }
2360   {
2361     // add new elements into myLastCreatedElems
2362     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
2363     myLastCreatedElems->length(aSeq.Length());
2364     for(int i=0; i<aSeq.Length(); i++)
2365       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
2366   }
2367 }
2368
2369 //================================================================================
2370 /*!
2371  * Return data of mesh edition preview
2372  */
2373 //================================================================================
2374
2375 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
2376 {
2377   return myPreviewData._retn();
2378 }
2379
2380 //================================================================================
2381 /*!
2382  * \brief Returns list of it's IDs of created nodes
2383   * \retval SMESH::long_array* - list of node ID
2384  */
2385 //================================================================================
2386
2387 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
2388 {
2389   return myLastCreatedNodes._retn();
2390 }
2391
2392 //================================================================================
2393 /*!
2394  * \brief Returns list of it's IDs of created elements
2395   * \retval SMESH::long_array* - list of elements' ID
2396  */
2397 //================================================================================
2398
2399 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
2400 {
2401   return myLastCreatedElems._retn();
2402 }
2403
2404 //=======================================================================
2405 //function : ConvertToQuadratic
2406 //purpose  :
2407 //=======================================================================
2408
2409 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
2410 {
2411   ::SMESH_MeshEditor anEditor( myMesh );
2412   anEditor.ConvertToQuadratic(theForce3d);
2413  // Update Python script
2414   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
2415 }
2416
2417 //=======================================================================
2418 //function : ConvertFromQuadratic
2419 //purpose  :
2420 //=======================================================================
2421
2422 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
2423 {
2424   ::SMESH_MeshEditor anEditor( myMesh );
2425   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
2426   // Update Python script
2427   TPythonDump() << this << ".ConvertFromQuadratic()";
2428   return isDone;
2429 }