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