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