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