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