Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 //  File   : SMESH_MeshEditor_i.cxx
24 //  Author : Nicolas REJNERI
25 //  Module : SMESH
26
27 #include "SMESH_MeshEditor_i.hxx"
28
29 #include "SMDS_MeshEdge.hxx"
30 #include "SMDS_MeshFace.hxx"
31 #include "SMDS_MeshVolume.hxx"
32 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
33 #include "SMESH_MeshEditor.hxx"
34 #include "SMESH_subMeshEventListener.hxx"
35 #include "SMESH_Gen_i.hxx"
36 #include "SMESH_Filter_i.hxx"
37 #include "SMESH_PythonDump.hxx"
38
39 #include "utilities.h"
40 #include "Utils_ExceptHandlers.hxx"
41 #include "Utils_CorbaException.hxx"
42
43 #include <BRepAdaptor_Surface.hxx>
44 #include <BRep_Tool.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopoDS.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <gp_Ax1.hxx>
50 #include <gp_Ax2.hxx>
51 #include <gp_Vec.hxx>
52
53 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
54 #define NO_CAS_CATCH
55 #endif
56
57 #include <Standard_Failure.hxx>
58
59 #ifdef NO_CAS_CATCH
60 #include <Standard_ErrorHandler.hxx>
61 #endif
62
63 #include <sstream>
64
65 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
66
67 using namespace std;
68 using SMESH::TPythonDump;
69
70 namespace {
71
72   //=============================================================================
73   /*!
74    * \brief Mesh to apply modifications for preview purposes
75    */
76   //=============================================================================
77
78   struct TPreviewMesh: public SMESH_Mesh
79   {
80     SMDSAbs_ElementType myPreviewType; // type to show
81     //!< Constructor
82     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
83       _isShapeToMesh = _id =_studyId =_idDoc = 0;
84       _myMeshDS  = new SMESHDS_Mesh( _id, true );
85       myPreviewType = previewElements;
86     }
87     //!< Destructor
88     virtual ~TPreviewMesh() { delete _myMeshDS; }
89     //!< Copy a set of elements
90     void Copy(const TIDSortedElemSet & theElements,
91               TIDSortedElemSet&        theCopyElements,
92               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
93               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
94     {
95       // loop on theIDsOfElements
96       TIDSortedElemSet::const_iterator eIt = theElements.begin();
97       for ( ; eIt != theElements.end(); ++eIt )
98       {
99         const SMDS_MeshElement* anElem = *eIt;
100         if ( !anElem ) continue;
101         SMDSAbs_ElementType type = anElem->GetType();
102         if ( type == theAvoidType ||
103              ( theSelectType != SMDSAbs_All && type != theSelectType ))
104           continue;
105
106         if ( const SMDS_MeshElement* anElemCopy = Copy( anElem ))
107           theCopyElements.insert( theCopyElements.end(), anElemCopy );
108       }
109     }
110     //!< Copy an element
111     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
112     {
113       // copy element nodes
114       int anElemNbNodes = anElem->NbNodes();
115       vector< int > anElemNodesID( anElemNbNodes ) ;
116       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
117       for ( int i = 0; itElemNodes->more(); i++)
118       {
119         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
120         Copy( anElemNode );
121         anElemNodesID[i] = anElemNode->GetID();
122       }
123
124       // creates a corresponding element on copied nodes
125       SMDS_MeshElement* anElemCopy = 0;
126       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
127       {
128         const SMDS_PolyhedralVolumeOfNodes* ph =
129           dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem);
130         if ( ph )
131           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
132             (anElemNodesID, ph->GetQuanities(),anElem->GetID());
133       }
134       else {
135         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
136                                                           anElem->GetType(),
137                                                           anElem->IsPoly() );
138       }
139       return anElemCopy;
140     }
141     //!< Copy a node
142     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
143     {
144       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(), 
145                                       anElemNode->GetID());
146     }
147   };// struct TPreviewMesh
148
149   static SMESH_NodeSearcher * myNodeSearcher = 0;
150
151   //=============================================================================
152   /*!
153    * \brief Deleter of myNodeSearcher at any compute event occured
154    */
155   //=============================================================================
156
157   struct TNodeSearcherDeleter : public SMESH_subMeshEventListener
158   {
159     SMESH_Mesh* myMesh;
160     //!< Constructor
161     TNodeSearcherDeleter(): SMESH_subMeshEventListener( false ), // won't be deleted by submesh
162     myMesh(0) {}
163     //!< Delete myNodeSearcher
164     static void Delete()
165     {
166       if ( myNodeSearcher ) { delete myNodeSearcher; myNodeSearcher = 0; }
167     }
168     typedef map < int, SMESH_subMesh * > TDependsOnMap;
169     //!< The meshod called by submesh: do my main job
170     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
171                       SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
172     {
173       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
174         Delete();
175         Unset( sm->GetFather() );
176       }
177     }
178     //!< set self on all submeshes and delete myNodeSearcher if other mesh is set
179     void Set(SMESH_Mesh* mesh)
180     {
181       if ( myMesh && myMesh != mesh ) {
182         Delete();
183         Unset( myMesh );
184       }
185       myMesh = mesh;
186       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
187         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
188         TDependsOnMap::const_iterator sm;
189         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
190           sm->second->SetEventListener( this, 0, sm->second );
191       }
192     }
193     //!<  delete self from all submeshes
194     void Unset(SMESH_Mesh* mesh)
195     {
196       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
197         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
198         TDependsOnMap::const_iterator sm;
199         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
200           sm->second->DeleteEventListener( this );
201       }
202     }
203   };
204
205   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
206   {
207     TCollection_AsciiString typeStr;
208     switch ( theMirrorType ) {
209     case  SMESH::SMESH_MeshEditor::POINT:
210       typeStr = "SMESH.SMESH_MeshEditor.POINT";
211       break;
212     case  SMESH::SMESH_MeshEditor::AXIS:
213       typeStr = "SMESH.SMESH_MeshEditor.AXIS";
214       break;
215     default:
216       typeStr = "SMESH.SMESH_MeshEditor.PLANE";
217     }
218     return typeStr;
219   }
220 }
221
222 //=============================================================================
223 /*!
224  *
225  */
226 //=============================================================================
227
228 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview)
229 {
230   myMesh_i = theMesh;
231   myMesh = & theMesh->GetImpl();
232   myPreviewMode = isPreview;
233 }
234
235 //================================================================================
236 /*!
237  * \brief Destructor
238  */
239 //================================================================================
240
241 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
242 {
243 }
244
245 //================================================================================
246 /*!
247  * \brief Clear members
248  */
249 //================================================================================
250
251 void SMESH_MeshEditor_i::initData()
252 {
253   if ( myPreviewMode ) {
254     myPreviewData = new SMESH::MeshPreviewStruct();
255   }
256   else {
257     myLastCreatedElems = new SMESH::long_array();
258     myLastCreatedNodes = new SMESH::long_array();
259     TNodeSearcherDeleter::Delete();
260   }
261 }
262
263 //=============================================================================
264 /*!
265  *
266  */
267 //=============================================================================
268
269 CORBA::Boolean
270   SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
271 {
272   initData();
273
274   ::SMESH_MeshEditor anEditor( myMesh );
275   list< int > IdList;
276
277   for (int i = 0; i < IDsOfElements.length(); i++)
278     IdList.push_back( IDsOfElements[i] );
279
280   // Update Python script
281   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
282 #ifdef _DEBUG_
283   TPythonDump() << "print 'RemoveElements: ', isDone";
284 #endif
285   // Remove Elements
286   return anEditor.Remove( IdList, false );
287 }
288
289 //=============================================================================
290 /*!
291  *
292  */
293 //=============================================================================
294
295 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
296 {
297   initData();
298
299   ::SMESH_MeshEditor anEditor( myMesh );
300   list< int > IdList;
301   for (int i = 0; i < IDsOfNodes.length(); i++)
302     IdList.push_back( IDsOfNodes[i] );
303
304   // Update Python script
305   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
306 #ifdef _DEBUG_
307   TPythonDump() << "print 'RemoveNodes: ', isDone";
308 #endif
309
310   return anEditor.Remove( IdList, true );
311 }
312
313 //=============================================================================
314 /*!
315  *
316  */
317 //=============================================================================
318
319 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
320 {
321   initData();
322
323   int NbNodes = IDsOfNodes.length();
324   SMDS_MeshElement* elem = 0;
325   if (NbNodes == 2)
326   {
327     CORBA::Long index1 = IDsOfNodes[0];
328     CORBA::Long index2 = IDsOfNodes[1];
329     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(index1), GetMeshDS()->FindNode(index2));
330
331     // Update Python script
332     TPythonDump() << "edge = " << this << ".AddEdge([ "
333                   << index1 << ", " << index2 <<" ])";
334   }
335   if (NbNodes == 3) {
336     CORBA::Long n1 = IDsOfNodes[0];
337     CORBA::Long n2 = IDsOfNodes[1];
338     CORBA::Long n12 = IDsOfNodes[2];
339     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(n1),
340                                 GetMeshDS()->FindNode(n2),
341                                 GetMeshDS()->FindNode(n12));
342     // Update Python script
343     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
344                   <<n1<<", "<<n2<<", "<<n12<<" ])";
345   }
346
347   if(elem)
348     return elem->GetID();
349
350   return 0;
351 }
352
353 //=============================================================================
354 /*!
355  *
356  */
357 //=============================================================================
358
359 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
360                                         CORBA::Double y, CORBA::Double z)
361 {
362   initData();
363
364   const SMDS_MeshNode* N = GetMeshDS()->AddNode(x, y, z);
365
366   // Update Python script
367   TPythonDump() << "nodeID = " << this << ".AddNode( "
368                 << x << ", " << y << ", " << z << " )";
369
370   return N->GetID();
371 }
372
373 //=============================================================================
374 /*!
375  *  AddFace
376  */
377 //=============================================================================
378
379 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
380 {
381   initData();
382
383   int NbNodes = IDsOfNodes.length();
384   if (NbNodes < 3)
385   {
386     return 0;
387   }
388
389   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
390   for (int i = 0; i < NbNodes; i++)
391     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
392
393   SMDS_MeshElement* elem = 0;
394   if (NbNodes == 3) {
395     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
396   }
397   else if (NbNodes == 4) {
398     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
399   }
400   else if (NbNodes == 6) {
401     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
402                                 nodes[4], nodes[5]);
403   }
404   else if (NbNodes == 8) {
405     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
406                                 nodes[4], nodes[5], nodes[6], nodes[7]);
407   }
408
409   // Update Python script
410   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
411
412   if(elem)
413     return elem->GetID();
414
415   return 0;
416 }
417
418 //=============================================================================
419 /*!
420  *  AddPolygonalFace
421  */
422 //=============================================================================
423 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace
424                                    (const SMESH::long_array & IDsOfNodes)
425 {
426   initData();
427
428   int NbNodes = IDsOfNodes.length();
429   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
430   for (int i = 0; i < NbNodes; i++)
431     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
432
433   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
434   
435   // Update Python script
436   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
437 #ifdef _DEBUG_
438   TPythonDump() << "print 'AddPolygonalFace: ', faceID";
439 #endif
440
441   if(elem)
442     return elem->GetID();
443
444   return 0;
445 }
446
447 //=============================================================================
448 /*!
449  *
450  */
451 //=============================================================================
452
453 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
454 {
455   initData();
456
457   int NbNodes = IDsOfNodes.length();
458   vector< const SMDS_MeshNode*> n(NbNodes);
459   for(int i=0;i<NbNodes;i++)
460     n[i]=GetMeshDS()->FindNode(IDsOfNodes[i]);
461
462   SMDS_MeshElement* elem = 0;
463   switch(NbNodes)
464   {
465   case 4 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
466   case 5 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
467   case 6 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
468   case 8 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
469   case 10:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
470                                         n[6],n[7],n[8],n[9]);
471     break;
472   case 13:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
473                                         n[7],n[8],n[9],n[10],n[11],n[12]);
474     break;
475   case 15:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
476                                         n[9],n[10],n[11],n[12],n[13],n[14]);
477     break;
478   case 20:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
479                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
480                                         n[15],n[16],n[17],n[18],n[19]);
481     break;
482   }
483
484   // Update Python script
485   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
486 #ifdef _DEBUG_
487   TPythonDump() << "print 'AddVolume: ', volID";
488 #endif
489
490   if(elem)
491     return elem->GetID();
492
493   return 0;
494 }
495
496 //=============================================================================
497 /*!
498  *  AddPolyhedralVolume
499  */
500 //=============================================================================
501 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
502                                    (const SMESH::long_array & IDsOfNodes,
503                                     const SMESH::long_array & Quantities)
504 {
505   initData();
506
507   int NbNodes = IDsOfNodes.length();
508   std::vector<const SMDS_MeshNode*> n (NbNodes);
509   for (int i = 0; i < NbNodes; i++)
510     n[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
511
512   int NbFaces = Quantities.length();
513   std::vector<int> q (NbFaces);
514   for (int j = 0; j < NbFaces; j++)
515     q[j] = Quantities[j];
516
517   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(n, q);
518
519   // Update Python script
520   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
521                 << IDsOfNodes << ", " << Quantities << " )";
522 #ifdef _DEBUG_
523   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
524 #endif
525
526   if(elem)
527     return elem->GetID();
528
529   return 0;
530 }
531
532 //=============================================================================
533 /*!
534  *  AddPolyhedralVolumeByFaces
535  */
536 //=============================================================================
537 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces
538                                    (const SMESH::long_array & IdsOfFaces)
539 {
540   initData();
541
542   int NbFaces = IdsOfFaces.length();
543   std::vector<const SMDS_MeshNode*> poly_nodes;
544   std::vector<int> quantities (NbFaces);
545
546   for (int i = 0; i < NbFaces; i++) {
547     const SMDS_MeshElement* aFace = GetMeshDS()->FindElement(IdsOfFaces[i]);
548     quantities[i] = aFace->NbNodes();
549
550     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
551     while (It->more()) {
552       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
553     }
554   }
555
556   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
557
558   // Update Python script
559   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
560                 << IdsOfFaces << " )";
561 #ifdef _DEBUG_
562   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
563 #endif
564
565   if(elem)
566     return elem->GetID();
567
568   return 0;
569 }
570
571 //=============================================================================
572 /*!
573  * \brief Bind a node to a vertex
574  * \param NodeID - node ID
575  * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
576  * \retval boolean - false if NodeID or VertexID is invalid
577  */
578 //=============================================================================
579
580 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
581   throw (SALOME::SALOME_Exception)
582 {
583   Unexpect aCatch(SALOME_SalomeException);
584
585   SMESHDS_Mesh * mesh = GetMeshDS();
586   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
587   if ( !node )
588     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
589
590   if ( mesh->MaxShapeIndex() < VertexID )
591     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
592
593   TopoDS_Shape shape = mesh->IndexToShape( VertexID );
594   if ( shape.ShapeType() != TopAbs_VERTEX )
595     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
596
597   mesh->SetNodeOnVertex( node, VertexID );
598 }
599
600 //=============================================================================
601 /*!
602  * \brief Store node position on an edge
603  * \param NodeID - node ID
604  * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
605  * \param paramOnEdge - parameter on edge where the node is located
606  * \retval boolean - false if any parameter is invalid
607  */
608 //=============================================================================
609
610 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
611                                        CORBA::Double paramOnEdge)
612   throw (SALOME::SALOME_Exception)
613 {
614   Unexpect aCatch(SALOME_SalomeException);
615
616   SMESHDS_Mesh * mesh = GetMeshDS();
617   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
618   if ( !node )
619     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
620
621   if ( mesh->MaxShapeIndex() < EdgeID )
622     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
623
624   TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
625   if ( shape.ShapeType() != TopAbs_EDGE )
626     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
627
628   Standard_Real f,l;
629   BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
630   if ( paramOnEdge < f || paramOnEdge > l )
631     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
632
633   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
634 }
635
636 //=============================================================================
637 /*!
638  * \brief Store node position on a face
639  * \param NodeID - node ID
640  * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
641  * \param u - U parameter on face where the node is located
642  * \param v - V parameter on face where the node is located
643  * \retval boolean - false if any parameter is invalid
644  */
645 //=============================================================================
646
647 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
648                                        CORBA::Double u, CORBA::Double v)
649   throw (SALOME::SALOME_Exception)
650 {
651   Unexpect aCatch(SALOME_SalomeException);
652
653   SMESHDS_Mesh * mesh = GetMeshDS();
654   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
655   if ( !node )
656     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
657
658   if ( mesh->MaxShapeIndex() < FaceID )
659     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
660
661   TopoDS_Shape shape = mesh->IndexToShape( FaceID );
662   if ( shape.ShapeType() != TopAbs_FACE )
663     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
664
665   BRepAdaptor_Surface surf( TopoDS::Face( shape ));
666   bool isOut = ( u < surf.FirstUParameter() ||
667                  u > surf.LastUParameter()  ||
668                  v < surf.FirstVParameter() ||
669                  v > surf.LastVParameter() );
670
671   if ( isOut ) {
672 #ifdef _DEBUG_
673     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
674            << " u( " <<  surf.FirstUParameter() 
675            << "," <<  surf.LastUParameter()  
676            << ") v( " <<  surf.FirstVParameter() 
677            << "," <<  surf.LastVParameter() << ")" );
678 #endif    
679     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
680   }
681
682   mesh->SetNodeOnFace( node, FaceID, u, v );
683 }
684
685 //=============================================================================
686 /*!
687  * \brief Bind a node to a solid
688  * \param NodeID - node ID
689  * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
690  * \retval boolean - false if NodeID or SolidID is invalid
691  */
692 //=============================================================================
693
694 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
695   throw (SALOME::SALOME_Exception)
696 {
697   Unexpect aCatch(SALOME_SalomeException);
698
699   SMESHDS_Mesh * mesh = GetMeshDS();
700   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
701   if ( !node )
702     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
703
704   if ( mesh->MaxShapeIndex() < SolidID )
705     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
706
707   TopoDS_Shape shape = mesh->IndexToShape( SolidID );
708   if ( shape.ShapeType() != TopAbs_SOLID &&
709        shape.ShapeType() != TopAbs_SHELL)
710     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
711
712   mesh->SetNodeInVolume( node, SolidID );
713 }
714
715 //=============================================================================
716 /*!
717  * \brief Bind an element to a shape
718  * \param ElementID - element ID
719  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
720  * \retval boolean - false if ElementID or ShapeID is invalid
721  */
722 //=============================================================================
723
724 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
725                                                CORBA::Long ShapeID)
726   throw (SALOME::SALOME_Exception)
727 {
728   Unexpect aCatch(SALOME_SalomeException);
729
730   SMESHDS_Mesh * mesh = GetMeshDS();
731   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
732   if ( !elem )
733     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
734
735   if ( mesh->MaxShapeIndex() < ShapeID )
736     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
737
738   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
739   if ( shape.ShapeType() != TopAbs_EDGE &&
740        shape.ShapeType() != TopAbs_FACE &&
741        shape.ShapeType() != TopAbs_SOLID &&
742        shape.ShapeType() != TopAbs_SHELL )
743     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
744
745   mesh->SetMeshElementOnShape( elem, ShapeID );
746 }
747
748
749 //=============================================================================
750 /*!
751  *
752  */
753 //=============================================================================
754
755 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
756                                             CORBA::Double x,
757                                             CORBA::Double y,
758                                             CORBA::Double z)
759 {
760   initData();
761
762   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
763   if ( !node )
764     return false;
765
766   GetMeshDS()->MoveNode(node, x, y, z);
767
768   // Update Python script
769   TPythonDump() << "isDone = " << this << ".MoveNode( "
770                 << NodeID << ", " << x << ", " << y << ", " << z << " )";
771
772   return true;
773 }
774
775 //=============================================================================
776 /*!
777  *
778  */
779 //=============================================================================
780
781 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
782                                                CORBA::Long NodeID2)
783 {
784   initData();
785
786   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
787   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
788   if ( !n1 || !n2 )
789     return false;
790
791   // Update Python script
792   TPythonDump() << "isDone = " << this << ".InverseDiag( "
793                 << NodeID1 << ", " << NodeID2 << " )";
794
795   ::SMESH_MeshEditor aMeshEditor( myMesh );
796   return aMeshEditor.InverseDiag ( n1, n2 );
797 }
798
799 //=============================================================================
800 /*!
801  *
802  */
803 //=============================================================================
804
805 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
806                                               CORBA::Long NodeID2)
807 {
808   initData();
809
810   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
811   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
812   if ( !n1 || !n2 )
813     return false;
814
815   // Update Python script
816   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
817                 << NodeID1 << ", " << NodeID2 <<  " )";
818
819   ::SMESH_MeshEditor aMeshEditor( myMesh );
820
821   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
822
823   storeResult(aMeshEditor);
824
825   return stat;
826 }
827
828 //=============================================================================
829 /*!
830  *
831  */
832 //=============================================================================
833
834 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
835 {
836   initData();
837
838   ::SMESH_MeshEditor anEditor( myMesh );
839   for (int i = 0; i < IDsOfElements.length(); i++)
840   {
841     CORBA::Long index = IDsOfElements[i];
842     const SMDS_MeshElement * elem = GetMeshDS()->FindElement(index);
843     if ( elem )
844       anEditor.Reorient( elem );
845   }
846   // Update Python script
847   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
848
849   return true;
850 }
851
852
853 //=============================================================================
854 /*!
855  *
856  */
857 //=============================================================================
858
859 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
860 {
861   initData();
862
863   SMESH::long_array_var anElementsId = theObject->GetIDs();
864   CORBA::Boolean isDone = Reorient(anElementsId);
865
866   // Clear python line, created by Reorient()
867   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
868   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
869
870   // Update Python script
871   TPythonDump() << "isDone = " << this << ".ReorientObject( " << theObject << " )";
872
873   return isDone;
874 }
875
876 namespace
877 {
878   //================================================================================
879   /*!
880    * \brief function for conversion long_array to TIDSortedElemSet
881     * \param IDs - array of IDs
882     * \param aMesh - mesh
883     * \param aMap - collection to fill
884     * \param aType - element type
885    */
886   //================================================================================
887
888   void arrayToSet(const SMESH::long_array & IDs,
889                   const SMESHDS_Mesh*       aMesh,
890                   TIDSortedElemSet&         aMap,
891                   const SMDSAbs_ElementType aType = SMDSAbs_All )
892   { 
893     for (int i=0; i<IDs.length(); i++) {
894       CORBA::Long ind = IDs[i];
895       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
896       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
897         aMap.insert( elem );
898     }
899   }
900 }
901
902 //=============================================================================
903 /*!
904  *
905  */
906 //=============================================================================
907 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
908                                               SMESH::NumericalFunctor_ptr Criterion,
909                                               CORBA::Double               MaxAngle)
910 {
911   initData();
912
913   SMESHDS_Mesh* aMesh = GetMeshDS();
914   TIDSortedElemSet faces;
915   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
916
917   SMESH::NumericalFunctor_i* aNumericalFunctor =
918     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
919   SMESH::Controls::NumericalFunctorPtr aCrit;
920   if ( !aNumericalFunctor )
921     aCrit.reset( new SMESH::Controls::AspectRatio() );
922   else
923     aCrit = aNumericalFunctor->GetNumericalFunctor();
924
925   // Update Python script
926   TPythonDump() << "isDone = " << this << ".TriToQuad( "
927                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
928 #ifdef _DEBUG_
929   TPythonDump() << "print 'TriToQuad: ', isDone";
930 #endif
931
932   ::SMESH_MeshEditor anEditor( myMesh );
933
934   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
935
936   storeResult(anEditor);
937
938   return stat;
939 }
940
941
942 //=============================================================================
943 /*!
944  *
945  */
946 //=============================================================================
947 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
948                                                     SMESH::NumericalFunctor_ptr Criterion,
949                                                     CORBA::Double               MaxAngle)
950 {
951   initData();
952
953   SMESH::long_array_var anElementsId = theObject->GetIDs();
954   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
955
956   // Clear python line(s), created by TriToQuad()
957   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
958   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
959 #ifdef _DEBUG_
960   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
961 #endif
962
963   SMESH::NumericalFunctor_i* aNumericalFunctor =
964     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
965
966   // Update Python script
967   TPythonDump() << "isDone = " << this << ".TriToQuadObject("
968                 << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
969 #ifdef _DEBUG_
970   TPythonDump() << "print 'TriToQuadObject: ', isDone";
971 #endif
972
973   return isDone;
974 }
975
976
977 //=============================================================================
978 /*!
979  *
980  */
981 //=============================================================================
982 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
983                                               SMESH::NumericalFunctor_ptr Criterion)
984 {
985   initData();
986
987   SMESHDS_Mesh* aMesh = GetMeshDS();
988   TIDSortedElemSet faces;
989   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
990
991   SMESH::NumericalFunctor_i* aNumericalFunctor =
992     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
993   SMESH::Controls::NumericalFunctorPtr aCrit;
994   if ( !aNumericalFunctor )
995     aCrit.reset( new SMESH::Controls::AspectRatio() );
996   else
997     aCrit = aNumericalFunctor->GetNumericalFunctor();
998
999
1000   // Update Python script
1001   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1002 #ifdef _DEBUG_
1003   TPythonDump() << "print 'QuadToTri: ', isDone";
1004 #endif
1005
1006   ::SMESH_MeshEditor anEditor( myMesh );
1007   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
1008
1009   storeResult(anEditor);
1010
1011   return stat;
1012 }
1013
1014
1015 //=============================================================================
1016 /*!
1017  *
1018  */
1019 //=============================================================================
1020 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1021                                                     SMESH::NumericalFunctor_ptr Criterion)
1022 {
1023   initData();
1024
1025   SMESH::long_array_var anElementsId = theObject->GetIDs();
1026   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1027
1028   // Clear python line(s), created by QuadToTri()
1029   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1030   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1031 #ifdef _DEBUG_
1032   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1033 #endif
1034
1035   SMESH::NumericalFunctor_i* aNumericalFunctor =
1036     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1037
1038   // Update Python script
1039   TPythonDump() << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1040 #ifdef _DEBUG_
1041   TPythonDump() << "print 'QuadToTriObject: ', isDone";
1042 #endif
1043
1044   return isDone;
1045 }
1046
1047
1048 //=============================================================================
1049 /*!
1050  *
1051  */
1052 //=============================================================================
1053 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1054                                               CORBA::Boolean            Diag13)
1055 {
1056   initData();
1057
1058   SMESHDS_Mesh* aMesh = GetMeshDS();
1059   TIDSortedElemSet faces;
1060   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1061
1062   // Update Python script
1063   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1064                 << IDsOfElements << ", " << Diag13 << " )";
1065 #ifdef _DEBUG_
1066   TPythonDump() << "print 'SplitQuad: ', isDone";
1067 #endif
1068
1069   ::SMESH_MeshEditor anEditor( myMesh );
1070   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
1071
1072   storeResult(anEditor);
1073
1074   return stat;
1075 }
1076
1077
1078 //=============================================================================
1079 /*!
1080  *
1081  */
1082 //=============================================================================
1083 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1084                                                     CORBA::Boolean            Diag13)
1085 {
1086   initData();
1087
1088   SMESH::long_array_var anElementsId = theObject->GetIDs();
1089   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1090
1091   // Clear python line(s), created by SplitQuad()
1092   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1093   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1094 #ifdef _DEBUG_
1095   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1096 #endif
1097
1098   // Update Python script
1099   TPythonDump() << "isDone = " << this << ".SplitQuadObject( "
1100                 << theObject << ", " << Diag13 << " )";
1101 #ifdef _DEBUG_
1102   TPythonDump() << "print 'SplitQuadObject: ', isDone";
1103 #endif
1104
1105   return isDone;
1106 }
1107
1108
1109 //=============================================================================
1110 /*!
1111  *  BestSplit
1112  */
1113 //=============================================================================
1114 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
1115                                            SMESH::NumericalFunctor_ptr Criterion)
1116 {
1117   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
1118   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1119   {
1120     SMESH::NumericalFunctor_i* aNumericalFunctor =
1121       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1122     SMESH::Controls::NumericalFunctorPtr aCrit;
1123     if (aNumericalFunctor)
1124       aCrit = aNumericalFunctor->GetNumericalFunctor();
1125     else
1126       aCrit.reset(new SMESH::Controls::AspectRatio());
1127
1128     ::SMESH_MeshEditor anEditor (myMesh);
1129     return anEditor.BestSplit(quad, aCrit);
1130   }
1131   return -1;
1132 }
1133
1134
1135 //=======================================================================
1136 //function : Smooth
1137 //purpose  :
1138 //=======================================================================
1139
1140 CORBA::Boolean
1141   SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
1142                              const SMESH::long_array &              IDsOfFixedNodes,
1143                              CORBA::Long                            MaxNbOfIterations,
1144                              CORBA::Double                          MaxAspectRatio,
1145                              SMESH::SMESH_MeshEditor::Smooth_Method Method)
1146 {
1147   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1148                 MaxAspectRatio, Method, false );
1149 }
1150
1151
1152 //=======================================================================
1153 //function : SmoothParametric
1154 //purpose  :
1155 //=======================================================================
1156
1157 CORBA::Boolean
1158   SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
1159                                        const SMESH::long_array &              IDsOfFixedNodes,
1160                                        CORBA::Long                            MaxNbOfIterations,
1161                                        CORBA::Double                          MaxAspectRatio,
1162                                        SMESH::SMESH_MeshEditor::Smooth_Method Method)
1163 {
1164   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1165                 MaxAspectRatio, Method, true );
1166 }
1167
1168
1169 //=======================================================================
1170 //function : SmoothObject
1171 //purpose  :
1172 //=======================================================================
1173
1174 CORBA::Boolean
1175   SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1176                                    const SMESH::long_array &              IDsOfFixedNodes,
1177                                    CORBA::Long                            MaxNbOfIterations,
1178                                    CORBA::Double                          MaxAspectRatio,
1179                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
1180 {
1181   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1182                        MaxAspectRatio, Method, false);
1183 }
1184
1185
1186 //=======================================================================
1187 //function : SmoothParametricObject
1188 //purpose  :
1189 //=======================================================================
1190
1191 CORBA::Boolean
1192   SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
1193                                    const SMESH::long_array &              IDsOfFixedNodes,
1194                                    CORBA::Long                            MaxNbOfIterations,
1195                                    CORBA::Double                          MaxAspectRatio,
1196                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
1197 {
1198   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1199                        MaxAspectRatio, Method, true);
1200 }
1201
1202
1203 //=============================================================================
1204 /*!
1205  *
1206  */
1207 //=============================================================================
1208
1209 CORBA::Boolean
1210   SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1211                              const SMESH::long_array &              IDsOfFixedNodes,
1212                              CORBA::Long                            MaxNbOfIterations,
1213                              CORBA::Double                          MaxAspectRatio,
1214                              SMESH::SMESH_MeshEditor::Smooth_Method Method,
1215                              bool                                   IsParametric)
1216 {
1217   initData();
1218
1219   SMESHDS_Mesh* aMesh = GetMeshDS();
1220
1221   TIDSortedElemSet elements;
1222   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1223
1224   set<const SMDS_MeshNode*> fixedNodes;
1225   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1226     CORBA::Long index = IDsOfFixedNodes[i];
1227     const SMDS_MeshNode * node = aMesh->FindNode(index);
1228     if ( node )
1229       fixedNodes.insert( node );
1230   }
1231   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1232   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1233     method = ::SMESH_MeshEditor::CENTROIDAL;
1234
1235   ::SMESH_MeshEditor anEditor( myMesh );
1236   anEditor.Smooth(elements, fixedNodes, method,
1237                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1238
1239   storeResult(anEditor);
1240
1241   // Update Python script
1242   TPythonDump() << "isDone = " << this << "."
1243                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1244                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1245                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1246                 << "SMESH.SMESH_MeshEditor."
1247                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1248                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1249 #ifdef _DEBUG_
1250   TPythonDump() << "print 'Smooth: ', isDone";
1251 #endif
1252
1253   return true;
1254 }
1255
1256
1257 //=============================================================================
1258 /*!
1259  *
1260  */
1261 //=============================================================================
1262
1263 CORBA::Boolean
1264 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1265                                  const SMESH::long_array &              IDsOfFixedNodes,
1266                                  CORBA::Long                            MaxNbOfIterations,
1267                                  CORBA::Double                          MaxAspectRatio,
1268                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1269                                  bool                                   IsParametric)
1270 {
1271   initData();
1272
1273   SMESH::long_array_var anElementsId = theObject->GetIDs();
1274   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1275                                   MaxAspectRatio, Method, IsParametric);
1276
1277   // Clear python line(s), created by Smooth()
1278   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1279   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1280 #ifdef _DEBUG_
1281   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1282 #endif
1283
1284   // Update Python script
1285   TPythonDump() << "isDone = " << this << "."
1286                 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1287                 << theObject << ", " << IDsOfFixedNodes << ", "
1288                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1289                 << "SMESH.SMESH_MeshEditor."
1290                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1291                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1292 #ifdef _DEBUG_
1293   TPythonDump() << "print 'SmoothObject: ', isDone";
1294 #endif
1295
1296   return isDone;
1297 }
1298
1299
1300 //=============================================================================
1301 /*!
1302  *
1303  */
1304 //=============================================================================
1305
1306 void SMESH_MeshEditor_i::RenumberNodes()
1307 {
1308   // Update Python script
1309   TPythonDump() << this << ".RenumberNodes()";
1310
1311   GetMeshDS()->Renumber( true );
1312 }
1313
1314
1315 //=============================================================================
1316 /*!
1317  *
1318  */
1319 //=============================================================================
1320
1321 void SMESH_MeshEditor_i::RenumberElements()
1322 {
1323   // Update Python script
1324   TPythonDump() << this << ".RenumberElements()";
1325
1326   GetMeshDS()->Renumber( false );
1327 }
1328
1329 //=======================================================================
1330   /*!
1331    * \brief Return groups by their IDs
1332    */
1333 //=======================================================================
1334
1335 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
1336 {
1337   if ( !groupIDs )
1338     return 0;
1339   myMesh_i->CreateGroupServants();
1340   return myMesh_i->GetGroups( *groupIDs );
1341 }
1342
1343 //=======================================================================
1344 //function : rotationSweep
1345 //purpose  : 
1346 //=======================================================================
1347
1348 SMESH::ListOfGroups*
1349 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
1350                                   const SMESH::AxisStruct & theAxis,
1351                                   CORBA::Double             theAngleInRadians,
1352                                   CORBA::Long               theNbOfSteps,
1353                                   CORBA::Double             theTolerance,
1354                                   const bool                theMakeGroups,
1355                                   const SMDSAbs_ElementType theElementType)
1356 {
1357   initData();
1358
1359   TIDSortedElemSet inElements, copyElements;
1360   arrayToSet(theIDsOfElements, GetMeshDS(), inElements, theElementType);
1361
1362   TIDSortedElemSet* workElements = & inElements;
1363   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1364   SMESH_Mesh*       mesh = 0;
1365   bool              makeWalls=true;
1366   if ( myPreviewMode )
1367   {
1368     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1369     tmpMesh.Copy( inElements, copyElements, select, avoid );
1370     mesh = &tmpMesh;
1371     workElements = & copyElements;
1372     //makeWalls = false;
1373   }
1374   else
1375   {
1376     mesh = myMesh;
1377   }
1378
1379   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1380               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1381
1382   ::SMESH_MeshEditor anEditor( mesh );
1383   ::SMESH_MeshEditor::PGroupIDs groupIds =
1384     anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1385                             theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
1386   storeResult(anEditor);
1387
1388   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1389 }
1390
1391 //=======================================================================
1392 //function : RotationSweep
1393 //purpose  :
1394 //=======================================================================
1395
1396 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1397                                        const SMESH::AxisStruct & theAxis,
1398                                        CORBA::Double             theAngleInRadians,
1399                                        CORBA::Long               theNbOfSteps,
1400                                        CORBA::Double             theTolerance)
1401 {
1402   if ( !myPreviewMode ) {
1403     TPythonDump() << this << ".RotationSweep( "
1404                   << theIDsOfElements << ", "
1405                   << theAxis << ", "
1406                   << theAngleInRadians << ", "
1407                   << theNbOfSteps << ", "
1408                   << theTolerance << " )";
1409   }
1410   rotationSweep(theIDsOfElements,
1411                 theAxis,
1412                 theAngleInRadians,
1413                 theNbOfSteps,
1414                 theTolerance,
1415                 false);
1416 }
1417
1418 //=======================================================================
1419 //function : RotationSweepMakeGroups
1420 //purpose  : 
1421 //=======================================================================
1422
1423 SMESH::ListOfGroups*
1424 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1425                                             const SMESH::AxisStruct& theAxis,
1426                                             CORBA::Double            theAngleInRadians,
1427                                             CORBA::Long              theNbOfSteps,
1428                                             CORBA::Double            theTolerance)
1429 {
1430   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
1431                                                theAxis,
1432                                                theAngleInRadians,
1433                                                theNbOfSteps,
1434                                                theTolerance,
1435                                                true);
1436   if ( !myPreviewMode ) {
1437     TPythonDump aPythonDump;
1438     DumpGroupsList(aPythonDump,aGroups);
1439     aPythonDump<< this << ".RotationSweepMakeGroups( "
1440                << theIDsOfElements << ", "
1441                << theAxis << ", "
1442                << theAngleInRadians << ", "
1443                << theNbOfSteps << ", "
1444                << theTolerance << " )";
1445   }
1446   return aGroups;
1447 }
1448
1449 //=======================================================================
1450 //function : RotationSweepObject
1451 //purpose  :
1452 //=======================================================================
1453
1454 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1455                                              const SMESH::AxisStruct & theAxis,
1456                                              CORBA::Double             theAngleInRadians,
1457                                              CORBA::Long               theNbOfSteps,
1458                                              CORBA::Double             theTolerance)
1459 {
1460   if ( !myPreviewMode ) {
1461     TPythonDump() << this << ".RotationSweepObject( "
1462                   << theObject << ", "
1463                   << theAxis << ", "
1464                   << theAngleInRadians << ", "
1465                   << theNbOfSteps << ", "
1466                   << theTolerance << " )";
1467   }
1468   SMESH::long_array_var anElementsId = theObject->GetIDs();
1469   rotationSweep(anElementsId,
1470                 theAxis,
1471                 theAngleInRadians,
1472                 theNbOfSteps,
1473                 theTolerance,
1474                 false);
1475 }
1476
1477 //=======================================================================
1478 //function : RotationSweepObject1D
1479 //purpose  :
1480 //=======================================================================
1481
1482 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1483                                                const SMESH::AxisStruct & theAxis,
1484                                                CORBA::Double             theAngleInRadians,
1485                                                CORBA::Long               theNbOfSteps,
1486                                                CORBA::Double             theTolerance)
1487 {
1488   if ( !myPreviewMode ) {
1489     TPythonDump() << this << ".RotationSweepObject1D( "
1490                   << theObject << ", "
1491                   << theAxis << ", "
1492                   << theAngleInRadians << ", "
1493                   << theNbOfSteps << ", "
1494                   << theTolerance << " )";
1495   }
1496   SMESH::long_array_var anElementsId = theObject->GetIDs();
1497   rotationSweep(anElementsId,
1498                 theAxis,
1499                 theAngleInRadians,
1500                 theNbOfSteps,
1501                 theTolerance,
1502                 false,
1503                 SMDSAbs_Edge);
1504 }
1505
1506 //=======================================================================
1507 //function : RotationSweepObject2D
1508 //purpose  :
1509 //=======================================================================
1510
1511 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1512                                                const SMESH::AxisStruct & theAxis,
1513                                                CORBA::Double             theAngleInRadians,
1514                                                CORBA::Long               theNbOfSteps,
1515                                                CORBA::Double             theTolerance)
1516 {
1517   if ( !myPreviewMode ) {
1518     TPythonDump() << this << ".RotationSweepObject2D( "
1519                   << theObject << ", "
1520                   << theAxis << ", "
1521                   << theAngleInRadians << ", "
1522                   << theNbOfSteps << ", "
1523                   << theTolerance << " )";
1524   }
1525   SMESH::long_array_var anElementsId = theObject->GetIDs();
1526   rotationSweep(anElementsId,
1527                 theAxis,
1528                 theAngleInRadians,
1529                 theNbOfSteps,
1530                 theTolerance,
1531                 false,
1532                 SMDSAbs_Face);
1533 }
1534
1535 //=======================================================================
1536 //function : RotationSweepObjectMakeGroups
1537 //purpose  : 
1538 //=======================================================================
1539
1540 SMESH::ListOfGroups*
1541 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1542                                                   const SMESH::AxisStruct&  theAxis,
1543                                                   CORBA::Double             theAngleInRadians,
1544                                                   CORBA::Long               theNbOfSteps,
1545                                                   CORBA::Double             theTolerance)
1546 {
1547   SMESH::long_array_var anElementsId = theObject->GetIDs();
1548   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1549                                                theAxis,
1550                                                theAngleInRadians,
1551                                                theNbOfSteps,
1552                                                theTolerance,
1553                                                true);
1554   if ( !myPreviewMode ) {
1555     TPythonDump aPythonDump;
1556     DumpGroupsList(aPythonDump,aGroups);
1557     aPythonDump<< this << ".RotationSweepObjectMakeGroups( "
1558                << theObject << ", "
1559                << theAxis << ", "
1560                << theAngleInRadians << ", "
1561                << theNbOfSteps << ", "
1562                << theTolerance << " )";
1563   }
1564   return aGroups;
1565 }
1566
1567 //=======================================================================
1568 //function : RotationSweepObject1DMakeGroups
1569 //purpose  : 
1570 //=======================================================================
1571
1572 SMESH::ListOfGroups*
1573 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1574                                                     const SMESH::AxisStruct&  theAxis,
1575                                                     CORBA::Double             theAngleInRadians,
1576                                                     CORBA::Long               theNbOfSteps,
1577                                                     CORBA::Double             theTolerance)
1578 {
1579   SMESH::long_array_var anElementsId = theObject->GetIDs();
1580   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1581                                                theAxis,
1582                                                theAngleInRadians,
1583                                                theNbOfSteps,
1584                                                theTolerance,
1585                                                true,
1586                                                SMDSAbs_Edge);
1587   if ( !myPreviewMode ) {
1588     TPythonDump aPythonDump;
1589     DumpGroupsList(aPythonDump,aGroups);
1590     aPythonDump<< this << ".RotationSweepObject1DMakeGroups( "
1591                << theObject << ", "
1592                << theAxis << ", "
1593                << theAngleInRadians << ", "
1594                << theNbOfSteps << ", "
1595                << theTolerance << " )";
1596   }
1597   return aGroups;
1598 }
1599
1600 //=======================================================================
1601 //function : RotationSweepObject2DMakeGroups
1602 //purpose  : 
1603 //=======================================================================
1604
1605 SMESH::ListOfGroups*
1606 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1607                                                     const SMESH::AxisStruct&  theAxis,
1608                                                     CORBA::Double             theAngleInRadians,
1609                                                     CORBA::Long               theNbOfSteps,
1610                                                     CORBA::Double             theTolerance)
1611 {
1612   SMESH::long_array_var anElementsId = theObject->GetIDs();
1613   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1614                                                theAxis,
1615                                                theAngleInRadians,
1616                                                theNbOfSteps,
1617                                                theTolerance,
1618                                                true,
1619                                                SMDSAbs_Face);
1620   if ( !myPreviewMode ) {
1621     TPythonDump aPythonDump;
1622     DumpGroupsList(aPythonDump,aGroups);
1623     aPythonDump<< this << ".RotationSweepObject2DMakeGroups( "
1624                << theObject << ", "
1625                << theAxis << ", "
1626                << theAngleInRadians << ", "
1627                << theNbOfSteps << ", "
1628                << theTolerance << " )";
1629   }
1630   return aGroups;
1631 }
1632
1633
1634 //=======================================================================
1635 //function : extrusionSweep
1636 //purpose  : 
1637 //=======================================================================
1638
1639 SMESH::ListOfGroups*
1640 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
1641                                    const SMESH::DirStruct &  theStepVector,
1642                                    CORBA::Long               theNbOfSteps,
1643                                    const bool                theMakeGroups,
1644                                    const SMDSAbs_ElementType theElementType)
1645 {
1646   initData();
1647
1648   try {   
1649 #ifdef NO_CAS_CATCH
1650     OCC_CATCH_SIGNALS;
1651 #endif
1652     TIDSortedElemSet elements;
1653     arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
1654
1655     const SMESH::PointStruct * P = &theStepVector.PS;
1656     gp_Vec stepVec( P->x, P->y, P->z );
1657
1658     TElemOfElemListMap aHystory;
1659     ::SMESH_MeshEditor anEditor( myMesh );
1660     ::SMESH_MeshEditor::PGroupIDs groupIds =
1661         anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
1662
1663     storeResult(anEditor);
1664
1665     return theMakeGroups ? getGroups(groupIds.get()) : 0;
1666
1667   } catch(Standard_Failure) {
1668     Handle(Standard_Failure) aFail = Standard_Failure::Caught();          
1669     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1670   }
1671   return 0;
1672 }
1673
1674 //=======================================================================
1675 //function : ExtrusionSweep
1676 //purpose  :
1677 //=======================================================================
1678
1679 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1680                                         const SMESH::DirStruct &  theStepVector,
1681                                         CORBA::Long               theNbOfSteps)
1682 {
1683   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
1684   if ( !myPreviewMode ) {
1685     TPythonDump() << this << ".ExtrusionSweep( "
1686                   << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1687   }
1688 }
1689
1690
1691 //=======================================================================
1692 //function : ExtrusionSweepObject
1693 //purpose  :
1694 //=======================================================================
1695
1696 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1697                                               const SMESH::DirStruct &  theStepVector,
1698                                               CORBA::Long               theNbOfSteps)
1699 {
1700   SMESH::long_array_var anElementsId = theObject->GetIDs();
1701   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
1702   if ( !myPreviewMode ) {
1703     TPythonDump() << this << ".ExtrusionSweepObject( "
1704                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1705   }
1706 }
1707
1708 //=======================================================================
1709 //function : ExtrusionSweepObject1D
1710 //purpose  :
1711 //=======================================================================
1712
1713 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1714                                                 const SMESH::DirStruct &  theStepVector,
1715                                                 CORBA::Long               theNbOfSteps)
1716 {
1717   SMESH::long_array_var anElementsId = theObject->GetIDs();
1718   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
1719   if ( !myPreviewMode ) {
1720     TPythonDump() << this << ".ExtrusionSweepObject1D( "
1721                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1722   }
1723 }
1724
1725 //=======================================================================
1726 //function : ExtrusionSweepObject2D
1727 //purpose  :
1728 //=======================================================================
1729
1730 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1731                                                 const SMESH::DirStruct &  theStepVector,
1732                                                 CORBA::Long               theNbOfSteps)
1733 {
1734   SMESH::long_array_var anElementsId = theObject->GetIDs();
1735   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
1736   if ( !myPreviewMode ) {
1737     TPythonDump() << this << ".ExtrusionSweepObject2D( "
1738                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1739   }
1740 }
1741
1742 //=======================================================================
1743 //function : ExtrusionSweepMakeGroups
1744 //purpose  : 
1745 //=======================================================================
1746
1747 SMESH::ListOfGroups*
1748 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1749                                              const SMESH::DirStruct&  theStepVector,
1750                                              CORBA::Long              theNbOfSteps)
1751 {
1752   SMESH::ListOfGroups* aGroups = extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, true );
1753     
1754   if ( !myPreviewMode ) {
1755     TPythonDump aPythonDump;
1756     DumpGroupsList(aPythonDump,aGroups);
1757     aPythonDump  << this << ".ExtrusionSweepMakeGroups( "
1758                  << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1759   }
1760   return aGroups;
1761 }
1762 //=======================================================================
1763 //function : ExtrusionSweepObjectMakeGroups
1764 //purpose  : 
1765 //=======================================================================
1766
1767 SMESH::ListOfGroups*
1768 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1769                                                    const SMESH::DirStruct&   theStepVector,
1770                                                    CORBA::Long               theNbOfSteps)
1771 {
1772   SMESH::long_array_var anElementsId = theObject->GetIDs();
1773   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true );
1774   
1775   if ( !myPreviewMode ) {
1776     TPythonDump aPythonDump;
1777     DumpGroupsList(aPythonDump,aGroups);
1778     aPythonDump<< this << ".ExtrusionSweepObjectMakeGroups( "
1779                << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1780   }
1781   return aGroups;
1782 }
1783
1784 //=======================================================================
1785 //function : ExtrusionSweepObject1DMakeGroups
1786 //purpose  : 
1787 //=======================================================================
1788
1789 SMESH::ListOfGroups*
1790 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1791                                                      const SMESH::DirStruct&   theStepVector,
1792                                                      CORBA::Long               theNbOfSteps)
1793 {
1794   SMESH::long_array_var anElementsId = theObject->GetIDs();
1795   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Edge );
1796   if ( !myPreviewMode ) {
1797     TPythonDump aPythonDump;
1798     DumpGroupsList(aPythonDump,aGroups);
1799     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( "
1800                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1801   }
1802   return aGroups;
1803 }
1804
1805 //=======================================================================
1806 //function : ExtrusionSweepObject2DMakeGroups
1807 //purpose  : 
1808 //=======================================================================
1809
1810 SMESH::ListOfGroups*
1811 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1812                                                      const SMESH::DirStruct&   theStepVector,
1813                                                      CORBA::Long               theNbOfSteps)
1814 {
1815   SMESH::long_array_var anElementsId = theObject->GetIDs();
1816   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Face );
1817   if ( !myPreviewMode ) {
1818     TPythonDump aPythonDump;
1819     DumpGroupsList(aPythonDump,aGroups);
1820     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( "
1821                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1822   }
1823   return aGroups;
1824 }
1825
1826
1827 //=======================================================================
1828 //function : advancedExtrusion
1829 //purpose  : 
1830 //=======================================================================
1831
1832 SMESH::ListOfGroups*
1833 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
1834                                       const SMESH::DirStruct &  theStepVector,
1835                                       CORBA::Long               theNbOfSteps,
1836                                       CORBA::Long               theExtrFlags,
1837                                       CORBA::Double             theSewTolerance,
1838                                       const bool                theMakeGroups)
1839 {
1840   initData();
1841
1842   TIDSortedElemSet elements;
1843   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
1844
1845   const SMESH::PointStruct * P = &theStepVector.PS;
1846   gp_Vec stepVec( P->x, P->y, P->z );
1847
1848   ::SMESH_MeshEditor anEditor( myMesh );
1849   TElemOfElemListMap aHystory;
1850   ::SMESH_MeshEditor::PGroupIDs groupIds =
1851       anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
1852                                theMakeGroups, theExtrFlags, theSewTolerance);
1853   storeResult(anEditor);
1854
1855   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1856 }
1857
1858 //=======================================================================
1859 //function : AdvancedExtrusion
1860 //purpose  :
1861 //=======================================================================
1862
1863 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
1864                                            const SMESH::DirStruct &  theStepVector,
1865                                            CORBA::Long               theNbOfSteps,
1866                                            CORBA::Long               theExtrFlags,
1867                                            CORBA::Double             theSewTolerance)
1868 {
1869   if ( !myPreviewMode ) {
1870     TPythonDump() << "stepVector = " << theStepVector;
1871     TPythonDump() << this << ".AdvancedExtrusion("
1872                   << theIDsOfElements
1873                   << ", stepVector, "
1874                   << theNbOfSteps << ","
1875                   << theExtrFlags << ", "
1876                   << theSewTolerance <<  " )";
1877   }
1878   advancedExtrusion( theIDsOfElements,
1879                      theStepVector,
1880                      theNbOfSteps,
1881                      theExtrFlags,
1882                      theSewTolerance,
1883                      false);
1884 }
1885
1886 //=======================================================================
1887 //function : AdvancedExtrusionMakeGroups
1888 //purpose  : 
1889 //=======================================================================
1890
1891 SMESH::ListOfGroups*
1892 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
1893                                                 const SMESH::DirStruct&  theStepVector,
1894                                                 CORBA::Long              theNbOfSteps,
1895                                                 CORBA::Long              theExtrFlags,
1896                                                 CORBA::Double            theSewTolerance)
1897 {
1898   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
1899                                                     theStepVector,
1900                                                     theNbOfSteps,
1901                                                     theExtrFlags,
1902                                                     theSewTolerance,
1903                                                     true);
1904   
1905   if ( !myPreviewMode ) {
1906     TPythonDump() << "stepVector = " << theStepVector;
1907     TPythonDump aPythonDump;
1908     DumpGroupsList(aPythonDump,aGroups);
1909     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
1910                 << theIDsOfElements
1911                 << ", stepVector, "
1912                 << theNbOfSteps << ","
1913                 << theExtrFlags << ", "
1914                 << theSewTolerance <<  " )";
1915   }
1916   return aGroups;
1917 }
1918
1919
1920 //================================================================================
1921 /*!
1922  * \brief Convert extrusion error to IDL enum
1923  */
1924 //================================================================================
1925
1926 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
1927
1928 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
1929 {
1930   switch ( e ) {
1931   RETCASE( EXTR_OK );
1932   RETCASE( EXTR_NO_ELEMENTS );
1933   RETCASE( EXTR_PATH_NOT_EDGE );
1934   RETCASE( EXTR_BAD_PATH_SHAPE );
1935   RETCASE( EXTR_BAD_STARTING_NODE );
1936   RETCASE( EXTR_BAD_ANGLES_NUMBER );
1937   RETCASE( EXTR_CANT_GET_TANGENT );
1938   }
1939   return SMESH::SMESH_MeshEditor::EXTR_OK;
1940 }
1941
1942
1943 //=======================================================================
1944 //function : extrusionAlongPath
1945 //purpose  : 
1946 //=======================================================================
1947
1948 SMESH::ListOfGroups*
1949 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
1950                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
1951                                        GEOM::GEOM_Object_ptr       thePathShape,
1952                                        CORBA::Long                 theNodeStart,
1953                                        CORBA::Boolean              theHasAngles,
1954                                        const SMESH::double_array & theAngles,
1955                                        CORBA::Boolean              theHasRefPoint,
1956                                        const SMESH::PointStruct &  theRefPoint,
1957                                        const bool                  theMakeGroups,
1958                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
1959                                        const SMDSAbs_ElementType   theElementType)
1960 {
1961   initData();
1962
1963   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
1964     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1965     return 0;
1966   }
1967   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
1968
1969   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
1970   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
1971
1972   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
1973     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1974     return 0;
1975   }
1976
1977   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
1978   if ( !nodeStart ) {
1979     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
1980     return 0;
1981   }
1982
1983   TIDSortedElemSet elements;
1984   arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
1985
1986   list<double> angles;
1987   for (int i = 0; i < theAngles.length(); i++) {
1988     angles.push_back( theAngles[i] );
1989   }
1990
1991   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
1992
1993   int nbOldGroups = myMesh->NbGroup();
1994
1995   ::SMESH_MeshEditor anEditor( myMesh );
1996   ::SMESH_MeshEditor::Extrusion_Error error =
1997       anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
1998                                     theHasAngles, angles,
1999                                     theHasRefPoint, refPnt, theMakeGroups );
2000   storeResult(anEditor);
2001   theError = convExtrError( error );
2002
2003   if ( theMakeGroups ) {
2004     list<int> groupIDs = myMesh->GetGroupIds();
2005     list<int>::iterator newBegin = groupIDs.begin();
2006     std::advance( newBegin, nbOldGroups ); // skip old groups
2007     groupIDs.erase( groupIDs.begin(), newBegin );
2008     return getGroups( & groupIDs );
2009   }
2010   return 0;
2011 }
2012
2013 //=======================================================================
2014 //function : ExtrusionAlongPath
2015 //purpose  :
2016 //=======================================================================
2017
2018 SMESH::SMESH_MeshEditor::Extrusion_Error
2019   SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2020                                          SMESH::SMESH_Mesh_ptr       thePathMesh,
2021                                          GEOM::GEOM_Object_ptr       thePathShape,
2022                                          CORBA::Long                 theNodeStart,
2023                                          CORBA::Boolean              theHasAngles,
2024                                          const SMESH::double_array & theAngles,
2025                                          CORBA::Boolean              theHasRefPoint,
2026                                          const SMESH::PointStruct &  theRefPoint)
2027 {
2028   if ( !myPreviewMode ) {
2029     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
2030                   << theIDsOfElements << ", "
2031                   << thePathMesh      << ", "
2032                   << thePathShape     << ", "
2033                   << theNodeStart     << ", "
2034                   << theHasAngles     << ", "
2035                   << theAngles        << ", "
2036                   << theHasRefPoint   << ", "
2037                   << "SMESH.PointStruct( "
2038                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2039                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2040                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2041   }
2042   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2043   extrusionAlongPath( theIDsOfElements,
2044                       thePathMesh,
2045                       thePathShape,
2046                       theNodeStart,
2047                       theHasAngles,
2048                       theAngles,
2049                       theHasRefPoint,
2050                       theRefPoint,
2051                       false,
2052                       anError);
2053   return anError;
2054 }
2055
2056 //=======================================================================
2057 //function : ExtrusionAlongPathObject
2058 //purpose  :
2059 //=======================================================================
2060
2061 SMESH::SMESH_MeshEditor::Extrusion_Error
2062 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
2063                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
2064                                              GEOM::GEOM_Object_ptr       thePathShape,
2065                                              CORBA::Long                 theNodeStart,
2066                                              CORBA::Boolean              theHasAngles,
2067                                              const SMESH::double_array & theAngles,
2068                                              CORBA::Boolean              theHasRefPoint,
2069                                              const SMESH::PointStruct &  theRefPoint)
2070 {
2071   if ( !myPreviewMode ) {
2072     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
2073                   << theObject        << ", "
2074                   << thePathMesh      << ", "
2075                   << thePathShape     << ", "
2076                   << theNodeStart     << ", "
2077                   << theHasAngles     << ", "
2078                   << theAngles        << ", "
2079                   << theHasRefPoint   << ", "
2080                   << "SMESH.PointStruct( "
2081                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2082                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2083                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2084   }
2085   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2086   SMESH::long_array_var anElementsId = theObject->GetIDs();
2087   extrusionAlongPath( anElementsId,
2088                       thePathMesh,
2089                       thePathShape,
2090                       theNodeStart,
2091                       theHasAngles,
2092                       theAngles,
2093                       theHasRefPoint,
2094                       theRefPoint,
2095                       false,
2096                       anError);
2097   return anError;
2098 }
2099
2100 //=======================================================================
2101 //function : ExtrusionAlongPathObject1D
2102 //purpose  :
2103 //=======================================================================
2104
2105 SMESH::SMESH_MeshEditor::Extrusion_Error
2106 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
2107                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2108                                                GEOM::GEOM_Object_ptr       thePathShape,
2109                                                CORBA::Long                 theNodeStart,
2110                                                CORBA::Boolean              theHasAngles,
2111                                                const SMESH::double_array & theAngles,
2112                                                CORBA::Boolean              theHasRefPoint,
2113                                                const SMESH::PointStruct &  theRefPoint)
2114 {
2115   if ( !myPreviewMode ) {
2116     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
2117                   << theObject        << ", "
2118                   << thePathMesh      << ", "
2119                   << thePathShape     << ", "
2120                   << theNodeStart     << ", "
2121                   << theHasAngles     << ", "
2122                   << theAngles        << ", "
2123                   << theHasRefPoint   << ", "
2124                   << "SMESH.PointStruct( "
2125                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2126                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2127                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2128   }
2129   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2130   SMESH::long_array_var anElementsId = theObject->GetIDs();
2131   extrusionAlongPath( anElementsId,
2132                       thePathMesh,
2133                       thePathShape,
2134                       theNodeStart,
2135                       theHasAngles,
2136                       theAngles,
2137                       theHasRefPoint,
2138                       theRefPoint,
2139                       false,
2140                       anError,
2141                       SMDSAbs_Edge);
2142   return anError;
2143 }
2144
2145 //=======================================================================
2146 //function : ExtrusionAlongPathObject2D
2147 //purpose  :
2148 //=======================================================================
2149
2150 SMESH::SMESH_MeshEditor::Extrusion_Error
2151 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
2152                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2153                                                GEOM::GEOM_Object_ptr       thePathShape,
2154                                                CORBA::Long                 theNodeStart,
2155                                                CORBA::Boolean              theHasAngles,
2156                                                const SMESH::double_array & theAngles,
2157                                                CORBA::Boolean              theHasRefPoint,
2158                                                const SMESH::PointStruct &  theRefPoint)
2159 {
2160   if ( !myPreviewMode ) {
2161     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
2162                   << theObject        << ", "
2163                   << thePathMesh      << ", "
2164                   << thePathShape     << ", "
2165                   << theNodeStart     << ", "
2166                   << theHasAngles     << ", "
2167                   << theAngles        << ", "
2168                   << theHasRefPoint   << ", "
2169                   << "SMESH.PointStruct( "
2170                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2171                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2172                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2173   }
2174   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2175   SMESH::long_array_var anElementsId = theObject->GetIDs();
2176   extrusionAlongPath( anElementsId,
2177                       thePathMesh,
2178                       thePathShape,
2179                       theNodeStart,
2180                       theHasAngles,
2181                       theAngles,
2182                       theHasRefPoint,
2183                       theRefPoint,
2184                       false,
2185                       anError,
2186                       SMDSAbs_Face);
2187   return anError;
2188 }
2189
2190
2191 //=======================================================================
2192 //function : ExtrusionAlongPathMakeGroups
2193 //purpose  : 
2194 //=======================================================================
2195
2196 SMESH::ListOfGroups*
2197 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
2198                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
2199                                                  GEOM::GEOM_Object_ptr      thePathShape,
2200                                                  CORBA::Long                theNodeStart,
2201                                                  CORBA::Boolean             theHasAngles,
2202                                                  const SMESH::double_array& theAngles,
2203                                                  CORBA::Boolean             theHasRefPoint,
2204                                                  const SMESH::PointStruct&  theRefPoint,
2205                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2206 {
2207     SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
2208                                                          thePathMesh,
2209                                                          thePathShape,
2210                                                          theNodeStart,
2211                                                          theHasAngles,
2212                                                          theAngles,
2213                                                          theHasRefPoint,
2214                                                          theRefPoint,
2215                                                          true,
2216                                                          Error);
2217   if ( !myPreviewMode ) {
2218     bool isDumpGroups = aGroups && aGroups->length() > 0;
2219     TPythonDump aPythonDump;
2220     if(isDumpGroups) {
2221       aPythonDump << "("<<aGroups;
2222     }
2223     if(isDumpGroups)
2224       aPythonDump << ", error)";
2225     else
2226       aPythonDump <<"error";
2227     
2228     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
2229                << theIDsOfElements << ", "
2230                << thePathMesh      << ", "
2231                << thePathShape     << ", "
2232                << theNodeStart     << ", "
2233                << theHasAngles     << ", "
2234                << theAngles        << ", "
2235                << theHasRefPoint   << ", "
2236                << "SMESH.PointStruct( "
2237                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2238                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2239                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2240   }
2241   return aGroups;
2242 }
2243
2244 //=======================================================================
2245 //function : ExtrusionAlongPathObjectMakeGroups
2246 //purpose  : 
2247 //=======================================================================
2248
2249 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2250 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2251                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
2252                                    GEOM::GEOM_Object_ptr      thePathShape,
2253                                    CORBA::Long                theNodeStart,
2254                                    CORBA::Boolean             theHasAngles,
2255                                    const SMESH::double_array& theAngles,
2256                                    CORBA::Boolean             theHasRefPoint,
2257                                    const SMESH::PointStruct&  theRefPoint,
2258                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2259 {
2260   SMESH::long_array_var anElementsId = theObject->GetIDs();
2261   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2262                                                       thePathMesh,
2263                                                       thePathShape,
2264                                                       theNodeStart,
2265                                                       theHasAngles,
2266                                                       theAngles,
2267                                                       theHasRefPoint,
2268                                                       theRefPoint,
2269                                                       true,
2270                                                       Error);
2271   
2272   if ( !myPreviewMode ) {
2273     bool isDumpGroups = aGroups && aGroups->length() > 0;
2274     TPythonDump aPythonDump;
2275     if(isDumpGroups) {
2276       aPythonDump << "("<<aGroups;
2277     }
2278     if(isDumpGroups)
2279       aPythonDump << ", error)";
2280     else
2281       aPythonDump <<"error";
2282
2283     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
2284                 << theObject << ", "
2285                 << thePathMesh      << ", "
2286                 << thePathShape     << ", "
2287                 << theNodeStart     << ", "
2288                 << theHasAngles     << ", "
2289                 << theAngles        << ", "
2290                 << theHasRefPoint   << ", "
2291                 << "SMESH.PointStruct( "
2292                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2293                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2294                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2295   }
2296   return aGroups;
2297 }
2298
2299 //=======================================================================
2300 //function : ExtrusionAlongPathObject1DMakeGroups
2301 //purpose  : 
2302 //=======================================================================
2303
2304 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2305 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2306                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2307                                      GEOM::GEOM_Object_ptr      thePathShape,
2308                                      CORBA::Long                theNodeStart,
2309                                      CORBA::Boolean             theHasAngles,
2310                                      const SMESH::double_array& theAngles,
2311                                      CORBA::Boolean             theHasRefPoint,
2312                                      const SMESH::PointStruct&  theRefPoint,
2313                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2314 {
2315   SMESH::long_array_var anElementsId = theObject->GetIDs();
2316   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2317                                                       thePathMesh,
2318                                                       thePathShape,
2319                                                       theNodeStart,
2320                                                       theHasAngles,
2321                                                       theAngles,
2322                                                       theHasRefPoint,
2323                                                       theRefPoint,
2324                                                       true,
2325                                                       Error,
2326                                                       SMDSAbs_Edge);
2327   
2328   if ( !myPreviewMode ) {
2329     bool isDumpGroups = aGroups && aGroups->length() > 0;
2330     TPythonDump aPythonDump;
2331     if(isDumpGroups) {
2332       aPythonDump << "("<<aGroups;
2333     }
2334     if(isDumpGroups)
2335       aPythonDump << ", error)";
2336     else
2337       aPythonDump <<"error";
2338
2339     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
2340                 << theObject << ", "
2341                 << thePathMesh      << ", "
2342                 << thePathShape     << ", "
2343                 << theNodeStart     << ", "
2344                 << theHasAngles     << ", "
2345                 << theAngles        << ", "
2346                 << theHasRefPoint   << ", "
2347                 << "SMESH.PointStruct( "
2348                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2349                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2350                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2351   }
2352   return aGroups;
2353 }
2354
2355 //=======================================================================
2356 //function : ExtrusionAlongPathObject2DMakeGroups
2357 //purpose  : 
2358 //=======================================================================
2359
2360 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2361 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2362                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2363                                      GEOM::GEOM_Object_ptr      thePathShape,
2364                                      CORBA::Long                theNodeStart,
2365                                      CORBA::Boolean             theHasAngles,
2366                                      const SMESH::double_array& theAngles,
2367                                      CORBA::Boolean             theHasRefPoint,
2368                                      const SMESH::PointStruct&  theRefPoint,
2369                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2370 {
2371   SMESH::long_array_var anElementsId = theObject->GetIDs();
2372   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2373                                                       thePathMesh,
2374                                                       thePathShape,
2375                                                       theNodeStart,
2376                                                       theHasAngles,
2377                                                       theAngles,
2378                                                       theHasRefPoint,
2379                                                       theRefPoint,
2380                                                       true,
2381                                                       Error,
2382                                                       SMDSAbs_Face);
2383   
2384   if ( !myPreviewMode ) {
2385     bool isDumpGroups = aGroups && aGroups->length() > 0;
2386     TPythonDump aPythonDump;
2387     if(isDumpGroups) {
2388       aPythonDump << "("<<aGroups;
2389     }
2390     if(isDumpGroups)
2391       aPythonDump << ", error)";
2392     else
2393       aPythonDump <<"error";
2394
2395     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
2396                 << theObject << ", "
2397                 << thePathMesh      << ", "
2398                 << thePathShape     << ", "
2399                 << theNodeStart     << ", "
2400                 << theHasAngles     << ", "
2401                 << theAngles        << ", "
2402                 << theHasRefPoint   << ", "
2403                 << "SMESH.PointStruct( "
2404                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2405                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2406                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2407   }
2408   return aGroups;
2409 }
2410
2411 //================================================================================
2412 /*!
2413  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2414  * of given angles along path steps
2415   * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
2416   *                which proceeds the extrusion
2417   * \param PathShape is shape(edge); as the mesh can be complex, the edge 
2418   *                 is used to define the sub-mesh for the path
2419  */
2420 //================================================================================
2421
2422 SMESH::double_array*
2423 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
2424                                           GEOM::GEOM_Object_ptr       thePathShape,
2425                                           const SMESH::double_array & theAngles)
2426 {
2427   SMESH::double_array_var aResult = new SMESH::double_array();
2428   int nbAngles = theAngles.length();
2429   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2430   {
2431     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2432     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2433     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2434     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2435       return aResult._retn();
2436     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2437     if ( nbSteps == nbAngles )
2438     {
2439       aResult.inout() = theAngles;
2440     }
2441     else
2442     {
2443       aResult->length( nbSteps );
2444       double rAn2St = double( nbAngles ) / double( nbSteps );
2445       double angPrev = 0, angle;
2446       for ( int iSt = 0; iSt < nbSteps; ++iSt )
2447       {
2448         double angCur = rAn2St * ( iSt+1 );
2449         double angCurFloor  = floor( angCur );
2450         double angPrevFloor = floor( angPrev );
2451         if ( angPrevFloor == angCurFloor )
2452           angle = rAn2St * theAngles[ int( angCurFloor ) ];
2453         else
2454         {
2455           int iP = int( angPrevFloor );
2456           double angPrevCeil = ceil(angPrev);
2457           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2458           
2459           int iC = int( angCurFloor );
2460           if ( iC < nbAngles )
2461             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2462
2463           iP = int( angPrevCeil );
2464           while ( iC-- > iP )
2465             angle += theAngles[ iC ];
2466         }
2467         aResult[ iSt ] = angle;
2468         angPrev = angCur;
2469       }
2470     }
2471   }
2472   // Update Python script
2473   TPythonDump() << "rotAngles = " << theAngles;
2474   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2475                 << thePathMesh  << ", "
2476                 << thePathShape << ", "
2477                 << "rotAngles )";
2478
2479   return aResult._retn();
2480 }
2481
2482
2483 //=======================================================================
2484 //function : mirror
2485 //purpose  : 
2486 //=======================================================================
2487
2488 SMESH::ListOfGroups*
2489 SMESH_MeshEditor_i::mirror(const SMESH::long_array &           theIDsOfElements,
2490                            const SMESH::AxisStruct &           theAxis,
2491                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2492                            CORBA::Boolean                      theCopy,
2493                            const bool                          theMakeGroups,
2494                            ::SMESH_Mesh*                       theTargetMesh)
2495 {
2496   initData();
2497
2498   TIDSortedElemSet elements;
2499   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2500
2501   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2502   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2503
2504   gp_Trsf aTrsf;
2505   switch ( theMirrorType ) {
2506   case  SMESH::SMESH_MeshEditor::POINT:
2507     aTrsf.SetMirror( P );
2508     break;
2509   case  SMESH::SMESH_MeshEditor::AXIS:
2510     aTrsf.SetMirror( gp_Ax1( P, V ));
2511     break;
2512   default:
2513     aTrsf.SetMirror( gp_Ax2( P, V ));
2514   }
2515
2516   ::SMESH_MeshEditor anEditor( myMesh );
2517   ::SMESH_MeshEditor::PGroupIDs groupIds =
2518       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2519
2520   if(theCopy) {
2521     storeResult(anEditor);
2522   }
2523   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2524 }
2525
2526 //=======================================================================
2527 //function : Mirror
2528 //purpose  :
2529 //=======================================================================
2530
2531 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
2532                                 const SMESH::AxisStruct &           theAxis,
2533                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2534                                 CORBA::Boolean                      theCopy)
2535 {
2536   if ( !myPreviewMode ) {
2537     TPythonDump() << this << ".Mirror( "
2538                   << theIDsOfElements << ", "
2539                   << theAxis          << ", "
2540                   << mirrorTypeName(theMirrorType) << ", "
2541                   << theCopy          << " )";
2542   }
2543   mirror(theIDsOfElements, theAxis, theMirrorType, theCopy, false);
2544 }
2545
2546
2547 //=======================================================================
2548 //function : MirrorObject
2549 //purpose  :
2550 //=======================================================================
2551
2552 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
2553                                       const SMESH::AxisStruct &           theAxis,
2554                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2555                                       CORBA::Boolean                      theCopy)
2556 {
2557   if ( !myPreviewMode ) {
2558     TPythonDump() << this << ".MirrorObject( "
2559                   << theObject << ", "
2560                   << theAxis   << ", "
2561                   << mirrorTypeName(theMirrorType) << ", "
2562                   << theCopy   << " )";
2563   }
2564   SMESH::long_array_var anElementsId = theObject->GetIDs();
2565   mirror(anElementsId, theAxis, theMirrorType, theCopy, false);
2566 }
2567
2568 //=======================================================================
2569 //function : MirrorMakeGroups
2570 //purpose  : 
2571 //=======================================================================
2572
2573 SMESH::ListOfGroups*
2574 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
2575                                      const SMESH::AxisStruct&            theMirror,
2576                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2577 {
2578   SMESH::ListOfGroups * aGroups = mirror(theIDsOfElements, theMirror, theMirrorType, true, true);
2579   if ( !myPreviewMode ) {
2580     TPythonDump aPythonDump;
2581     DumpGroupsList(aPythonDump,aGroups);
2582     aPythonDump << this << ".MirrorMakeGroups( "
2583                 << theIDsOfElements << ", "
2584                 << theMirror << ", "
2585                 << mirrorTypeName(theMirrorType) << " )";
2586   }
2587   return aGroups;
2588 }
2589
2590 //=======================================================================
2591 //function : MirrorObjectMakeGroups
2592 //purpose  : 
2593 //=======================================================================
2594
2595 SMESH::ListOfGroups*
2596 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
2597                                            const SMESH::AxisStruct&            theMirror,
2598                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2599 {
2600   SMESH::long_array_var anElementsId = theObject->GetIDs();
2601   SMESH::ListOfGroups * aGroups = mirror(anElementsId, theMirror, theMirrorType, true, true);
2602   if ( !myPreviewMode ) {
2603     TPythonDump aPythonDump;
2604     DumpGroupsList(aPythonDump,aGroups);
2605     aPythonDump << this << ".MirrorObjectMakeGroups( "
2606                 << theObject << ", "
2607                 << theMirror << ", "
2608                 << mirrorTypeName(theMirrorType) << " )";
2609   }
2610   return aGroups;
2611 }
2612
2613 //=======================================================================
2614 //function : MirrorMakeMesh
2615 //purpose  : 
2616 //=======================================================================
2617
2618 SMESH::SMESH_Mesh_ptr
2619 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
2620                                    const SMESH::AxisStruct&            theMirror,
2621                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2622                                    CORBA::Boolean                      theCopyGroups,
2623                                    const char*                         theMeshName)
2624 {
2625   SMESH_Mesh_i* mesh_i;
2626   SMESH::SMESH_Mesh_var mesh;
2627   { // open new scope to dump "MakeMesh" command
2628     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2629     
2630     TPythonDump pydump; // to prevent dump at mesh creation
2631
2632     mesh = makeMesh( theMeshName );
2633     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2634     if (mesh_i) {
2635       mirror(theIDsOfElements, theMirror, theMirrorType,
2636              false, theCopyGroups, & mesh_i->GetImpl());
2637       mesh_i->CreateGroupServants();
2638     }
2639     
2640     if ( !myPreviewMode ) {
2641       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
2642              << theIDsOfElements << ", "
2643              << theMirror   << ", "
2644              << mirrorTypeName(theMirrorType) << ", "
2645              << theCopyGroups << ", '"
2646              << theMeshName << "' )";
2647     }
2648   }
2649
2650   //dump "GetGroups"
2651   if(!myPreviewMode && mesh_i)
2652     mesh_i->GetGroups();
2653   
2654   return mesh._retn();
2655 }
2656
2657 //=======================================================================
2658 //function : MirrorObjectMakeMesh
2659 //purpose  : 
2660 //=======================================================================
2661
2662 SMESH::SMESH_Mesh_ptr
2663 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
2664                                          const SMESH::AxisStruct&            theMirror,
2665                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2666                                          CORBA::Boolean                      theCopyGroups,
2667                                          const char*                         theMeshName)
2668 {
2669   SMESH_Mesh_i* mesh_i;
2670   SMESH::SMESH_Mesh_var mesh;
2671   { // open new scope to dump "MakeMesh" command
2672     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2673     
2674     TPythonDump pydump; // to prevent dump at mesh creation
2675
2676     mesh = makeMesh( theMeshName );
2677     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2678     if ( mesh_i ) {
2679       SMESH::long_array_var anElementsId = theObject->GetIDs();
2680       mirror(anElementsId, theMirror, theMirrorType,
2681              false, theCopyGroups, & mesh_i->GetImpl());
2682       mesh_i->CreateGroupServants();
2683     }
2684
2685     if ( !myPreviewMode ) {
2686       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
2687              << theObject << ", "
2688              << theMirror   << ", "
2689              << mirrorTypeName(theMirrorType) << ", "
2690              << theCopyGroups << ", '"
2691              << theMeshName << "' )";
2692     }
2693   } 
2694
2695   //dump "GetGroups"
2696   if(!myPreviewMode && mesh_i)
2697     mesh_i->GetGroups();
2698   
2699   return mesh._retn();
2700 }
2701
2702 //=======================================================================
2703 //function : translate
2704 //purpose  : 
2705 //=======================================================================
2706
2707 SMESH::ListOfGroups*
2708 SMESH_MeshEditor_i::translate(const SMESH::long_array & theIDsOfElements,
2709                               const SMESH::DirStruct &  theVector,
2710                               CORBA::Boolean            theCopy,
2711                               const bool                theMakeGroups,
2712                               ::SMESH_Mesh*             theTargetMesh)
2713 {
2714   initData();
2715
2716   TIDSortedElemSet elements;
2717   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2718
2719   gp_Trsf aTrsf;
2720   const SMESH::PointStruct * P = &theVector.PS;
2721   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
2722
2723   ::SMESH_MeshEditor anEditor( myMesh );
2724   ::SMESH_MeshEditor::PGroupIDs groupIds =
2725       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2726
2727   if(theCopy)
2728     storeResult(anEditor);
2729
2730   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2731 }
2732
2733 //=======================================================================
2734 //function : Translate
2735 //purpose  :
2736 //=======================================================================
2737
2738 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
2739                                    const SMESH::DirStruct &  theVector,
2740                                    CORBA::Boolean            theCopy)
2741 {
2742   if ( !myPreviewMode ) {
2743     TPythonDump() << this << ".Translate( "
2744                   << theIDsOfElements << ", "
2745                   << theVector << ", "
2746                   << theCopy << " )";
2747   }
2748   translate(theIDsOfElements,
2749             theVector,
2750             theCopy,
2751             false);
2752 }
2753
2754 //=======================================================================
2755 //function : TranslateObject
2756 //purpose  :
2757 //=======================================================================
2758
2759 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
2760                                          const SMESH::DirStruct &  theVector,
2761                                          CORBA::Boolean            theCopy)
2762 {
2763   if ( !myPreviewMode ) {
2764     TPythonDump() << this << ".TranslateObject( "
2765                   << theObject << ", "
2766                   << theVector << ", "
2767                   << theCopy << " )";
2768   }
2769   SMESH::long_array_var anElementsId = theObject->GetIDs();
2770   translate(anElementsId,
2771             theVector,
2772             theCopy,
2773             false);
2774 }
2775
2776 //=======================================================================
2777 //function : TranslateMakeGroups
2778 //purpose  : 
2779 //=======================================================================
2780
2781 SMESH::ListOfGroups*
2782 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
2783                                         const SMESH::DirStruct&  theVector)
2784 {
2785   SMESH::ListOfGroups * aGroups = translate(theIDsOfElements,theVector,true,true);
2786   if ( !myPreviewMode ) {
2787     TPythonDump aPythonDump;
2788     DumpGroupsList(aPythonDump,aGroups);
2789     aPythonDump << this << ".TranslateMakeGroups( "
2790                 << theIDsOfElements << ", "
2791                 << theVector << " )";
2792   }
2793   return aGroups;
2794 }
2795
2796 //=======================================================================
2797 //function : TranslateObjectMakeGroups
2798 //purpose  : 
2799 //=======================================================================
2800
2801 SMESH::ListOfGroups*
2802 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2803                                               const SMESH::DirStruct&   theVector)
2804 {
2805   SMESH::long_array_var anElementsId = theObject->GetIDs();
2806   SMESH::ListOfGroups * aGroups = translate(anElementsId, theVector, true, true);
2807   
2808   if ( !myPreviewMode ) {
2809
2810     TPythonDump aPythonDump;
2811     DumpGroupsList(aPythonDump,aGroups);
2812     aPythonDump << this << ".TranslateObjectMakeGroups( "
2813                 << theObject << ", "
2814                 << theVector << " )";
2815   }
2816   return aGroups;
2817 }
2818
2819 //=======================================================================
2820 //function : TranslateMakeMesh
2821 //purpose  : 
2822 //=======================================================================
2823
2824 SMESH::SMESH_Mesh_ptr
2825 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
2826                                       const SMESH::DirStruct&  theVector,
2827                                       CORBA::Boolean           theCopyGroups,
2828                                       const char*              theMeshName)
2829 {
2830   SMESH_Mesh_i* mesh_i;
2831   SMESH::SMESH_Mesh_var mesh;
2832   
2833   { // open new scope to dump "MakeMesh" command
2834     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2835
2836     TPythonDump pydump; // to prevent dump at mesh creation
2837     
2838     mesh = makeMesh( theMeshName );
2839     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2840     
2841     if ( mesh_i ) {
2842       translate(theIDsOfElements, theVector,
2843                 false, theCopyGroups, & mesh_i->GetImpl());
2844       mesh_i->CreateGroupServants();
2845     }
2846     
2847     if ( !myPreviewMode ) {
2848       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
2849              << theIDsOfElements << ", "
2850              << theVector   << ", "
2851              << theCopyGroups << ", '"
2852              << theMeshName << "' )";
2853     }
2854   }
2855   
2856   //dump "GetGroups"
2857   if(!myPreviewMode && mesh_i)
2858     mesh_i->GetGroups();
2859   
2860   return mesh._retn();
2861 }
2862
2863 //=======================================================================
2864 //function : TranslateObjectMakeMesh
2865 //purpose  : 
2866 //=======================================================================
2867
2868 SMESH::SMESH_Mesh_ptr
2869 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
2870                                             const SMESH::DirStruct&   theVector,
2871                                             CORBA::Boolean            theCopyGroups,
2872                                             const char*               theMeshName)
2873 {
2874   SMESH_Mesh_i* mesh_i;
2875   SMESH::SMESH_Mesh_var mesh;
2876   { // open new scope to dump "MakeMesh" command
2877     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2878     
2879     TPythonDump pydump; // to prevent dump at mesh creation
2880     mesh = makeMesh( theMeshName );
2881     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2882     
2883     if ( mesh_i ) {
2884       SMESH::long_array_var anElementsId = theObject->GetIDs();
2885       translate(anElementsId, theVector,
2886                 false, theCopyGroups, & mesh_i->GetImpl());
2887       mesh_i->CreateGroupServants();
2888     }
2889     if ( !myPreviewMode ) {
2890       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
2891              << theObject << ", "
2892              << theVector   << ", "
2893              << theCopyGroups << ", '"
2894              << theMeshName << "' )";
2895     }
2896   }
2897   
2898   //dump "GetGroups"
2899   if(!myPreviewMode && mesh_i)
2900     mesh_i->GetGroups();
2901   
2902   return mesh._retn();
2903 }
2904
2905 //=======================================================================
2906 //function : rotate
2907 //purpose  : 
2908 //=======================================================================
2909
2910 SMESH::ListOfGroups*
2911 SMESH_MeshEditor_i::rotate(const SMESH::long_array & theIDsOfElements,
2912                            const SMESH::AxisStruct & theAxis,
2913                            CORBA::Double             theAngle,
2914                            CORBA::Boolean            theCopy,
2915                            const bool                theMakeGroups,
2916                            ::SMESH_Mesh*             theTargetMesh)
2917 {
2918   initData();
2919
2920   TIDSortedElemSet elements;
2921   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2922
2923   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2924   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2925
2926   gp_Trsf aTrsf;
2927   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
2928
2929   ::SMESH_MeshEditor anEditor( myMesh );
2930   ::SMESH_MeshEditor::PGroupIDs groupIds =
2931       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2932
2933   if(theCopy) {
2934     storeResult(anEditor);
2935   }
2936   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2937 }
2938
2939 //=======================================================================
2940 //function : Rotate
2941 //purpose  :
2942 //=======================================================================
2943
2944 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
2945                                 const SMESH::AxisStruct & theAxis,
2946                                 CORBA::Double             theAngle,
2947                                 CORBA::Boolean            theCopy)
2948 {
2949   if ( !myPreviewMode ) {
2950     TPythonDump() << this << ".Rotate( "
2951                   << theIDsOfElements << ", "
2952                   << theAxis << ", "
2953                   << theAngle << ", "
2954                   << theCopy << " )";
2955   }
2956   rotate(theIDsOfElements,
2957          theAxis,
2958          theAngle,
2959          theCopy,
2960          false);
2961 }
2962
2963 //=======================================================================
2964 //function : RotateObject
2965 //purpose  :
2966 //=======================================================================
2967
2968 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
2969                                       const SMESH::AxisStruct & theAxis,
2970                                       CORBA::Double             theAngle,
2971                                       CORBA::Boolean            theCopy)
2972 {
2973   if ( !myPreviewMode ) {
2974     TPythonDump() << this << ".RotateObject( "
2975                   << theObject << ", "
2976                   << theAxis << ", "
2977                   << theAngle << ", "
2978                   << theCopy << " )";
2979   }
2980   SMESH::long_array_var anElementsId = theObject->GetIDs();
2981   rotate(anElementsId,
2982          theAxis,
2983          theAngle,
2984          theCopy,
2985          false);
2986 }
2987
2988 //=======================================================================
2989 //function : RotateMakeGroups
2990 //purpose  : 
2991 //=======================================================================
2992
2993 SMESH::ListOfGroups*
2994 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
2995                                      const SMESH::AxisStruct& theAxis,
2996                                      CORBA::Double            theAngle)
2997 {
2998   SMESH::ListOfGroups * aGroups =  rotate(theIDsOfElements,theAxis,theAngle,true,true);
2999   if ( !myPreviewMode ) {
3000     TPythonDump aPythonDump;
3001     DumpGroupsList(aPythonDump,aGroups);
3002     aPythonDump << this << ".RotateMakeGroups( "
3003                 << theIDsOfElements << ", "
3004                 << theAxis << ", "
3005                 << theAngle << " )";
3006   }
3007   return aGroups;
3008 }
3009
3010 //=======================================================================
3011 //function : RotateObjectMakeGroups
3012 //purpose  : 
3013 //=======================================================================
3014
3015 SMESH::ListOfGroups*
3016 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3017                                            const SMESH::AxisStruct&  theAxis,
3018                                            CORBA::Double             theAngle)
3019 {
3020   SMESH::long_array_var anElementsId = theObject->GetIDs();
3021   SMESH::ListOfGroups * aGroups =  rotate(anElementsId,theAxis,theAngle,true,true);
3022  
3023   if ( !myPreviewMode ) {
3024     TPythonDump aPythonDump;
3025     DumpGroupsList(aPythonDump,aGroups);
3026     aPythonDump << this << ".RotateObjectMakeGroups( "
3027                 << theObject << ", "
3028                 << theAxis << ", "
3029                 << theAngle << " )";
3030   }
3031   return aGroups;
3032 }
3033
3034 //=======================================================================
3035 //function : RotateMakeMesh
3036 //purpose  : 
3037 //=======================================================================
3038
3039 SMESH::SMESH_Mesh_ptr 
3040 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3041                                    const SMESH::AxisStruct& theAxis,
3042                                    CORBA::Double            theAngleInRadians,
3043                                    CORBA::Boolean           theCopyGroups,
3044                                    const char*              theMeshName)
3045 {
3046   SMESH::SMESH_Mesh_var mesh;
3047   SMESH_Mesh_i* mesh_i;
3048
3049   { // open new scope to dump "MakeMesh" command
3050     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3051     
3052     TPythonDump pydump; // to prevent dump at mesh creation
3053
3054     mesh = makeMesh( theMeshName );
3055     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3056     
3057     if ( mesh_i ) {
3058       rotate(theIDsOfElements, theAxis, theAngleInRadians,
3059              false, theCopyGroups, & mesh_i->GetImpl());
3060       mesh_i->CreateGroupServants();
3061     }
3062     if ( !myPreviewMode ) {
3063       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3064              << theIDsOfElements << ", "
3065              << theAxis << ", "
3066              << theAngleInRadians   << ", "
3067              << theCopyGroups << ", '"
3068              << theMeshName << "' )";
3069     }
3070   }
3071   
3072   //dump "GetGroups"
3073   if(!myPreviewMode && mesh_i)
3074     mesh_i->GetGroups();
3075   
3076   return mesh._retn();
3077 }
3078
3079 //=======================================================================
3080 //function : RotateObjectMakeMesh
3081 //purpose  : 
3082 //=======================================================================
3083
3084 SMESH::SMESH_Mesh_ptr 
3085 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3086                                          const SMESH::AxisStruct&  theAxis,
3087                                          CORBA::Double             theAngleInRadians,
3088                                          CORBA::Boolean            theCopyGroups,
3089                                          const char*               theMeshName)
3090 {
3091   SMESH::SMESH_Mesh_var mesh;
3092   SMESH_Mesh_i* mesh_i;
3093   
3094   {// open new scope to dump "MakeMesh" command
3095    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3096     
3097     TPythonDump pydump; // to prevent dump at mesh creation
3098     mesh = makeMesh( theMeshName );
3099     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3100     
3101     if (mesh_i ) {
3102       SMESH::long_array_var anElementsId = theObject->GetIDs();
3103       rotate(anElementsId, theAxis, theAngleInRadians,
3104              false, theCopyGroups, & mesh_i->GetImpl());
3105       mesh_i->CreateGroupServants();
3106     }
3107     if ( !myPreviewMode ) {
3108       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3109              << theObject << ", "
3110              << theAxis << ", "
3111              << theAngleInRadians   << ", "
3112              << theCopyGroups << ", '"
3113              << theMeshName << "' )";
3114     }
3115   }
3116   
3117   //dump "GetGroups"
3118   if(!myPreviewMode && mesh_i)
3119     mesh_i->GetGroups();
3120   
3121   return mesh._retn();
3122 }
3123
3124 //=======================================================================
3125 //function : FindCoincidentNodes
3126 //purpose  :
3127 //=======================================================================
3128
3129 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
3130                                               SMESH::array_of_long_array_out GroupsOfNodes)
3131 {
3132   initData();
3133
3134   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3135   ::SMESH_MeshEditor anEditor( myMesh );
3136   set<const SMDS_MeshNode*> nodes; // no input nodes
3137   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3138
3139   GroupsOfNodes = new SMESH::array_of_long_array;
3140   GroupsOfNodes->length( aListOfListOfNodes.size() );
3141   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3142   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3143     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3144     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3145     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3146     aGroup.length( aListOfNodes.size() );
3147     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3148       aGroup[ j ] = (*lIt)->GetID();
3149   }
3150   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3151                 << Tolerance << " )";
3152 }
3153
3154 //=======================================================================
3155 //function : FindCoincidentNodesOnPart
3156 //purpose  :
3157 //=======================================================================
3158 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
3159                                                    CORBA::Double                  Tolerance,
3160                                                    SMESH::array_of_long_array_out GroupsOfNodes)
3161 {
3162   initData();
3163   SMESH::long_array_var aElementsId = theObject->GetIDs();
3164
3165   SMESHDS_Mesh* aMesh = GetMeshDS();
3166   set<const SMDS_MeshNode*> nodes;
3167
3168   if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
3169       SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) {
3170     for(int i = 0; i < aElementsId->length(); i++) {
3171       CORBA::Long ind = aElementsId[i];
3172       const SMDS_MeshNode * elem = aMesh->FindNode(ind);
3173       if(elem)
3174         nodes.insert(elem);
3175     }
3176   }
3177   else {
3178     for(int i = 0; i < aElementsId->length(); i++) {
3179       CORBA::Long ind = aElementsId[i];
3180       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
3181       if(elem) {
3182         SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
3183         while ( nIt->more() )
3184           nodes.insert( nodes.end(),static_cast<const SMDS_MeshNode*>(nIt->next()));
3185       }
3186     }
3187   }
3188     
3189   
3190   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3191   ::SMESH_MeshEditor anEditor( myMesh );
3192   if(!nodes.empty())
3193     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3194   
3195   GroupsOfNodes = new SMESH::array_of_long_array;
3196   GroupsOfNodes->length( aListOfListOfNodes.size() );
3197   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3198   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3199     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3200     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3201     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3202     aGroup.length( aListOfNodes.size() );
3203     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3204       aGroup[ j ] = (*lIt)->GetID();
3205   }
3206   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3207                 <<theObject<<", "
3208                 << Tolerance << " )";
3209 }
3210
3211 //=======================================================================
3212 //function : MergeNodes
3213 //purpose  :
3214 //=======================================================================
3215
3216 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
3217 {
3218   initData();
3219
3220   SMESHDS_Mesh* aMesh = GetMeshDS();
3221
3222   TPythonDump aTPythonDump;
3223   aTPythonDump << this << ".MergeNodes([";
3224   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3225   for (int i = 0; i < GroupsOfNodes.length(); i++)
3226   {
3227     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
3228     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
3229     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
3230     for ( int j = 0; j < aNodeGroup.length(); j++ )
3231     {
3232       CORBA::Long index = aNodeGroup[ j ];
3233       const SMDS_MeshNode * node = aMesh->FindNode(index);
3234       if ( node )
3235         aListOfNodes.push_back( node );
3236     }
3237     if ( aListOfNodes.size() < 2 )
3238       aListOfListOfNodes.pop_back();
3239
3240     if ( i > 0 ) aTPythonDump << ", ";
3241     aTPythonDump << aNodeGroup;
3242   }
3243   ::SMESH_MeshEditor anEditor( myMesh );
3244   anEditor.MergeNodes( aListOfListOfNodes );
3245
3246   aTPythonDump <<  "])";
3247 }
3248
3249 //=======================================================================
3250 //function : FindEqualElements
3251 //purpose  :
3252 //=======================================================================
3253 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
3254                                            SMESH::array_of_long_array_out GroupsOfElementsID)
3255 {
3256   initData();
3257   if ( !(!CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
3258          SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) ) {
3259     typedef list<int> TListOfIDs;
3260     set<const SMDS_MeshElement*> elems;
3261     SMESH::long_array_var aElementsId = theObject->GetIDs();
3262     SMESHDS_Mesh* aMesh = GetMeshDS();
3263
3264     for(int i = 0; i < aElementsId->length(); i++) {
3265       CORBA::Long anID = aElementsId[i];
3266       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
3267       if (elem) {
3268         elems.insert(elem);
3269       }
3270     }
3271
3272     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3273     ::SMESH_MeshEditor anEditor( myMesh );
3274     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
3275
3276     GroupsOfElementsID = new SMESH::array_of_long_array;
3277     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
3278
3279     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
3280     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
3281       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
3282       TListOfIDs& listOfIDs = *arraysIt;
3283       aGroup.length( listOfIDs.size() );
3284       TListOfIDs::iterator idIt = listOfIDs.begin();
3285       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
3286         aGroup[ k ] = *idIt;
3287       }
3288     }
3289
3290   TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
3291                 <<theObject<<" )";
3292   }
3293 }
3294
3295 //=======================================================================
3296 //function : MergeElements
3297 //purpose  :
3298 //=======================================================================
3299
3300 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
3301 {
3302   initData();
3303
3304   TPythonDump aTPythonDump;
3305   aTPythonDump << this << ".MergeElements( [";
3306
3307   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3308
3309   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
3310     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
3311     aListOfListOfElementsID.push_back( list< int >() );
3312     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
3313     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
3314       CORBA::Long id = anElemsIDGroup[ j ];
3315       aListOfElemsID.push_back( id );
3316     }
3317     if ( aListOfElemsID.size() < 2 )
3318       aListOfListOfElementsID.pop_back();
3319     if ( i > 0 ) aTPythonDump << ", ";
3320     aTPythonDump << anElemsIDGroup;
3321   }
3322
3323   ::SMESH_MeshEditor anEditor( myMesh );
3324   anEditor.MergeElements(aListOfListOfElementsID);
3325
3326   aTPythonDump << "] )";
3327 }
3328
3329 //=======================================================================
3330 //function : MergeEqualElements
3331 //purpose  :
3332 //=======================================================================
3333
3334 void SMESH_MeshEditor_i::MergeEqualElements()
3335 {
3336   initData();
3337
3338   ::SMESH_MeshEditor anEditor( myMesh );
3339   anEditor.MergeEqualElements();
3340
3341   TPythonDump() << this << ".MergeEqualElements()";
3342 }
3343
3344 //================================================================================
3345 /*!
3346  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
3347  * move the node closest to the point to point's location and return ID of the node
3348  */
3349 //================================================================================
3350
3351 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
3352                                                        CORBA::Double y,
3353                                                        CORBA::Double z,
3354                                                        CORBA::Long   theNodeID)
3355 {
3356   // We keep myNodeSearcher until any mesh modification:
3357   // 1) initData() deletes myNodeSearcher at any edition,
3358   // 2) TNodeSearcherDeleter - at any mesh compute event and mesh change
3359
3360   initData();
3361
3362   int nodeID = theNodeID;
3363   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
3364   if ( !node )
3365   {
3366     static TNodeSearcherDeleter deleter;
3367     deleter.Set( myMesh );
3368     if ( !myNodeSearcher ) {
3369       ::SMESH_MeshEditor anEditor( myMesh );
3370       myNodeSearcher = anEditor.GetNodeSearcher();
3371     }
3372     gp_Pnt p( x,y,z );
3373     node = myNodeSearcher->FindClosestTo( p );
3374   }
3375   if ( node ) {
3376     nodeID = node->GetID();
3377     if ( myPreviewMode ) // make preview data
3378     {
3379       // in a preview mesh, make edges linked to a node
3380       TPreviewMesh tmpMesh;
3381       TIDSortedElemSet linkedNodes;
3382       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3383       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3384       for ( ; nIt != linkedNodes.end(); ++nIt )
3385       {
3386         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3387         tmpMesh.Copy( &edge );
3388       }
3389       // move copied node
3390       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
3391       if ( node )
3392         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3393       // fill preview data
3394       ::SMESH_MeshEditor anEditor( & tmpMesh );
3395       storeResult( anEditor );
3396     }
3397     else
3398     {
3399       GetMeshDS()->MoveNode(node, x, y, z);
3400     }
3401   }
3402
3403   if ( !myPreviewMode ) {
3404     TPythonDump() << "nodeID = " << this
3405                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
3406                   << ", " << nodeID << " )";
3407   }
3408
3409   return nodeID;
3410 }
3411
3412 //=======================================================================
3413 //function : convError
3414 //purpose  :
3415 //=======================================================================
3416
3417 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
3418
3419 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
3420 {
3421   switch ( e ) {
3422   RETCASE( SEW_OK );
3423   RETCASE( SEW_BORDER1_NOT_FOUND );
3424   RETCASE( SEW_BORDER2_NOT_FOUND );
3425   RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
3426   RETCASE( SEW_BAD_SIDE_NODES );
3427   RETCASE( SEW_VOLUMES_TO_SPLIT );
3428   RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
3429   RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
3430   RETCASE( SEW_BAD_SIDE1_NODES );
3431   RETCASE( SEW_BAD_SIDE2_NODES );
3432   }
3433   return SMESH::SMESH_MeshEditor::SEW_OK;
3434 }
3435
3436 //=======================================================================
3437 //function : SewFreeBorders
3438 //purpose  :
3439 //=======================================================================
3440
3441 SMESH::SMESH_MeshEditor::Sew_Error
3442   SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
3443                                      CORBA::Long SecondNodeID1,
3444                                      CORBA::Long LastNodeID1,
3445                                      CORBA::Long FirstNodeID2,
3446                                      CORBA::Long SecondNodeID2,
3447                                      CORBA::Long LastNodeID2,
3448                                      CORBA::Boolean CreatePolygons,
3449                                      CORBA::Boolean CreatePolyedrs)
3450 {
3451   initData();
3452
3453   SMESHDS_Mesh* aMesh = GetMeshDS();
3454
3455   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
3456   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
3457   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
3458   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
3459   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
3460   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
3461
3462   if (!aBorderFirstNode ||
3463       !aBorderSecondNode||
3464       !aBorderLastNode)
3465     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3466   if (!aSide2FirstNode  ||
3467       !aSide2SecondNode ||
3468       !aSide2ThirdNode)
3469     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
3470
3471   TPythonDump() << "error = " << this << ".SewFreeBorders( "
3472                 << FirstNodeID1  << ", "
3473                 << SecondNodeID1 << ", "
3474                 << LastNodeID1   << ", "
3475                 << FirstNodeID2  << ", "
3476                 << SecondNodeID2 << ", "
3477                 << LastNodeID2   << ", "
3478                 << CreatePolygons<< ", "
3479                 << CreatePolyedrs<< " )";
3480
3481   ::SMESH_MeshEditor anEditor( myMesh );
3482   SMESH::SMESH_MeshEditor::Sew_Error error =
3483     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3484                                        aBorderSecondNode,
3485                                        aBorderLastNode,
3486                                        aSide2FirstNode,
3487                                        aSide2SecondNode,
3488                                        aSide2ThirdNode,
3489                                        true,
3490                                        CreatePolygons,
3491                                        CreatePolyedrs) );
3492
3493   storeResult(anEditor);
3494
3495   return error;
3496 }
3497
3498
3499 //=======================================================================
3500 //function : SewConformFreeBorders
3501 //purpose  :
3502 //=======================================================================
3503
3504 SMESH::SMESH_MeshEditor::Sew_Error
3505 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
3506                                           CORBA::Long SecondNodeID1,
3507                                           CORBA::Long LastNodeID1,
3508                                           CORBA::Long FirstNodeID2,
3509                                           CORBA::Long SecondNodeID2)
3510 {
3511   initData();
3512
3513   SMESHDS_Mesh* aMesh = GetMeshDS();
3514
3515   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
3516   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
3517   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
3518   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
3519   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
3520   const SMDS_MeshNode* aSide2ThirdNode   = 0;
3521
3522   if (!aBorderFirstNode ||
3523       !aBorderSecondNode||
3524       !aBorderLastNode )
3525     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3526   if (!aSide2FirstNode  ||
3527       !aSide2SecondNode)
3528     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
3529
3530   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
3531                 << FirstNodeID1  << ", "
3532                 << SecondNodeID1 << ", "
3533                 << LastNodeID1   << ", "
3534                 << FirstNodeID2  << ", "
3535                 << SecondNodeID2 << " )";
3536
3537   ::SMESH_MeshEditor anEditor( myMesh );
3538   SMESH::SMESH_MeshEditor::Sew_Error error =
3539     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3540                                        aBorderSecondNode,
3541                                        aBorderLastNode,
3542                                        aSide2FirstNode,
3543                                        aSide2SecondNode,
3544                                        aSide2ThirdNode,
3545                                        true,
3546                                        false, false) );
3547
3548   storeResult(anEditor);
3549
3550   return error;
3551 }
3552
3553
3554 //=======================================================================
3555 //function : SewBorderToSide
3556 //purpose  :
3557 //=======================================================================
3558
3559 SMESH::SMESH_MeshEditor::Sew_Error
3560 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
3561                                     CORBA::Long SecondNodeIDOnFreeBorder,
3562                                     CORBA::Long LastNodeIDOnFreeBorder,
3563                                     CORBA::Long FirstNodeIDOnSide,
3564                                     CORBA::Long LastNodeIDOnSide,
3565                                     CORBA::Boolean CreatePolygons,
3566                                     CORBA::Boolean CreatePolyedrs)
3567 {
3568   initData();
3569
3570   SMESHDS_Mesh* aMesh = GetMeshDS();
3571
3572   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
3573   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
3574   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
3575   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
3576   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
3577   const SMDS_MeshNode* aSide2ThirdNode   = 0;
3578
3579   if (!aBorderFirstNode ||
3580       !aBorderSecondNode||
3581       !aBorderLastNode  )
3582     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3583   if (!aSide2FirstNode  ||
3584       !aSide2SecondNode)
3585     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
3586
3587   TPythonDump() << "error = " << this << ".SewBorderToSide( "
3588                 << FirstNodeIDOnFreeBorder  << ", "
3589                 << SecondNodeIDOnFreeBorder << ", "
3590                 << LastNodeIDOnFreeBorder   << ", "
3591                 << FirstNodeIDOnSide        << ", "
3592                 << LastNodeIDOnSide         << ", "
3593                 << CreatePolygons           << ", "
3594                 << CreatePolyedrs           << ") ";
3595
3596   ::SMESH_MeshEditor anEditor( myMesh );
3597   SMESH::SMESH_MeshEditor::Sew_Error error =
3598     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3599                                        aBorderSecondNode,
3600                                        aBorderLastNode,
3601                                        aSide2FirstNode,
3602                                        aSide2SecondNode,
3603                                        aSide2ThirdNode,
3604                                        false,
3605                                        CreatePolygons,
3606                                        CreatePolyedrs) );
3607
3608   storeResult(anEditor);
3609
3610   return error;
3611 }
3612
3613
3614 //=======================================================================
3615 //function : SewSideElements
3616 //purpose  :
3617 //=======================================================================
3618
3619 SMESH::SMESH_MeshEditor::Sew_Error
3620 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
3621                                     const SMESH::long_array& IDsOfSide2Elements,
3622                                     CORBA::Long NodeID1OfSide1ToMerge,
3623                                     CORBA::Long NodeID1OfSide2ToMerge,
3624                                     CORBA::Long NodeID2OfSide1ToMerge,
3625                                     CORBA::Long NodeID2OfSide2ToMerge)
3626 {
3627   initData();
3628
3629   SMESHDS_Mesh* aMesh = GetMeshDS();
3630
3631   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
3632   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
3633   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
3634   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
3635
3636   if (!aFirstNode1ToMerge ||
3637       !aFirstNode2ToMerge )
3638     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
3639   if (!aSecondNode1ToMerge||
3640       !aSecondNode2ToMerge)
3641     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
3642
3643   TIDSortedElemSet aSide1Elems, aSide2Elems;
3644   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
3645   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
3646
3647   TPythonDump() << "error = " << this << ".SewSideElements( "
3648                 << IDsOfSide1Elements << ", "
3649                 << IDsOfSide2Elements << ", "
3650                 << NodeID1OfSide1ToMerge << ", "
3651                 << NodeID1OfSide2ToMerge << ", "
3652                 << NodeID2OfSide1ToMerge << ", "
3653                 << NodeID2OfSide2ToMerge << ")";
3654
3655   ::SMESH_MeshEditor anEditor( myMesh );
3656   SMESH::SMESH_MeshEditor::Sew_Error error =
3657     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
3658                                          aFirstNode1ToMerge,
3659                                          aFirstNode2ToMerge,
3660                                          aSecondNode1ToMerge,
3661                                          aSecondNode2ToMerge));
3662
3663   storeResult(anEditor);
3664
3665   return error;
3666 }
3667
3668 //================================================================================
3669 /*!
3670  * \brief Set new nodes for given element
3671   * \param ide - element id
3672   * \param newIDs - new node ids
3673   * \retval CORBA::Boolean - true if result is OK
3674  */
3675 //================================================================================
3676
3677 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
3678                                                    const SMESH::long_array& newIDs)
3679 {
3680   initData();
3681
3682   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
3683   if(!elem) return false;
3684
3685   int nbn = newIDs.length();
3686   int i=0;
3687   vector<const SMDS_MeshNode*> aNodes(nbn);
3688   int nbn1=-1;
3689   for(; i<nbn; i++) {
3690     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
3691     if(aNode) {
3692       nbn1++;
3693       aNodes[nbn1] = aNode;
3694     }
3695   }
3696   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
3697                 << ide << ", " << newIDs << " )";
3698 #ifdef _DEBUG_
3699   TPythonDump() << "print 'ChangeElemNodes: ', isDone";
3700 #endif
3701
3702   return GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
3703 }
3704   
3705 //================================================================================
3706 /*!
3707  * \brief Update myLastCreated* or myPreviewData
3708   * \param anEditor - it contains last modification results
3709  */
3710 //================================================================================
3711
3712 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
3713 {
3714   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
3715
3716     list<int> aNodesConnectivity;
3717     typedef map<int, int> TNodesMap;
3718     TNodesMap nodesMap;
3719
3720     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
3721     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
3722
3723     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
3724     int nbEdges = aMeshDS->NbEdges();
3725     int nbFaces = aMeshDS->NbFaces();
3726     int nbVolum = aMeshDS->NbVolumes();
3727     switch ( previewType ) {
3728     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
3729     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
3730     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
3731     default:;
3732     }
3733     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
3734     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
3735     int i = 0, j = 0;
3736     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
3737
3738     while ( itMeshElems->more() ) {
3739       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
3740       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
3741         continue;
3742
3743       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
3744       while ( itElemNodes->more() ) {
3745         const SMDS_MeshNode* aMeshNode = 
3746           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
3747         int aNodeID = aMeshNode->GetID();
3748         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
3749         if ( anIter == nodesMap.end() ) {
3750           // filling the nodes coordinates
3751           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
3752           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
3753           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
3754           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
3755           j++;
3756         }
3757         aNodesConnectivity.push_back(anIter->second);
3758       }
3759
3760       // filling the elements types
3761       SMDSAbs_ElementType aType;
3762       bool isPoly;
3763       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
3764         aType = SMDSAbs_Node;
3765         isPoly = false;
3766       }
3767       else*/ {
3768         aType = aMeshElem->GetType();
3769         isPoly = aMeshElem->IsPoly();
3770       }
3771
3772       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
3773       myPreviewData->elementTypes[i].isPoly = isPoly;
3774       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
3775       i++;
3776
3777     }
3778     myPreviewData->nodesXYZ.length( j );
3779
3780     // filling the elements connectivities
3781     list<int>::iterator aConnIter = aNodesConnectivity.begin();
3782     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
3783     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
3784       myPreviewData->elementConnectivities[i] = *aConnIter;
3785     
3786     return;
3787   }
3788
3789   {
3790     // add new nodes into myLastCreatedNodes
3791     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
3792     myLastCreatedNodes->length(aSeq.Length());
3793     for(int i=0; i<aSeq.Length(); i++)
3794       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
3795   }
3796   {
3797     // add new elements into myLastCreatedElems
3798     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
3799     myLastCreatedElems->length(aSeq.Length());
3800     for(int i=0; i<aSeq.Length(); i++)
3801       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
3802   }
3803 }
3804
3805 //================================================================================
3806 /*!
3807  * Return data of mesh edition preview
3808  */
3809 //================================================================================
3810
3811 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
3812 {
3813   return myPreviewData._retn();
3814 }
3815
3816 //================================================================================
3817 /*!
3818  * \brief Returns list of it's IDs of created nodes
3819   * \retval SMESH::long_array* - list of node ID
3820  */
3821 //================================================================================
3822
3823 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
3824 {
3825   return myLastCreatedNodes._retn();
3826 }
3827
3828 //================================================================================
3829 /*!
3830  * \brief Returns list of it's IDs of created elements
3831   * \retval SMESH::long_array* - list of elements' ID
3832  */
3833 //================================================================================
3834
3835 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
3836 {
3837   return myLastCreatedElems._retn();
3838 }
3839
3840 //=======================================================================
3841 //function : ConvertToQuadratic
3842 //purpose  :
3843 //=======================================================================
3844
3845 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
3846 {
3847   ::SMESH_MeshEditor anEditor( myMesh );
3848   anEditor.ConvertToQuadratic(theForce3d);
3849   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
3850 }
3851
3852 //=======================================================================
3853 //function : ConvertFromQuadratic
3854 //purpose  : 
3855 //=======================================================================
3856
3857 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
3858 {
3859   ::SMESH_MeshEditor anEditor( myMesh );
3860   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
3861   TPythonDump() << this << ".ConvertFromQuadratic()";
3862   return isDone;
3863 }
3864
3865 //=======================================================================
3866 //function : makeMesh
3867 //purpose  : create a named imported mesh 
3868 //=======================================================================
3869
3870 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
3871 {
3872   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
3873   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
3874   SALOMEDS::Study_var study = gen->GetCurrentStudy();
3875   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
3876   gen->SetName( meshSO, theMeshName, "Mesh" );
3877
3878   SALOMEDS::StudyBuilder_var builder = study->NewBuilder();
3879   SALOMEDS::GenericAttribute_var anAttr
3880     = builder->FindOrCreateAttribute( meshSO, "AttributePixMap" );
3881   SALOMEDS::AttributePixMap::_narrow( anAttr )->SetPixMap( "ICON_SMESH_TREE_MESH_IMPORTED" );
3882
3883   return mesh._retn();
3884 }
3885
3886 //=======================================================================
3887 //function : DumpGroupsList
3888 //purpose  :
3889 //=======================================================================
3890 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython, 
3891                                         const SMESH::ListOfGroups * theGroupList)
3892 {
3893   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
3894   if(isDumpGroupList) {
3895     theDumpPython << theGroupList << " = ";
3896   }
3897 }
3898
3899 //================================================================================
3900 /*!
3901   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
3902   \param theNodes - identifiers of nodes to be doubled
3903   \param theModifiedElems - identifiers of elements to be updated by the new (doubled) 
3904          nodes. If list of element identifiers is empty then nodes are doubled but 
3905          they not assigned to elements
3906   \return TRUE if operation has been completed successfully, FALSE otherwise
3907   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
3908 */
3909 //================================================================================
3910
3911 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes, 
3912                                                 const SMESH::long_array& theModifiedElems )
3913 {
3914   initData();
3915
3916   ::SMESH_MeshEditor aMeshEditor( myMesh );
3917   list< int > aListOfNodes;
3918   int i, n;
3919   for ( i = 0, n = theNodes.length(); i < n; i++ )
3920     aListOfNodes.push_back( theNodes[ i ] );
3921
3922   list< int > aListOfElems;
3923   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
3924     aListOfElems.push_back( theModifiedElems[ i ] );
3925
3926   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
3927
3928   storeResult( aMeshEditor) ;
3929
3930   return aResult;
3931 }
3932
3933 //================================================================================
3934 /*!
3935   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
3936   This method provided for convenience works as DoubleNodes() described above.
3937   \param theNodeId - identifier of node to be doubled.
3938   \param theModifiedElems - identifiers of elements to be updated.
3939   \return TRUE if operation has been completed successfully, FALSE otherwise
3940   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
3941 */
3942 //================================================================================
3943
3944 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId, 
3945                                                const SMESH::long_array& theModifiedElems )
3946 {
3947   SMESH::long_array_var aNodes = new SMESH::long_array;
3948   aNodes->length( 1 );
3949   aNodes[ 0 ] = theNodeId;
3950   return DoubleNodes( aNodes, theModifiedElems );
3951 }
3952
3953 //================================================================================
3954 /*!
3955   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
3956   This method provided for convenience works as DoubleNodes() described above.
3957   \param theNodes - group of nodes to be doubled.
3958   \param theModifiedElems - group of elements to be updated.
3959   \return TRUE if operation has been completed successfully, FALSE otherwise
3960   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
3961 */
3962 //================================================================================
3963
3964 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup( 
3965   SMESH::SMESH_GroupBase_ptr theNodes,
3966   SMESH::SMESH_GroupBase_ptr theModifiedElems )
3967 {
3968   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
3969     return false;
3970
3971   SMESH::long_array_var aNodes = theNodes->GetListOfID();
3972   SMESH::long_array_var aModifiedElems;
3973   if ( !CORBA::is_nil( theModifiedElems ) )
3974     aModifiedElems = theModifiedElems->GetListOfID();
3975   else 
3976   {
3977     aModifiedElems = new SMESH::long_array;
3978     aModifiedElems->length( 0 );
3979   }
3980
3981   return DoubleNodes( aNodes, aModifiedElems );
3982 }
3983
3984 //================================================================================
3985 /*!
3986   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
3987   This method provided for convenience works as DoubleNodes() described above.
3988   \param theNodes - list of groups of nodes to be doubled
3989   \param theModifiedElems - list of groups of elements to be updated.
3990   \return TRUE if operation has been completed successfully, FALSE otherwise
3991   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
3992 */
3993 //================================================================================
3994
3995 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups( 
3996   const SMESH::ListOfGroups& theNodes,
3997   const SMESH::ListOfGroups& theModifiedElems )
3998 {
3999   initData();
4000
4001   ::SMESH_MeshEditor aMeshEditor( myMesh );
4002
4003   std::list< int > aNodes;
4004   int i, n, j, m;
4005   for ( i = 0, n = theNodes.length(); i < n; i++ )
4006   {
4007     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
4008     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
4009     {
4010       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4011       for ( j = 0, m = aCurr->length(); j < m; j++ )
4012         aNodes.push_back( aCurr[ j ] );
4013     }
4014   }
4015
4016   std::list< int > anElems;
4017   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4018   {
4019     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
4020     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
4021     {
4022       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4023       for ( j = 0, m = aCurr->length(); j < m; j++ )
4024         anElems.push_back( aCurr[ j ] );
4025     }
4026   }
4027
4028   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
4029
4030   storeResult( aMeshEditor) ;
4031
4032   return aResult;
4033 }