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