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