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