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