Salome HOME
Issue 0020755: EDF 1279 MESH : 'Mesh to Pass Through a Point' enhancement
[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 ( myPreviewMode ) // make preview data
3754   {
3755     // in a preview mesh, make edges linked to a node
3756     TPreviewMesh tmpMesh;
3757     TIDSortedElemSet linkedNodes;
3758     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3759     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3760     for ( ; nIt != linkedNodes.end(); ++nIt )
3761     {
3762       SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3763       tmpMesh.Copy( &edge );
3764     }
3765     // move copied node
3766     node = tmpMesh.GetMeshDS()->FindNode( NodeID );
3767     if ( node )
3768       tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3769     // fill preview data
3770     ::SMESH_MeshEditor anEditor( & tmpMesh );
3771     storeResult( anEditor );
3772   }
3773   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3774     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3775   else
3776     GetMeshDS()->MoveNode(node, x, y, z);
3777
3778   if ( !myPreviewMode )
3779   {
3780     // Update Python script
3781     TPythonDump() << "isDone = " << this << ".MoveNode( "
3782                   << NodeID << ", " << x << ", " << y << ", " << z << " )";
3783
3784     myMesh->SetIsModified( true );
3785   }
3786
3787   return true;
3788 }
3789
3790 //================================================================================
3791 /*!
3792  * \brief Return ID of node closest to a given point
3793  */
3794 //================================================================================
3795
3796 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
3797                                                   CORBA::Double y,
3798                                                   CORBA::Double z)
3799 {
3800   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3801
3802   if ( !theNodeSearcher ) {
3803     ::SMESH_MeshEditor anEditor( myMesh );
3804     theNodeSearcher = anEditor.GetNodeSearcher();
3805   }
3806   gp_Pnt p( x,y,z );
3807   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
3808     return node->GetID();
3809
3810   return 0;
3811 }
3812
3813 //================================================================================
3814 /*!
3815  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
3816  * move the node closest to the point to point's location and return ID of the node
3817  */
3818 //================================================================================
3819
3820 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
3821                                                        CORBA::Double y,
3822                                                        CORBA::Double z,
3823                                                        CORBA::Long   theNodeID)
3824 {
3825   // We keep theNodeSearcher until any mesh modification:
3826   // 1) initData() deletes theNodeSearcher at any edition,
3827   // 2) TSearchersDeleter - at any mesh compute event and mesh change
3828
3829   initData(/*deleteSearchers=*/false);
3830
3831   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3832
3833   int nodeID = theNodeID;
3834   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
3835   if ( !node ) // preview moving node
3836   {
3837     if ( !theNodeSearcher ) {
3838       ::SMESH_MeshEditor anEditor( myMesh );
3839       theNodeSearcher = anEditor.GetNodeSearcher();
3840     }
3841     gp_Pnt p( x,y,z );
3842     node = theNodeSearcher->FindClosestTo( p );
3843   }
3844   if ( node ) {
3845     nodeID = node->GetID();
3846     if ( myPreviewMode ) // make preview data
3847     {
3848       // in a preview mesh, make edges linked to a node
3849       TPreviewMesh tmpMesh;
3850       TIDSortedElemSet linkedNodes;
3851       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3852       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3853       for ( ; nIt != linkedNodes.end(); ++nIt )
3854       {
3855         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3856         tmpMesh.Copy( &edge );
3857       }
3858       // move copied node
3859       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
3860       if ( node )
3861         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3862       // fill preview data
3863       ::SMESH_MeshEditor anEditor( & tmpMesh );
3864       storeResult( anEditor );
3865     }
3866     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3867     {
3868       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3869     }
3870     else
3871     {
3872       GetMeshDS()->MoveNode(node, x, y, z);
3873     }
3874   }
3875
3876   if ( !myPreviewMode )
3877   {
3878     TPythonDump() << "nodeID = " << this
3879                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
3880                   << ", " << nodeID << " )";
3881
3882     myMesh->SetIsModified( true );
3883   }
3884
3885   return nodeID;
3886 }
3887
3888 //=======================================================================
3889 /*!
3890  * Return elements of given type where the given point is IN or ON.
3891  *
3892  * 'ALL' type means elements of any type excluding nodes
3893  */
3894 //=======================================================================
3895
3896 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
3897                                                            CORBA::Double      y,
3898                                                            CORBA::Double      z,
3899                                                            SMESH::ElementType type)
3900 {
3901   SMESH::long_array_var res = new SMESH::long_array;
3902   vector< const SMDS_MeshElement* > foundElems;
3903
3904   theSearchersDeleter.Set( myMesh );
3905   if ( !theElementSearcher ) {
3906     ::SMESH_MeshEditor anEditor( myMesh );
3907     theElementSearcher = anEditor.GetElementSearcher();
3908   }
3909   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
3910                                            SMDSAbs_ElementType( type ),
3911                                            foundElems);
3912   res->length( foundElems.size() );
3913   for ( int i = 0; i < foundElems.size(); ++i )
3914     res[i] = foundElems[i]->GetID();
3915
3916   if ( !myPreviewMode ) // call from tui
3917     TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
3918                   << x << ", "
3919                   << y << ", "
3920                   << z << ", "
3921                   << type << " )";
3922
3923   return res._retn();
3924 }
3925
3926 //=======================================================================
3927 //function : GetPointState
3928 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
3929 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
3930 //=======================================================================
3931
3932 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
3933                                                CORBA::Double y,
3934                                                CORBA::Double z)
3935 {
3936   theSearchersDeleter.Set( myMesh );
3937   if ( !theElementSearcher ) {
3938     ::SMESH_MeshEditor anEditor( myMesh );
3939     theElementSearcher = anEditor.GetElementSearcher();
3940   }
3941   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
3942 }
3943
3944 //=======================================================================
3945 //function : convError
3946 //purpose  :
3947 //=======================================================================
3948
3949 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
3950
3951 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
3952 {
3953   switch ( e ) {
3954     RETCASE( SEW_OK );
3955     RETCASE( SEW_BORDER1_NOT_FOUND );
3956     RETCASE( SEW_BORDER2_NOT_FOUND );
3957     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
3958     RETCASE( SEW_BAD_SIDE_NODES );
3959     RETCASE( SEW_VOLUMES_TO_SPLIT );
3960     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
3961     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
3962     RETCASE( SEW_BAD_SIDE1_NODES );
3963     RETCASE( SEW_BAD_SIDE2_NODES );
3964   }
3965   return SMESH::SMESH_MeshEditor::SEW_OK;
3966 }
3967
3968 //=======================================================================
3969 //function : SewFreeBorders
3970 //purpose  :
3971 //=======================================================================
3972
3973 SMESH::SMESH_MeshEditor::Sew_Error
3974 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
3975                                    CORBA::Long SecondNodeID1,
3976                                    CORBA::Long LastNodeID1,
3977                                    CORBA::Long FirstNodeID2,
3978                                    CORBA::Long SecondNodeID2,
3979                                    CORBA::Long LastNodeID2,
3980                                    CORBA::Boolean CreatePolygons,
3981                                    CORBA::Boolean CreatePolyedrs)
3982 {
3983   initData();
3984
3985   SMESHDS_Mesh* aMesh = GetMeshDS();
3986
3987   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
3988   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
3989   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
3990   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
3991   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
3992   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
3993
3994   if (!aBorderFirstNode ||
3995       !aBorderSecondNode||
3996       !aBorderLastNode)
3997     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3998   if (!aSide2FirstNode  ||
3999       !aSide2SecondNode ||
4000       !aSide2ThirdNode)
4001     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4002
4003   TPythonDump() << "error = " << this << ".SewFreeBorders( "
4004                 << FirstNodeID1  << ", "
4005                 << SecondNodeID1 << ", "
4006                 << LastNodeID1   << ", "
4007                 << FirstNodeID2  << ", "
4008                 << SecondNodeID2 << ", "
4009                 << LastNodeID2   << ", "
4010                 << CreatePolygons<< ", "
4011                 << CreatePolyedrs<< " )";
4012
4013   ::SMESH_MeshEditor anEditor( myMesh );
4014   SMESH::SMESH_MeshEditor::Sew_Error error =
4015     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4016                                        aBorderSecondNode,
4017                                        aBorderLastNode,
4018                                        aSide2FirstNode,
4019                                        aSide2SecondNode,
4020                                        aSide2ThirdNode,
4021                                        true,
4022                                        CreatePolygons,
4023                                        CreatePolyedrs) );
4024
4025   storeResult(anEditor);
4026
4027   myMesh->SetIsModified( true );
4028
4029   return error;
4030 }
4031
4032
4033 //=======================================================================
4034 //function : SewConformFreeBorders
4035 //purpose  :
4036 //=======================================================================
4037
4038 SMESH::SMESH_MeshEditor::Sew_Error
4039 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4040                                           CORBA::Long SecondNodeID1,
4041                                           CORBA::Long LastNodeID1,
4042                                           CORBA::Long FirstNodeID2,
4043                                           CORBA::Long SecondNodeID2)
4044 {
4045   initData();
4046
4047   SMESHDS_Mesh* aMesh = GetMeshDS();
4048
4049   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4050   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4051   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4052   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4053   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4054   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4055
4056   if (!aBorderFirstNode ||
4057       !aBorderSecondNode||
4058       !aBorderLastNode )
4059     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4060   if (!aSide2FirstNode  ||
4061       !aSide2SecondNode)
4062     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4063
4064   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4065                 << FirstNodeID1  << ", "
4066                 << SecondNodeID1 << ", "
4067                 << LastNodeID1   << ", "
4068                 << FirstNodeID2  << ", "
4069                 << SecondNodeID2 << " )";
4070
4071   ::SMESH_MeshEditor anEditor( myMesh );
4072   SMESH::SMESH_MeshEditor::Sew_Error error =
4073     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4074                                        aBorderSecondNode,
4075                                        aBorderLastNode,
4076                                        aSide2FirstNode,
4077                                        aSide2SecondNode,
4078                                        aSide2ThirdNode,
4079                                        true,
4080                                        false, false) );
4081
4082   storeResult(anEditor);
4083
4084   myMesh->SetIsModified( true );
4085
4086   return error;
4087 }
4088
4089
4090 //=======================================================================
4091 //function : SewBorderToSide
4092 //purpose  :
4093 //=======================================================================
4094
4095 SMESH::SMESH_MeshEditor::Sew_Error
4096 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4097                                     CORBA::Long SecondNodeIDOnFreeBorder,
4098                                     CORBA::Long LastNodeIDOnFreeBorder,
4099                                     CORBA::Long FirstNodeIDOnSide,
4100                                     CORBA::Long LastNodeIDOnSide,
4101                                     CORBA::Boolean CreatePolygons,
4102                                     CORBA::Boolean CreatePolyedrs)
4103 {
4104   initData();
4105
4106   SMESHDS_Mesh* aMesh = GetMeshDS();
4107
4108   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
4109   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4110   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
4111   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
4112   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
4113   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4114
4115   if (!aBorderFirstNode ||
4116       !aBorderSecondNode||
4117       !aBorderLastNode  )
4118     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4119   if (!aSide2FirstNode  ||
4120       !aSide2SecondNode)
4121     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4122
4123   TPythonDump() << "error = " << this << ".SewBorderToSide( "
4124                 << FirstNodeIDOnFreeBorder  << ", "
4125                 << SecondNodeIDOnFreeBorder << ", "
4126                 << LastNodeIDOnFreeBorder   << ", "
4127                 << FirstNodeIDOnSide        << ", "
4128                 << LastNodeIDOnSide         << ", "
4129                 << CreatePolygons           << ", "
4130                 << CreatePolyedrs           << ") ";
4131
4132   ::SMESH_MeshEditor anEditor( myMesh );
4133   SMESH::SMESH_MeshEditor::Sew_Error error =
4134     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4135                                        aBorderSecondNode,
4136                                        aBorderLastNode,
4137                                        aSide2FirstNode,
4138                                        aSide2SecondNode,
4139                                        aSide2ThirdNode,
4140                                        false,
4141                                        CreatePolygons,
4142                                        CreatePolyedrs) );
4143
4144   storeResult(anEditor);
4145
4146   myMesh->SetIsModified( true );
4147
4148   return error;
4149 }
4150
4151
4152 //=======================================================================
4153 //function : SewSideElements
4154 //purpose  :
4155 //=======================================================================
4156
4157 SMESH::SMESH_MeshEditor::Sew_Error
4158 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4159                                     const SMESH::long_array& IDsOfSide2Elements,
4160                                     CORBA::Long NodeID1OfSide1ToMerge,
4161                                     CORBA::Long NodeID1OfSide2ToMerge,
4162                                     CORBA::Long NodeID2OfSide1ToMerge,
4163                                     CORBA::Long NodeID2OfSide2ToMerge)
4164 {
4165   initData();
4166
4167   SMESHDS_Mesh* aMesh = GetMeshDS();
4168
4169   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
4170   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
4171   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4172   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4173
4174   if (!aFirstNode1ToMerge ||
4175       !aFirstNode2ToMerge )
4176     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4177   if (!aSecondNode1ToMerge||
4178       !aSecondNode2ToMerge)
4179     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4180
4181   TIDSortedElemSet aSide1Elems, aSide2Elems;
4182   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4183   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4184
4185   TPythonDump() << "error = " << this << ".SewSideElements( "
4186                 << IDsOfSide1Elements << ", "
4187                 << IDsOfSide2Elements << ", "
4188                 << NodeID1OfSide1ToMerge << ", "
4189                 << NodeID1OfSide2ToMerge << ", "
4190                 << NodeID2OfSide1ToMerge << ", "
4191                 << NodeID2OfSide2ToMerge << ")";
4192
4193   ::SMESH_MeshEditor anEditor( myMesh );
4194   SMESH::SMESH_MeshEditor::Sew_Error error =
4195     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
4196                                          aFirstNode1ToMerge,
4197                                          aFirstNode2ToMerge,
4198                                          aSecondNode1ToMerge,
4199                                          aSecondNode2ToMerge));
4200
4201   storeResult(anEditor);
4202
4203   myMesh->SetIsModified( true );
4204
4205   return error;
4206 }
4207
4208 //================================================================================
4209 /*!
4210  * \brief Set new nodes for given element
4211  * \param ide - element id
4212  * \param newIDs - new node ids
4213  * \retval CORBA::Boolean - true if result is OK
4214  */
4215 //================================================================================
4216
4217 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4218                                                    const SMESH::long_array& newIDs)
4219 {
4220   initData();
4221
4222   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4223   if(!elem) return false;
4224
4225   int nbn = newIDs.length();
4226   int i=0;
4227   vector<const SMDS_MeshNode*> aNodes(nbn);
4228   int nbn1=-1;
4229   for(; i<nbn; i++) {
4230     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4231     if(aNode) {
4232       nbn1++;
4233       aNodes[nbn1] = aNode;
4234     }
4235   }
4236   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4237                 << ide << ", " << newIDs << " )";
4238
4239   bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4240
4241   if ( res )
4242     myMesh->SetIsModified( true );
4243
4244   return res;
4245 }
4246
4247 //================================================================================
4248 /*!
4249  * \brief Update myLastCreated* or myPreviewData
4250  * \param anEditor - it contains last modification results
4251  */
4252 //================================================================================
4253
4254 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4255 {
4256   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
4257
4258     list<int> aNodesConnectivity;
4259     typedef map<int, int> TNodesMap;
4260     TNodesMap nodesMap;
4261
4262     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4263     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4264
4265     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4266     int nbEdges = aMeshDS->NbEdges();
4267     int nbFaces = aMeshDS->NbFaces();
4268     int nbVolum = aMeshDS->NbVolumes();
4269     switch ( previewType ) {
4270     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4271     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4272     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4273     default:;
4274     }
4275     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4276     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4277     int i = 0, j = 0;
4278     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4279
4280     while ( itMeshElems->more() ) {
4281       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4282       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4283         continue;
4284
4285       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4286       while ( itElemNodes->more() ) {
4287         const SMDS_MeshNode* aMeshNode = 
4288           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4289         int aNodeID = aMeshNode->GetID();
4290         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4291         if ( anIter == nodesMap.end() ) {
4292           // filling the nodes coordinates
4293           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4294           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4295           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4296           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4297           j++;
4298         }
4299         aNodesConnectivity.push_back(anIter->second);
4300       }
4301
4302       // filling the elements types
4303       SMDSAbs_ElementType aType;
4304       bool isPoly;
4305       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4306         aType = SMDSAbs_Node;
4307         isPoly = false;
4308         }
4309         else*/ {
4310         aType = aMeshElem->GetType();
4311         isPoly = aMeshElem->IsPoly();
4312       }
4313
4314       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4315       myPreviewData->elementTypes[i].isPoly = isPoly;
4316       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4317       i++;
4318
4319     }
4320     myPreviewData->nodesXYZ.length( j );
4321
4322     // filling the elements connectivities
4323     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4324     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4325     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4326       myPreviewData->elementConnectivities[i] = *aConnIter;
4327
4328     return;
4329   }
4330
4331   {
4332     // add new nodes into myLastCreatedNodes
4333     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4334     myLastCreatedNodes->length(aSeq.Length());
4335     for(int i=0; i<aSeq.Length(); i++)
4336       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
4337   }
4338   {
4339     // add new elements into myLastCreatedElems
4340     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4341     myLastCreatedElems->length(aSeq.Length());
4342     for(int i=0; i<aSeq.Length(); i++)
4343       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
4344   }
4345 }
4346
4347 //================================================================================
4348 /*!
4349  * Return data of mesh edition preview
4350  */
4351 //================================================================================
4352
4353 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4354 {
4355   return myPreviewData._retn();
4356 }
4357
4358 //================================================================================
4359 /*!
4360  * \brief Returns list of it's IDs of created nodes
4361  * \retval SMESH::long_array* - list of node ID
4362  */
4363 //================================================================================
4364
4365 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4366 {
4367   return myLastCreatedNodes._retn();
4368 }
4369
4370 //================================================================================
4371 /*!
4372  * \brief Returns list of it's IDs of created elements
4373  * \retval SMESH::long_array* - list of elements' ID
4374  */
4375 //================================================================================
4376
4377 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4378 {
4379   return myLastCreatedElems._retn();
4380 }
4381
4382 //=======================================================================
4383 //function : ConvertToQuadratic
4384 //purpose  :
4385 //=======================================================================
4386
4387 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4388 {
4389   ::SMESH_MeshEditor anEditor( myMesh );
4390   anEditor.ConvertToQuadratic(theForce3d);
4391   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4392   myMesh->SetIsModified( true );
4393 }
4394
4395 //=======================================================================
4396 //function : ConvertFromQuadratic
4397 //purpose  : 
4398 //=======================================================================
4399
4400 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4401 {
4402   ::SMESH_MeshEditor anEditor( myMesh );
4403   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
4404   TPythonDump() << this << ".ConvertFromQuadratic()";
4405   if ( isDone )
4406     myMesh->SetIsModified( true );
4407   return isDone;
4408 }
4409
4410 //=======================================================================
4411 //function : makeMesh
4412 //purpose  : create a named imported mesh 
4413 //=======================================================================
4414
4415 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4416 {
4417   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4418   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4419   SALOMEDS::Study_var study = gen->GetCurrentStudy();
4420   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
4421   gen->SetName( meshSO, theMeshName, "Mesh" );
4422   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4423
4424   return mesh._retn();
4425 }
4426
4427 //=======================================================================
4428 //function : DumpGroupsList
4429 //purpose  :
4430 //=======================================================================
4431 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython, 
4432                                         const SMESH::ListOfGroups * theGroupList)
4433 {
4434   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
4435   if(isDumpGroupList) {
4436     theDumpPython << theGroupList << " = ";
4437   }
4438 }
4439
4440 //================================================================================
4441 /*!
4442   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4443   \param theNodes - identifiers of nodes to be doubled
4444   \param theModifiedElems - identifiers of elements to be updated by the new (doubled) 
4445          nodes. If list of element identifiers is empty then nodes are doubled but 
4446          they not assigned to elements
4447   \return TRUE if operation has been completed successfully, FALSE otherwise
4448   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
4449 */
4450 //================================================================================
4451
4452 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes, 
4453                                                 const SMESH::long_array& theModifiedElems )
4454 {
4455   initData();
4456
4457   ::SMESH_MeshEditor aMeshEditor( myMesh );
4458   list< int > aListOfNodes;
4459   int i, n;
4460   for ( i = 0, n = theNodes.length(); i < n; i++ )
4461     aListOfNodes.push_back( theNodes[ i ] );
4462
4463   list< int > aListOfElems;
4464   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4465     aListOfElems.push_back( theModifiedElems[ i ] );
4466
4467   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
4468
4469   storeResult( aMeshEditor) ;
4470   if ( aResult )
4471     myMesh->SetIsModified( true );
4472
4473   return aResult;
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 theNodeId - identifier of node to be doubled.
4481   \param theModifiedElems - identifiers of elements to be updated.
4482   \return TRUE if operation has been completed successfully, FALSE otherwise
4483   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
4484 */
4485 //================================================================================
4486
4487 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId, 
4488                                                const SMESH::long_array& theModifiedElems )
4489 {
4490   SMESH::long_array_var aNodes = new SMESH::long_array;
4491   aNodes->length( 1 );
4492   aNodes[ 0 ] = theNodeId;
4493   bool done = DoubleNodes( aNodes, theModifiedElems );
4494   if ( done )
4495     myMesh->SetIsModified( true );
4496   return done;
4497 }
4498
4499 //================================================================================
4500 /*!
4501   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4502   This method provided for convenience works as DoubleNodes() described above.
4503   \param theNodes - group of nodes to be doubled.
4504   \param theModifiedElems - group of elements to be updated.
4505   \return TRUE if operation has been completed successfully, FALSE otherwise
4506   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
4507 */
4508 //================================================================================
4509
4510 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup( 
4511   SMESH::SMESH_GroupBase_ptr theNodes,
4512   SMESH::SMESH_GroupBase_ptr theModifiedElems )
4513 {
4514   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4515     return false;
4516
4517   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4518   SMESH::long_array_var aModifiedElems;
4519   if ( !CORBA::is_nil( theModifiedElems ) )
4520     aModifiedElems = theModifiedElems->GetListOfID();
4521   else 
4522   {
4523     aModifiedElems = new SMESH::long_array;
4524     aModifiedElems->length( 0 );
4525   }
4526
4527   bool done = DoubleNodes( aNodes, aModifiedElems );
4528
4529   if ( done )
4530     myMesh->SetIsModified( true );
4531
4532   return done;
4533 }
4534
4535 //================================================================================
4536 /*!
4537   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4538   This method provided for convenience works as DoubleNodes() described above.
4539   \param theNodes - list of groups of nodes to be doubled
4540   \param theModifiedElems - list of groups of elements to be updated.
4541   \return TRUE if operation has been completed successfully, FALSE otherwise
4542   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
4543 */
4544 //================================================================================
4545
4546 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups( 
4547   const SMESH::ListOfGroups& theNodes,
4548   const SMESH::ListOfGroups& theModifiedElems )
4549 {
4550   initData();
4551
4552   ::SMESH_MeshEditor aMeshEditor( myMesh );
4553
4554   std::list< int > aNodes;
4555   int i, n, j, m;
4556   for ( i = 0, n = theNodes.length(); i < n; i++ )
4557   {
4558     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
4559     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
4560     {
4561       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4562       for ( j = 0, m = aCurr->length(); j < m; j++ )
4563         aNodes.push_back( aCurr[ j ] );
4564     }
4565   }
4566
4567   std::list< int > anElems;
4568   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4569   {
4570     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
4571     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
4572     {
4573       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4574       for ( j = 0, m = aCurr->length(); j < m; j++ )
4575         anElems.push_back( aCurr[ j ] );
4576     }
4577   }
4578
4579   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
4580
4581   storeResult( aMeshEditor) ;
4582
4583   if ( aResult )
4584     myMesh->SetIsModified( true );
4585
4586   return aResult;
4587 }
4588
4589 //================================================================================
4590 /*!
4591   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4592   \param theElems - the list of elements (edges or faces) to be replicated
4593   The nodes for duplication could be found from these elements
4594   \param theNodesNot - list of nodes to NOT replicate
4595   \param theAffectedElems - the list of elements (cells and edges) to which the 
4596   replicated nodes should be associated to.
4597   \return TRUE if operation has been completed successfully, FALSE otherwise
4598   \sa DoubleNodeGroup(), DoubleNodeGroups()
4599 */
4600 //================================================================================
4601
4602 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems, 
4603                                                    const SMESH::long_array& theNodesNot,
4604                                                    const SMESH::long_array& theAffectedElems )
4605
4606 {
4607   initData();
4608
4609   ::SMESH_MeshEditor aMeshEditor( myMesh );
4610
4611   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4612   TIDSortedElemSet anElems, aNodes, anAffected;
4613   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4614   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4615   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
4616
4617   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4618
4619   storeResult( aMeshEditor) ;
4620
4621   if ( aResult )
4622     myMesh->SetIsModified( true );
4623
4624   // Update Python script
4625   TPythonDump() << "isDone = " << this << ".DoubleNodes( " << theElems << ", "
4626     << theNodesNot << ", " << theAffectedElems << " )";
4627   return aResult;
4628 }
4629
4630 //================================================================================
4631 /*!
4632   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4633   \param theElems - the list of elements (edges or faces) to be replicated
4634   The nodes for duplication could be found from these elements
4635   \param theNodesNot - list of nodes to NOT replicate
4636   \param theShape - shape to detect affected elements (element which geometric center
4637   located on or inside shape).
4638   The replicated nodes should be associated to affected elements.
4639   \return TRUE if operation has been completed successfully, FALSE otherwise
4640   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
4641 */
4642 //================================================================================
4643
4644 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion
4645 ( const SMESH::long_array& theElems, 
4646   const SMESH::long_array& theNodesNot,
4647   GEOM::GEOM_Object_ptr    theShape )
4648
4649 {
4650   initData();
4651
4652   ::SMESH_MeshEditor aMeshEditor( myMesh );
4653
4654   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4655   TIDSortedElemSet anElems, aNodes;
4656   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4657   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4658
4659   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4660   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4661
4662   storeResult( aMeshEditor) ;
4663
4664   if ( aResult )
4665     myMesh->SetIsModified( true );
4666
4667   // Update Python script
4668   TPythonDump() << "isDone = " << this << ".DoubleNodesInRegion( " << theElems << ", "
4669     << theNodesNot << ", " << theShape << " )";
4670   return aResult;
4671 }
4672
4673 //================================================================================
4674 /*!
4675   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4676   \param theElems - group of of elements (edges or faces) to be replicated
4677   \param theNodesNot - group of nodes not to replicated
4678   \param theAffectedElems - group of elements to which the replicated nodes
4679   should be associated to.
4680   \return TRUE if operation has been completed successfully, FALSE otherwise
4681   \sa DoubleNodes(), DoubleNodeGroups()
4682 */
4683 //================================================================================
4684
4685 static void groupToSet(SMESH::SMESH_GroupBase_ptr theGrp,
4686                        SMESHDS_Mesh*              theMeshDS,
4687                        TIDSortedElemSet&          theElemSet,
4688                        const SMDSAbs_ElementType  theType)
4689
4690 {
4691   if ( CORBA::is_nil( theGrp ) )
4692     return;
4693   SMESH::long_array_var anIDs = theGrp->GetIDs();
4694   arrayToSet( anIDs, theMeshDS, theElemSet, theType);
4695 }
4696
4697 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
4698                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
4699                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
4700 {
4701   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4702     return false;
4703
4704   initData();
4705
4706   ::SMESH_MeshEditor aMeshEditor( myMesh );
4707
4708   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4709   TIDSortedElemSet anElems, aNodes, anAffected;
4710   groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4711   groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4712   groupToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
4713
4714   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4715
4716   storeResult( aMeshEditor) ;
4717
4718   if ( aResult )
4719     myMesh->SetIsModified( true );
4720
4721   // Update Python script
4722   TPythonDump() << "isDone = " << this << ".DoubleNodeGroup( " << theElems << ", "
4723     << theNodesNot << ", " << theAffectedElems << " )";
4724   return aResult;
4725 }
4726
4727 //================================================================================
4728 /*!
4729   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4730   \param theElems - group of of elements (edges or faces) to be replicated
4731   \param theNodesNot - group of nodes not to replicated
4732   \param theShape - shape to detect affected elements (element which geometric center
4733   located on or inside shape).
4734   The replicated nodes should be associated to affected elements.
4735   \return TRUE if operation has been completed successfully, FALSE otherwise
4736   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
4737 */
4738 //================================================================================
4739
4740 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion( 
4741                                                                SMESH::SMESH_GroupBase_ptr theElems,
4742                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
4743                                                                GEOM::GEOM_Object_ptr      theShape )
4744
4745 {
4746   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4747     return false;
4748
4749   initData();
4750
4751   ::SMESH_MeshEditor aMeshEditor( myMesh );
4752
4753   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4754   TIDSortedElemSet anElems, aNodes, anAffected;
4755   groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4756   groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4757
4758   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4759   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4760
4761   storeResult( aMeshEditor) ;
4762
4763   if ( aResult )
4764     myMesh->SetIsModified( true );
4765
4766   // Update Python script
4767   TPythonDump() << "isDone = " << this << ".DoubleNodeGroupInRegion( " << theElems << ", "
4768     << theNodesNot << ", " << theShape << " )";
4769   return aResult;
4770 }
4771
4772 //================================================================================
4773 /*!
4774   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4775   This method provided for convenience works as DoubleNodes() described above.
4776   \param theElems - list of groups of elements (edges or faces) to be replicated
4777   \param theNodesNot - list of groups of nodes not to replicated
4778   \param theAffectedElems - group of elements to which the replicated nodes
4779   should be associated to.
4780   \return TRUE if operation has been completed successfully, FALSE otherwise
4781   \sa DoubleNodeGroup(), DoubleNodes()
4782 */
4783 //================================================================================
4784
4785 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
4786                              SMESHDS_Mesh*              theMeshDS,
4787                              TIDSortedElemSet&          theElemSet,
4788                              const bool                 theIsNodeGrp)
4789 {
4790   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
4791   {
4792     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
4793     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE 
4794                                     : aGrp->GetType() != SMESH::NODE ) )
4795     {
4796       SMESH::long_array_var anIDs = aGrp->GetIDs();
4797       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
4798     }
4799   }
4800 }
4801
4802 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
4803                                                         const SMESH::ListOfGroups& theNodesNot,
4804                                                         const SMESH::ListOfGroups& theAffectedElems)
4805 {
4806   initData();
4807
4808   ::SMESH_MeshEditor aMeshEditor( myMesh );
4809
4810   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4811   TIDSortedElemSet anElems, aNodes, anAffected;
4812   listOfGroupToSet(theElems, aMeshDS, anElems, false );
4813   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
4814   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
4815
4816   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4817
4818   storeResult( aMeshEditor) ;
4819
4820   if ( aResult )
4821     myMesh->SetIsModified( true );
4822
4823   // Update Python script
4824   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
4825     << &theNodesNot << ", " << &theAffectedElems << " )";
4826   return aResult;
4827 }
4828
4829 //================================================================================
4830 /*!
4831   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4832   This method provided for convenience works as DoubleNodes() described above.
4833   \param theElems - list of groups of elements (edges or faces) to be replicated
4834   \param theNodesNot - list of groups of nodes not to replicated
4835   \param theShape - shape to detect affected elements (element which geometric center
4836   located on or inside shape).
4837   The replicated nodes should be associated to affected elements.
4838   \return TRUE if operation has been completed successfully, FALSE otherwise
4839   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
4840 */
4841 //================================================================================
4842
4843 CORBA::Boolean
4844 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
4845                                                  const SMESH::ListOfGroups& theNodesNot,
4846                                                  GEOM::GEOM_Object_ptr      theShape )
4847 {
4848   initData();
4849
4850   ::SMESH_MeshEditor aMeshEditor( myMesh );
4851
4852   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4853   TIDSortedElemSet anElems, aNodes;
4854   listOfGroupToSet(theElems, aMeshDS, anElems,false );
4855   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
4856
4857   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4858   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4859
4860   storeResult( aMeshEditor) ;
4861
4862   if ( aResult )
4863     myMesh->SetIsModified( true );
4864
4865   // Update Python script
4866   TPythonDump() << "isDone = " << this << ".DoubleNodeGroupsInRegion( " << &theElems << ", "
4867     << &theNodesNot << ", " << theShape << " )";
4868   return aResult;
4869 }
4870
4871 //================================================================================
4872 /*!
4873   \brief Generated skin mesh (containing 2D cells) from 3D mesh
4874    The created 2D mesh elements based on nodes of free faces of boundary volumes
4875   \return TRUE if operation has been completed successfully, FALSE otherwise
4876 */
4877 //================================================================================
4878
4879 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
4880 {
4881   initData();
4882
4883   ::SMESH_MeshEditor aMeshEditor( myMesh );
4884   bool aResult = aMeshEditor.Make2DMeshFrom3D();
4885   storeResult( aMeshEditor) ;
4886   
4887   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
4888   return aResult;
4889 }