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