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