Salome HOME
+ SMDS_MeshFace* AddPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes,
[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   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
1219   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1220   {
1221     SMESH::NumericalFunctor_i* aNumericalFunctor =
1222       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1223     SMESH::Controls::NumericalFunctorPtr aCrit;
1224     if (aNumericalFunctor)
1225       aCrit = aNumericalFunctor->GetNumericalFunctor();
1226     else
1227       aCrit.reset(new SMESH::Controls::AspectRatio());
1228
1229     ::SMESH_MeshEditor anEditor (myMesh);
1230     return anEditor.BestSplit(quad, aCrit);
1231   }
1232   return -1;
1233 }
1234
1235 //================================================================================
1236 /*!
1237  * \brief Split volumic elements into tetrahedrons
1238  */
1239 //================================================================================
1240
1241 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
1242                                                 CORBA::Short              methodFlags)
1243   throw (SALOME::SALOME_Exception)
1244 {
1245   Unexpect aCatch(SALOME_SalomeException);
1246
1247   SMESH::long_array_var anElementsId = elems->GetIDs();
1248   TIDSortedElemSet elemSet;
1249   arrayToSet( anElementsId, GetMeshDS(), elemSet, SMDSAbs_Volume );
1250   
1251   ::SMESH_MeshEditor anEditor (myMesh);
1252   anEditor.SplitVolumesIntoTetra( elemSet, int( methodFlags ));
1253
1254   storeResult(anEditor);
1255
1256 //   if ( myLastCreatedElems.length() ) - it does not influence Compute()
1257 //     myMesh->SetIsModified( true ); // issue 0020693
1258
1259   TPythonDump() << this << ".SplitVolumesIntoTetra( "
1260                 << elems << ", " << methodFlags << " )";
1261 }
1262
1263 //=======================================================================
1264 //function : Smooth
1265 //purpose  :
1266 //=======================================================================
1267
1268 CORBA::Boolean
1269 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
1270                            const SMESH::long_array &              IDsOfFixedNodes,
1271                            CORBA::Long                            MaxNbOfIterations,
1272                            CORBA::Double                          MaxAspectRatio,
1273                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1274 {
1275   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1276                  MaxAspectRatio, Method, false );
1277 }
1278
1279
1280 //=======================================================================
1281 //function : SmoothParametric
1282 //purpose  :
1283 //=======================================================================
1284
1285 CORBA::Boolean
1286 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
1287                                      const SMESH::long_array &              IDsOfFixedNodes,
1288                                      CORBA::Long                            MaxNbOfIterations,
1289                                      CORBA::Double                          MaxAspectRatio,
1290                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
1291 {
1292   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1293                  MaxAspectRatio, Method, true );
1294 }
1295
1296
1297 //=======================================================================
1298 //function : SmoothObject
1299 //purpose  :
1300 //=======================================================================
1301
1302 CORBA::Boolean
1303 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1304                                  const SMESH::long_array &              IDsOfFixedNodes,
1305                                  CORBA::Long                            MaxNbOfIterations,
1306                                  CORBA::Double                          MaxAspectRatio,
1307                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
1308 {
1309   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1310                        MaxAspectRatio, Method, false);
1311 }
1312
1313
1314 //=======================================================================
1315 //function : SmoothParametricObject
1316 //purpose  :
1317 //=======================================================================
1318
1319 CORBA::Boolean
1320 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
1321                                            const SMESH::long_array &              IDsOfFixedNodes,
1322                                            CORBA::Long                            MaxNbOfIterations,
1323                                            CORBA::Double                          MaxAspectRatio,
1324                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1325 {
1326   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1327                        MaxAspectRatio, Method, true);
1328 }
1329
1330
1331 //=============================================================================
1332 /*!
1333  *
1334  */
1335 //=============================================================================
1336
1337 CORBA::Boolean
1338 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1339                            const SMESH::long_array &              IDsOfFixedNodes,
1340                            CORBA::Long                            MaxNbOfIterations,
1341                            CORBA::Double                          MaxAspectRatio,
1342                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
1343                            bool                                   IsParametric)
1344 {
1345   initData();
1346
1347   SMESHDS_Mesh* aMesh = GetMeshDS();
1348
1349   TIDSortedElemSet elements;
1350   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1351
1352   set<const SMDS_MeshNode*> fixedNodes;
1353   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1354     CORBA::Long index = IDsOfFixedNodes[i];
1355     const SMDS_MeshNode * node = aMesh->FindNode(index);
1356     if ( node )
1357       fixedNodes.insert( node );
1358   }
1359   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1360   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1361     method = ::SMESH_MeshEditor::CENTROIDAL;
1362
1363   ::SMESH_MeshEditor anEditor( myMesh );
1364   anEditor.Smooth(elements, fixedNodes, method,
1365                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1366
1367   myMesh->SetIsModified( true ); // issue 0020693
1368
1369   storeResult(anEditor);
1370
1371   // Update Python script
1372   TPythonDump() << "isDone = " << this << "."
1373                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1374                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1375                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1376                 << "SMESH.SMESH_MeshEditor."
1377                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1378                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1379
1380   return true;
1381 }
1382
1383
1384 //=============================================================================
1385 /*!
1386  *
1387  */
1388 //=============================================================================
1389
1390 CORBA::Boolean
1391 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1392                                  const SMESH::long_array &              IDsOfFixedNodes,
1393                                  CORBA::Long                            MaxNbOfIterations,
1394                                  CORBA::Double                          MaxAspectRatio,
1395                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1396                                  bool                                   IsParametric)
1397 {
1398   initData();
1399
1400   TPythonDump aTPythonDump;  // suppress dump in smooth()
1401
1402   SMESH::long_array_var anElementsId = theObject->GetIDs();
1403   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1404                                   MaxAspectRatio, Method, IsParametric);
1405
1406   // Update Python script
1407   aTPythonDump << "isDone = " << this << "."
1408                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1409                << theObject << ", " << IDsOfFixedNodes << ", "
1410                << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1411                << "SMESH.SMESH_MeshEditor."
1412                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1413                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1414
1415   return isDone;
1416 }
1417
1418
1419 //=============================================================================
1420 /*!
1421  *
1422  */
1423 //=============================================================================
1424
1425 void SMESH_MeshEditor_i::RenumberNodes()
1426 {
1427   // Update Python script
1428   TPythonDump() << this << ".RenumberNodes()";
1429
1430   GetMeshDS()->Renumber( true );
1431 }
1432
1433
1434 //=============================================================================
1435 /*!
1436  *
1437  */
1438 //=============================================================================
1439
1440 void SMESH_MeshEditor_i::RenumberElements()
1441 {
1442   // Update Python script
1443   TPythonDump() << this << ".RenumberElements()";
1444
1445   GetMeshDS()->Renumber( false );
1446 }
1447
1448 //=======================================================================
1449 /*!
1450  * \brief Return groups by their IDs
1451  */
1452 //=======================================================================
1453
1454 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
1455 {
1456   if ( !groupIDs )
1457     return 0;
1458   myMesh_i->CreateGroupServants();
1459   return myMesh_i->GetGroups( *groupIDs );
1460 }
1461
1462 //=======================================================================
1463 //function : rotationSweep
1464 //purpose  : 
1465 //=======================================================================
1466
1467 SMESH::ListOfGroups*
1468 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
1469                                   const SMESH::AxisStruct & theAxis,
1470                                   CORBA::Double             theAngleInRadians,
1471                                   CORBA::Long               theNbOfSteps,
1472                                   CORBA::Double             theTolerance,
1473                                   const bool                theMakeGroups,
1474                                   const SMDSAbs_ElementType theElementType)
1475 {
1476   initData();
1477
1478   TIDSortedElemSet inElements, copyElements;
1479   arrayToSet(theIDsOfElements, GetMeshDS(), inElements, theElementType);
1480
1481   TIDSortedElemSet* workElements = & inElements;
1482   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1483   SMESH_Mesh*       mesh = 0;
1484   bool              makeWalls=true;
1485   if ( myPreviewMode )
1486   {
1487     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1488     tmpMesh.Copy( inElements, copyElements, select, avoid );
1489     mesh = &tmpMesh;
1490     workElements = & copyElements;
1491     //makeWalls = false;
1492   }
1493   else
1494   {
1495     mesh = myMesh;
1496   }
1497
1498   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1499               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1500
1501   ::SMESH_MeshEditor anEditor( mesh );
1502   ::SMESH_MeshEditor::PGroupIDs groupIds =
1503       anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1504                               theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
1505   storeResult(anEditor);
1506
1507   //  myMesh->SetIsModified( true ); -- it does not influence Compute()
1508
1509   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1510 }
1511
1512 //=======================================================================
1513 //function : RotationSweep
1514 //purpose  :
1515 //=======================================================================
1516
1517 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1518                                        const SMESH::AxisStruct & theAxis,
1519                                        CORBA::Double             theAngleInRadians,
1520                                        CORBA::Long               theNbOfSteps,
1521                                        CORBA::Double             theTolerance)
1522 {
1523   if ( !myPreviewMode ) {
1524     TPythonDump() << this << ".RotationSweep( "
1525                   << theIDsOfElements << ", "
1526                   << theAxis << ", "
1527                   << theAngleInRadians << ", "
1528                   << theNbOfSteps << ", "
1529                   << theTolerance << " )";
1530   }
1531   rotationSweep(theIDsOfElements,
1532                 theAxis,
1533                 theAngleInRadians,
1534                 theNbOfSteps,
1535                 theTolerance,
1536                 false);
1537 }
1538
1539 //=======================================================================
1540 //function : RotationSweepMakeGroups
1541 //purpose  : 
1542 //=======================================================================
1543
1544 SMESH::ListOfGroups*
1545 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1546                                             const SMESH::AxisStruct& theAxis,
1547                                             CORBA::Double            theAngleInRadians,
1548                                             CORBA::Long              theNbOfSteps,
1549                                             CORBA::Double            theTolerance)
1550 {
1551   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
1552                                                theAxis,
1553                                                theAngleInRadians,
1554                                                theNbOfSteps,
1555                                                theTolerance,
1556                                                true);
1557   if ( !myPreviewMode ) {
1558     TPythonDump aPythonDump;
1559     DumpGroupsList(aPythonDump,aGroups);
1560     aPythonDump<< this << ".RotationSweepMakeGroups( "
1561                << theIDsOfElements << ", "
1562                << theAxis << ", "
1563                << theAngleInRadians << ", "
1564                << theNbOfSteps << ", "
1565                << theTolerance << " )";
1566   }
1567   return aGroups;
1568 }
1569
1570 //=======================================================================
1571 //function : RotationSweepObject
1572 //purpose  :
1573 //=======================================================================
1574
1575 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1576                                              const SMESH::AxisStruct & theAxis,
1577                                              CORBA::Double             theAngleInRadians,
1578                                              CORBA::Long               theNbOfSteps,
1579                                              CORBA::Double             theTolerance)
1580 {
1581   if ( !myPreviewMode ) {
1582     TPythonDump() << this << ".RotationSweepObject( "
1583                   << theObject << ", "
1584                   << theAxis << ", "
1585                   << theAngleInRadians << ", "
1586                   << theNbOfSteps << ", "
1587                   << theTolerance << " )";
1588   }
1589   SMESH::long_array_var anElementsId = theObject->GetIDs();
1590   rotationSweep(anElementsId,
1591                 theAxis,
1592                 theAngleInRadians,
1593                 theNbOfSteps,
1594                 theTolerance,
1595                 false);
1596 }
1597
1598 //=======================================================================
1599 //function : RotationSweepObject1D
1600 //purpose  :
1601 //=======================================================================
1602
1603 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1604                                                const SMESH::AxisStruct & theAxis,
1605                                                CORBA::Double             theAngleInRadians,
1606                                                CORBA::Long               theNbOfSteps,
1607                                                CORBA::Double             theTolerance)
1608 {
1609   if ( !myPreviewMode ) {
1610     TPythonDump() << this << ".RotationSweepObject1D( "
1611                   << theObject << ", "
1612                   << theAxis << ", "
1613                   << theAngleInRadians << ", "
1614                   << theNbOfSteps << ", "
1615                   << theTolerance << " )";
1616   }
1617   SMESH::long_array_var anElementsId = theObject->GetIDs();
1618   rotationSweep(anElementsId,
1619                 theAxis,
1620                 theAngleInRadians,
1621                 theNbOfSteps,
1622                 theTolerance,
1623                 false,
1624                 SMDSAbs_Edge);
1625 }
1626
1627 //=======================================================================
1628 //function : RotationSweepObject2D
1629 //purpose  :
1630 //=======================================================================
1631
1632 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1633                                                const SMESH::AxisStruct & theAxis,
1634                                                CORBA::Double             theAngleInRadians,
1635                                                CORBA::Long               theNbOfSteps,
1636                                                CORBA::Double             theTolerance)
1637 {
1638   if ( !myPreviewMode ) {
1639     TPythonDump() << this << ".RotationSweepObject2D( "
1640                   << theObject << ", "
1641                   << theAxis << ", "
1642                   << theAngleInRadians << ", "
1643                   << theNbOfSteps << ", "
1644                   << theTolerance << " )";
1645   }
1646   SMESH::long_array_var anElementsId = theObject->GetIDs();
1647   rotationSweep(anElementsId,
1648                 theAxis,
1649                 theAngleInRadians,
1650                 theNbOfSteps,
1651                 theTolerance,
1652                 false,
1653                 SMDSAbs_Face);
1654 }
1655
1656 //=======================================================================
1657 //function : RotationSweepObjectMakeGroups
1658 //purpose  : 
1659 //=======================================================================
1660
1661 SMESH::ListOfGroups*
1662 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1663                                                   const SMESH::AxisStruct&  theAxis,
1664                                                   CORBA::Double             theAngleInRadians,
1665                                                   CORBA::Long               theNbOfSteps,
1666                                                   CORBA::Double             theTolerance)
1667 {
1668   SMESH::long_array_var anElementsId = theObject->GetIDs();
1669   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1670                                                theAxis,
1671                                                theAngleInRadians,
1672                                                theNbOfSteps,
1673                                                theTolerance,
1674                                                true);
1675   if ( !myPreviewMode ) {
1676     TPythonDump aPythonDump;
1677     DumpGroupsList(aPythonDump,aGroups);
1678     aPythonDump<< this << ".RotationSweepObjectMakeGroups( "
1679                << theObject << ", "
1680                << theAxis << ", "
1681                << theAngleInRadians << ", "
1682                << theNbOfSteps << ", "
1683                << theTolerance << " )";
1684   }
1685   return aGroups;
1686 }
1687
1688 //=======================================================================
1689 //function : RotationSweepObject1DMakeGroups
1690 //purpose  : 
1691 //=======================================================================
1692
1693 SMESH::ListOfGroups*
1694 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1695                                                     const SMESH::AxisStruct&  theAxis,
1696                                                     CORBA::Double             theAngleInRadians,
1697                                                     CORBA::Long               theNbOfSteps,
1698                                                     CORBA::Double             theTolerance)
1699 {
1700   SMESH::long_array_var anElementsId = theObject->GetIDs();
1701   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1702                                                theAxis,
1703                                                theAngleInRadians,
1704                                                theNbOfSteps,
1705                                                theTolerance,
1706                                                true,
1707                                                SMDSAbs_Edge);
1708   if ( !myPreviewMode ) {
1709     TPythonDump aPythonDump;
1710     DumpGroupsList(aPythonDump,aGroups);
1711     aPythonDump<< this << ".RotationSweepObject1DMakeGroups( "
1712                << theObject << ", "
1713                << theAxis << ", "
1714                << theAngleInRadians << ", "
1715                << theNbOfSteps << ", "
1716                << theTolerance << " )";
1717   }
1718   return aGroups;
1719 }
1720
1721 //=======================================================================
1722 //function : RotationSweepObject2DMakeGroups
1723 //purpose  : 
1724 //=======================================================================
1725
1726 SMESH::ListOfGroups*
1727 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1728                                                     const SMESH::AxisStruct&  theAxis,
1729                                                     CORBA::Double             theAngleInRadians,
1730                                                     CORBA::Long               theNbOfSteps,
1731                                                     CORBA::Double             theTolerance)
1732 {
1733   SMESH::long_array_var anElementsId = theObject->GetIDs();
1734   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1735                                                theAxis,
1736                                                theAngleInRadians,
1737                                                theNbOfSteps,
1738                                                theTolerance,
1739                                                true,
1740                                                SMDSAbs_Face);
1741   if ( !myPreviewMode ) {
1742     TPythonDump aPythonDump;
1743     DumpGroupsList(aPythonDump,aGroups);
1744     aPythonDump<< this << ".RotationSweepObject2DMakeGroups( "
1745                << theObject << ", "
1746                << theAxis << ", "
1747                << theAngleInRadians << ", "
1748                << theNbOfSteps << ", "
1749                << theTolerance << " )";
1750   }
1751   return aGroups;
1752 }
1753
1754
1755 //=======================================================================
1756 //function : extrusionSweep
1757 //purpose  : 
1758 //=======================================================================
1759
1760 SMESH::ListOfGroups*
1761 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
1762                                    const SMESH::DirStruct &  theStepVector,
1763                                    CORBA::Long               theNbOfSteps,
1764                                    const bool                theMakeGroups,
1765                                    const SMDSAbs_ElementType theElementType)
1766 {
1767   initData();
1768
1769   try {   
1770 #ifdef NO_CAS_CATCH
1771     OCC_CATCH_SIGNALS;
1772 #endif
1773     TIDSortedElemSet elements;
1774     arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
1775
1776     const SMESH::PointStruct * P = &theStepVector.PS;
1777     gp_Vec stepVec( P->x, P->y, P->z );
1778
1779     TElemOfElemListMap aHystory;
1780     ::SMESH_MeshEditor anEditor( myMesh );
1781     ::SMESH_MeshEditor::PGroupIDs groupIds =
1782         anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
1783
1784     storeResult(anEditor);
1785
1786     return theMakeGroups ? getGroups(groupIds.get()) : 0;
1787
1788   } catch(Standard_Failure) {
1789     Handle(Standard_Failure) aFail = Standard_Failure::Caught();          
1790     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1791   }
1792   return 0;
1793 }
1794
1795 //=======================================================================
1796 //function : ExtrusionSweep
1797 //purpose  :
1798 //=======================================================================
1799
1800 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1801                                         const SMESH::DirStruct &  theStepVector,
1802                                         CORBA::Long               theNbOfSteps)
1803 {
1804   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
1805   if ( !myPreviewMode ) {
1806     TPythonDump() << this << ".ExtrusionSweep( "
1807                   << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1808   }
1809 }
1810
1811
1812 //=======================================================================
1813 //function : ExtrusionSweepObject
1814 //purpose  :
1815 //=======================================================================
1816
1817 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1818                                               const SMESH::DirStruct &  theStepVector,
1819                                               CORBA::Long               theNbOfSteps)
1820 {
1821   SMESH::long_array_var anElementsId = theObject->GetIDs();
1822   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
1823   if ( !myPreviewMode ) {
1824     TPythonDump() << this << ".ExtrusionSweepObject( "
1825                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1826   }
1827 }
1828
1829 //=======================================================================
1830 //function : ExtrusionSweepObject1D
1831 //purpose  :
1832 //=======================================================================
1833
1834 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1835                                                 const SMESH::DirStruct &  theStepVector,
1836                                                 CORBA::Long               theNbOfSteps)
1837 {
1838   SMESH::long_array_var anElementsId = theObject->GetIDs();
1839   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
1840   if ( !myPreviewMode ) {
1841     TPythonDump() << this << ".ExtrusionSweepObject1D( "
1842                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1843   }
1844 }
1845
1846 //=======================================================================
1847 //function : ExtrusionSweepObject2D
1848 //purpose  :
1849 //=======================================================================
1850
1851 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1852                                                 const SMESH::DirStruct &  theStepVector,
1853                                                 CORBA::Long               theNbOfSteps)
1854 {
1855   SMESH::long_array_var anElementsId = theObject->GetIDs();
1856   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
1857   if ( !myPreviewMode ) {
1858     TPythonDump() << this << ".ExtrusionSweepObject2D( "
1859                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1860   }
1861 }
1862
1863 //=======================================================================
1864 //function : ExtrusionSweepMakeGroups
1865 //purpose  : 
1866 //=======================================================================
1867
1868 SMESH::ListOfGroups*
1869 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1870                                              const SMESH::DirStruct&  theStepVector,
1871                                              CORBA::Long              theNbOfSteps)
1872 {
1873   SMESH::ListOfGroups* aGroups = extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, true );
1874
1875   if ( !myPreviewMode ) {
1876     TPythonDump aPythonDump;
1877     DumpGroupsList(aPythonDump,aGroups);
1878     aPythonDump  << this << ".ExtrusionSweepMakeGroups( "
1879                  << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1880   }
1881   return aGroups;
1882 }
1883 //=======================================================================
1884 //function : ExtrusionSweepObjectMakeGroups
1885 //purpose  : 
1886 //=======================================================================
1887
1888 SMESH::ListOfGroups*
1889 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1890                                                    const SMESH::DirStruct&   theStepVector,
1891                                                    CORBA::Long               theNbOfSteps)
1892 {
1893   SMESH::long_array_var anElementsId = theObject->GetIDs();
1894   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true );
1895
1896   if ( !myPreviewMode ) {
1897     TPythonDump aPythonDump;
1898     DumpGroupsList(aPythonDump,aGroups);
1899     aPythonDump<< this << ".ExtrusionSweepObjectMakeGroups( "
1900                << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1901   }
1902   return aGroups;
1903 }
1904
1905 //=======================================================================
1906 //function : ExtrusionSweepObject1DMakeGroups
1907 //purpose  : 
1908 //=======================================================================
1909
1910 SMESH::ListOfGroups*
1911 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1912                                                      const SMESH::DirStruct&   theStepVector,
1913                                                      CORBA::Long               theNbOfSteps)
1914 {
1915   SMESH::long_array_var anElementsId = theObject->GetIDs();
1916   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Edge );
1917   if ( !myPreviewMode ) {
1918     TPythonDump aPythonDump;
1919     DumpGroupsList(aPythonDump,aGroups);
1920     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( "
1921                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1922   }
1923   return aGroups;
1924 }
1925
1926 //=======================================================================
1927 //function : ExtrusionSweepObject2DMakeGroups
1928 //purpose  : 
1929 //=======================================================================
1930
1931 SMESH::ListOfGroups*
1932 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1933                                                      const SMESH::DirStruct&   theStepVector,
1934                                                      CORBA::Long               theNbOfSteps)
1935 {
1936   SMESH::long_array_var anElementsId = theObject->GetIDs();
1937   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true, SMDSAbs_Face );
1938   if ( !myPreviewMode ) {
1939     TPythonDump aPythonDump;
1940     DumpGroupsList(aPythonDump,aGroups);
1941     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( "
1942                 << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1943   }
1944   return aGroups;
1945 }
1946
1947
1948 //=======================================================================
1949 //function : advancedExtrusion
1950 //purpose  : 
1951 //=======================================================================
1952
1953 SMESH::ListOfGroups*
1954 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
1955                                       const SMESH::DirStruct &  theStepVector,
1956                                       CORBA::Long               theNbOfSteps,
1957                                       CORBA::Long               theExtrFlags,
1958                                       CORBA::Double             theSewTolerance,
1959                                       const bool                theMakeGroups)
1960 {
1961   initData();
1962
1963   TIDSortedElemSet elements;
1964   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
1965
1966   const SMESH::PointStruct * P = &theStepVector.PS;
1967   gp_Vec stepVec( P->x, P->y, P->z );
1968
1969   ::SMESH_MeshEditor anEditor( myMesh );
1970   TElemOfElemListMap aHystory;
1971   ::SMESH_MeshEditor::PGroupIDs groupIds =
1972       anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
1973                                theMakeGroups, theExtrFlags, theSewTolerance);
1974   storeResult(anEditor);
1975
1976   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1977 }
1978
1979 //=======================================================================
1980 //function : AdvancedExtrusion
1981 //purpose  :
1982 //=======================================================================
1983
1984 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
1985                                            const SMESH::DirStruct &  theStepVector,
1986                                            CORBA::Long               theNbOfSteps,
1987                                            CORBA::Long               theExtrFlags,
1988                                            CORBA::Double             theSewTolerance)
1989 {
1990   if ( !myPreviewMode ) {
1991     TPythonDump() << "stepVector = " << theStepVector;
1992     TPythonDump() << this << ".AdvancedExtrusion("
1993                   << theIDsOfElements
1994                   << ", stepVector, "
1995                   << theNbOfSteps << ","
1996                   << theExtrFlags << ", "
1997                   << theSewTolerance <<  " )";
1998   }
1999   advancedExtrusion( theIDsOfElements,
2000                      theStepVector,
2001                      theNbOfSteps,
2002                      theExtrFlags,
2003                      theSewTolerance,
2004                      false);
2005 }
2006
2007 //=======================================================================
2008 //function : AdvancedExtrusionMakeGroups
2009 //purpose  : 
2010 //=======================================================================
2011
2012 SMESH::ListOfGroups*
2013 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
2014                                                 const SMESH::DirStruct&  theStepVector,
2015                                                 CORBA::Long              theNbOfSteps,
2016                                                 CORBA::Long              theExtrFlags,
2017                                                 CORBA::Double            theSewTolerance)
2018 {
2019   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
2020                                                      theStepVector,
2021                                                      theNbOfSteps,
2022                                                      theExtrFlags,
2023                                                      theSewTolerance,
2024                                                      true);
2025
2026   if ( !myPreviewMode ) {
2027     TPythonDump() << "stepVector = " << theStepVector;
2028     TPythonDump aPythonDump;
2029     DumpGroupsList(aPythonDump,aGroups);
2030     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
2031                 << theIDsOfElements
2032                 << ", stepVector, "
2033                 << theNbOfSteps << ","
2034                 << theExtrFlags << ", "
2035                 << theSewTolerance <<  " )";
2036   }
2037   return aGroups;
2038 }
2039
2040
2041 //================================================================================
2042 /*!
2043  * \brief Convert extrusion error to IDL enum
2044  */
2045 //================================================================================
2046
2047 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2048
2049 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
2050 {
2051   switch ( e ) {
2052     RETCASE( EXTR_OK );
2053     RETCASE( EXTR_NO_ELEMENTS );
2054     RETCASE( EXTR_PATH_NOT_EDGE );
2055     RETCASE( EXTR_BAD_PATH_SHAPE );
2056     RETCASE( EXTR_BAD_STARTING_NODE );
2057     RETCASE( EXTR_BAD_ANGLES_NUMBER );
2058     RETCASE( EXTR_CANT_GET_TANGENT );
2059   }
2060   return SMESH::SMESH_MeshEditor::EXTR_OK;
2061 }
2062
2063
2064 //=======================================================================
2065 //function : extrusionAlongPath
2066 //purpose  : 
2067 //=======================================================================
2068
2069 SMESH::ListOfGroups*
2070 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2071                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2072                                        GEOM::GEOM_Object_ptr       thePathShape,
2073                                        CORBA::Long                 theNodeStart,
2074                                        CORBA::Boolean              theHasAngles,
2075                                        const SMESH::double_array & theAngles,
2076                                        CORBA::Boolean              theHasRefPoint,
2077                                        const SMESH::PointStruct &  theRefPoint,
2078                                        const bool                  theMakeGroups,
2079                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
2080                                        const SMDSAbs_ElementType   theElementType)
2081 {
2082   initData();
2083
2084   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
2085     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2086     return 0;
2087   }
2088   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2089
2090   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2091   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2092
2093   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
2094     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2095     return 0;
2096   }
2097
2098   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2099   if ( !nodeStart ) {
2100     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2101     return 0;
2102   }
2103
2104   TIDSortedElemSet elements;
2105   arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
2106
2107   list<double> angles;
2108   for (int i = 0; i < theAngles.length(); i++) {
2109     angles.push_back( theAngles[i] );
2110   }
2111
2112   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2113
2114   int nbOldGroups = myMesh->NbGroup();
2115
2116   ::SMESH_MeshEditor anEditor( myMesh );
2117   ::SMESH_MeshEditor::Extrusion_Error error =
2118       anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
2119                                     theHasAngles, angles, false,
2120                                     theHasRefPoint, refPnt, theMakeGroups );
2121   storeResult(anEditor);
2122   theError = convExtrError( error );
2123
2124   if ( theMakeGroups ) {
2125     list<int> groupIDs = myMesh->GetGroupIds();
2126     list<int>::iterator newBegin = groupIDs.begin();
2127     std::advance( newBegin, nbOldGroups ); // skip old groups
2128     groupIDs.erase( groupIDs.begin(), newBegin );
2129     return getGroups( & groupIDs );
2130   }
2131   return 0;
2132 }
2133
2134
2135 //=======================================================================
2136 //function : extrusionAlongPathX
2137 //purpose  : 
2138 //=======================================================================
2139
2140 SMESH::ListOfGroups*
2141 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
2142                                         SMESH::SMESH_IDSource_ptr  Path,
2143                                         CORBA::Long                NodeStart,
2144                                         CORBA::Boolean             HasAngles,
2145                                         const SMESH::double_array& Angles,
2146                                         CORBA::Boolean             LinearVariation,
2147                                         CORBA::Boolean             HasRefPoint,
2148                                         const SMESH::PointStruct&  RefPoint,
2149                                         const bool                 MakeGroups,
2150                                         const SMDSAbs_ElementType  ElementType,
2151                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
2152 {
2153   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
2154
2155   initData();
2156
2157   list<double> angles;
2158   for (int i = 0; i < Angles.length(); i++) {
2159     angles.push_back( Angles[i] );
2160   }
2161   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
2162   int nbOldGroups = myMesh->NbGroup();
2163
2164   if ( Path->_is_nil() ) {
2165     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2166     return EmptyGr;
2167   }
2168
2169   TIDSortedElemSet elements;
2170   arrayToSet(IDsOfElements, GetMeshDS(), elements, ElementType);
2171
2172   ::SMESH_MeshEditor anEditor( myMesh );
2173   ::SMESH_MeshEditor::Extrusion_Error error;
2174
2175   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path );
2176   if(aMeshImp) {
2177     // path as mesh
2178     SMDS_MeshNode* aNodeStart = 
2179       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2180     if ( !aNodeStart ) {
2181       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2182       return EmptyGr;
2183     }
2184     error = anEditor.ExtrusionAlongTrack( elements, &(aMeshImp->GetImpl()), aNodeStart,
2185                                           HasAngles, angles, LinearVariation,
2186                                           HasRefPoint, refPnt, MakeGroups );
2187   }
2188   else {
2189     SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path );
2190     if(aSubMeshImp) {
2191       // path as submesh
2192       SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
2193       aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
2194       SMDS_MeshNode* aNodeStart = 
2195         (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2196       if ( !aNodeStart ) {
2197         Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2198         return EmptyGr;
2199       }
2200       SMESH_subMesh* aSubMesh = 
2201         aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
2202       error = anEditor.ExtrusionAlongTrack( elements, aSubMesh, aNodeStart,
2203                                             HasAngles, angles, LinearVariation,
2204                                             HasRefPoint, refPnt, MakeGroups );
2205     }
2206     else {
2207       SMESH_Group_i* aGroupImp = SMESH::DownCast<SMESH_Group_i*>( Path );
2208       if(aGroupImp) {
2209         // path as group of 1D elements
2210       }
2211       else {
2212         // invalid path
2213         Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2214         return EmptyGr;
2215       }
2216     }
2217   }
2218
2219   storeResult(anEditor);
2220   Error = convExtrError( error );
2221
2222   if ( MakeGroups ) {
2223     list<int> groupIDs = myMesh->GetGroupIds();
2224     list<int>::iterator newBegin = groupIDs.begin();
2225     std::advance( newBegin, nbOldGroups ); // skip old groups
2226     groupIDs.erase( groupIDs.begin(), newBegin );
2227     return getGroups( & groupIDs );
2228   }
2229   return EmptyGr;
2230 }
2231
2232
2233 //=======================================================================
2234 //function : ExtrusionAlongPath
2235 //purpose  :
2236 //=======================================================================
2237
2238 SMESH::SMESH_MeshEditor::Extrusion_Error
2239 SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2240                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2241                                        GEOM::GEOM_Object_ptr       thePathShape,
2242                                        CORBA::Long                 theNodeStart,
2243                                        CORBA::Boolean              theHasAngles,
2244                                        const SMESH::double_array & theAngles,
2245                                        CORBA::Boolean              theHasRefPoint,
2246                                        const SMESH::PointStruct &  theRefPoint)
2247 {
2248   if ( !myPreviewMode ) {
2249     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
2250                   << theIDsOfElements << ", "
2251                   << thePathMesh      << ", "
2252                   << thePathShape     << ", "
2253                   << theNodeStart     << ", "
2254                   << theHasAngles     << ", "
2255                   << theAngles        << ", "
2256                   << theHasRefPoint   << ", "
2257                   << "SMESH.PointStruct( "
2258                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2259                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2260                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2261   }
2262   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2263   extrusionAlongPath( theIDsOfElements,
2264                       thePathMesh,
2265                       thePathShape,
2266                       theNodeStart,
2267                       theHasAngles,
2268                       theAngles,
2269                       theHasRefPoint,
2270                       theRefPoint,
2271                       false,
2272                       anError);
2273   return anError;
2274 }
2275
2276 //=======================================================================
2277 //function : ExtrusionAlongPathObject
2278 //purpose  :
2279 //=======================================================================
2280
2281 SMESH::SMESH_MeshEditor::Extrusion_Error
2282 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
2283                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
2284                                              GEOM::GEOM_Object_ptr       thePathShape,
2285                                              CORBA::Long                 theNodeStart,
2286                                              CORBA::Boolean              theHasAngles,
2287                                              const SMESH::double_array & theAngles,
2288                                              CORBA::Boolean              theHasRefPoint,
2289                                              const SMESH::PointStruct &  theRefPoint)
2290 {
2291   if ( !myPreviewMode ) {
2292     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
2293                   << theObject        << ", "
2294                   << thePathMesh      << ", "
2295                   << thePathShape     << ", "
2296                   << theNodeStart     << ", "
2297                   << theHasAngles     << ", "
2298                   << theAngles        << ", "
2299                   << theHasRefPoint   << ", "
2300                   << "SMESH.PointStruct( "
2301                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2302                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2303                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2304   }
2305   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2306   SMESH::long_array_var anElementsId = theObject->GetIDs();
2307   extrusionAlongPath( anElementsId,
2308                       thePathMesh,
2309                       thePathShape,
2310                       theNodeStart,
2311                       theHasAngles,
2312                       theAngles,
2313                       theHasRefPoint,
2314                       theRefPoint,
2315                       false,
2316                       anError);
2317   return anError;
2318 }
2319
2320 //=======================================================================
2321 //function : ExtrusionAlongPathObject1D
2322 //purpose  :
2323 //=======================================================================
2324
2325 SMESH::SMESH_MeshEditor::Extrusion_Error
2326 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
2327                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2328                                                GEOM::GEOM_Object_ptr       thePathShape,
2329                                                CORBA::Long                 theNodeStart,
2330                                                CORBA::Boolean              theHasAngles,
2331                                                const SMESH::double_array & theAngles,
2332                                                CORBA::Boolean              theHasRefPoint,
2333                                                const SMESH::PointStruct &  theRefPoint)
2334 {
2335   if ( !myPreviewMode ) {
2336     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
2337                   << theObject        << ", "
2338                   << thePathMesh      << ", "
2339                   << thePathShape     << ", "
2340                   << theNodeStart     << ", "
2341                   << theHasAngles     << ", "
2342                   << theAngles        << ", "
2343                   << theHasRefPoint   << ", "
2344                   << "SMESH.PointStruct( "
2345                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2346                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2347                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2348   }
2349   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2350   SMESH::long_array_var anElementsId = theObject->GetIDs();
2351   extrusionAlongPath( anElementsId,
2352                       thePathMesh,
2353                       thePathShape,
2354                       theNodeStart,
2355                       theHasAngles,
2356                       theAngles,
2357                       theHasRefPoint,
2358                       theRefPoint,
2359                       false,
2360                       anError,
2361                       SMDSAbs_Edge);
2362   return anError;
2363 }
2364
2365 //=======================================================================
2366 //function : ExtrusionAlongPathObject2D
2367 //purpose  :
2368 //=======================================================================
2369
2370 SMESH::SMESH_MeshEditor::Extrusion_Error
2371 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
2372                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2373                                                GEOM::GEOM_Object_ptr       thePathShape,
2374                                                CORBA::Long                 theNodeStart,
2375                                                CORBA::Boolean              theHasAngles,
2376                                                const SMESH::double_array & theAngles,
2377                                                CORBA::Boolean              theHasRefPoint,
2378                                                const SMESH::PointStruct &  theRefPoint)
2379 {
2380   if ( !myPreviewMode ) {
2381     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
2382                   << theObject        << ", "
2383                   << thePathMesh      << ", "
2384                   << thePathShape     << ", "
2385                   << theNodeStart     << ", "
2386                   << theHasAngles     << ", "
2387                   << theAngles        << ", "
2388                   << theHasRefPoint   << ", "
2389                   << "SMESH.PointStruct( "
2390                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2391                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2392                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2393   }
2394   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2395   SMESH::long_array_var anElementsId = theObject->GetIDs();
2396   extrusionAlongPath( anElementsId,
2397                       thePathMesh,
2398                       thePathShape,
2399                       theNodeStart,
2400                       theHasAngles,
2401                       theAngles,
2402                       theHasRefPoint,
2403                       theRefPoint,
2404                       false,
2405                       anError,
2406                       SMDSAbs_Face);
2407   return anError;
2408 }
2409
2410
2411 //=======================================================================
2412 //function : ExtrusionAlongPathMakeGroups
2413 //purpose  : 
2414 //=======================================================================
2415
2416 SMESH::ListOfGroups*
2417 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
2418                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
2419                                                  GEOM::GEOM_Object_ptr      thePathShape,
2420                                                  CORBA::Long                theNodeStart,
2421                                                  CORBA::Boolean             theHasAngles,
2422                                                  const SMESH::double_array& theAngles,
2423                                                  CORBA::Boolean             theHasRefPoint,
2424                                                  const SMESH::PointStruct&  theRefPoint,
2425                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2426 {
2427   SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
2428                                                        thePathMesh,
2429                                                        thePathShape,
2430                                                        theNodeStart,
2431                                                        theHasAngles,
2432                                                        theAngles,
2433                                                        theHasRefPoint,
2434                                                        theRefPoint,
2435                                                        true,
2436                                                        Error);
2437   if ( !myPreviewMode ) {
2438     bool isDumpGroups = aGroups && aGroups->length() > 0;
2439     TPythonDump aPythonDump;
2440     if(isDumpGroups) {
2441       aPythonDump << "("<<aGroups;
2442     }
2443     if(isDumpGroups)
2444       aPythonDump << ", error)";
2445     else
2446       aPythonDump <<"error";
2447
2448     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
2449                << theIDsOfElements << ", "
2450                << thePathMesh      << ", "
2451                << thePathShape     << ", "
2452                << theNodeStart     << ", "
2453                << theHasAngles     << ", "
2454                << theAngles        << ", "
2455                << theHasRefPoint   << ", "
2456                << "SMESH.PointStruct( "
2457                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2458                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2459                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2460   }
2461   return aGroups;
2462 }
2463
2464 //=======================================================================
2465 //function : ExtrusionAlongPathObjectMakeGroups
2466 //purpose  : 
2467 //=======================================================================
2468
2469 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2470 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2471                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
2472                                    GEOM::GEOM_Object_ptr      thePathShape,
2473                                    CORBA::Long                theNodeStart,
2474                                    CORBA::Boolean             theHasAngles,
2475                                    const SMESH::double_array& theAngles,
2476                                    CORBA::Boolean             theHasRefPoint,
2477                                    const SMESH::PointStruct&  theRefPoint,
2478                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2479 {
2480   SMESH::long_array_var anElementsId = theObject->GetIDs();
2481   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2482                                                       thePathMesh,
2483                                                       thePathShape,
2484                                                       theNodeStart,
2485                                                       theHasAngles,
2486                                                       theAngles,
2487                                                       theHasRefPoint,
2488                                                       theRefPoint,
2489                                                       true,
2490                                                       Error);
2491
2492   if ( !myPreviewMode ) {
2493     bool isDumpGroups = aGroups && aGroups->length() > 0;
2494     TPythonDump aPythonDump;
2495     if(isDumpGroups) {
2496       aPythonDump << "("<<aGroups;
2497     }
2498     if(isDumpGroups)
2499       aPythonDump << ", error)";
2500     else
2501       aPythonDump <<"error";
2502
2503     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
2504                 << theObject << ", "
2505                 << thePathMesh      << ", "
2506                 << thePathShape     << ", "
2507                 << theNodeStart     << ", "
2508                 << theHasAngles     << ", "
2509                 << theAngles        << ", "
2510                 << theHasRefPoint   << ", "
2511                 << "SMESH.PointStruct( "
2512                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2513                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2514                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2515   }
2516   return aGroups;
2517 }
2518
2519 //=======================================================================
2520 //function : ExtrusionAlongPathObject1DMakeGroups
2521 //purpose  : 
2522 //=======================================================================
2523
2524 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2525 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2526                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2527                                      GEOM::GEOM_Object_ptr      thePathShape,
2528                                      CORBA::Long                theNodeStart,
2529                                      CORBA::Boolean             theHasAngles,
2530                                      const SMESH::double_array& theAngles,
2531                                      CORBA::Boolean             theHasRefPoint,
2532                                      const SMESH::PointStruct&  theRefPoint,
2533                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2534 {
2535   SMESH::long_array_var anElementsId = theObject->GetIDs();
2536   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2537                                                       thePathMesh,
2538                                                       thePathShape,
2539                                                       theNodeStart,
2540                                                       theHasAngles,
2541                                                       theAngles,
2542                                                       theHasRefPoint,
2543                                                       theRefPoint,
2544                                                       true,
2545                                                       Error,
2546                                                       SMDSAbs_Edge);
2547
2548   if ( !myPreviewMode ) {
2549     bool isDumpGroups = aGroups && aGroups->length() > 0;
2550     TPythonDump aPythonDump;
2551     if(isDumpGroups) {
2552       aPythonDump << "("<<aGroups;
2553     }
2554     if(isDumpGroups)
2555       aPythonDump << ", error)";
2556     else
2557       aPythonDump <<"error";
2558
2559     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
2560                 << theObject << ", "
2561                 << thePathMesh      << ", "
2562                 << thePathShape     << ", "
2563                 << theNodeStart     << ", "
2564                 << theHasAngles     << ", "
2565                 << theAngles        << ", "
2566                 << theHasRefPoint   << ", "
2567                 << "SMESH.PointStruct( "
2568                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2569                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2570                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2571   }
2572   return aGroups;
2573 }
2574
2575 //=======================================================================
2576 //function : ExtrusionAlongPathObject2DMakeGroups
2577 //purpose  : 
2578 //=======================================================================
2579
2580 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2581 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2582                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2583                                      GEOM::GEOM_Object_ptr      thePathShape,
2584                                      CORBA::Long                theNodeStart,
2585                                      CORBA::Boolean             theHasAngles,
2586                                      const SMESH::double_array& theAngles,
2587                                      CORBA::Boolean             theHasRefPoint,
2588                                      const SMESH::PointStruct&  theRefPoint,
2589                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2590 {
2591   SMESH::long_array_var anElementsId = theObject->GetIDs();
2592   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2593                                                       thePathMesh,
2594                                                       thePathShape,
2595                                                       theNodeStart,
2596                                                       theHasAngles,
2597                                                       theAngles,
2598                                                       theHasRefPoint,
2599                                                       theRefPoint,
2600                                                       true,
2601                                                       Error,
2602                                                       SMDSAbs_Face);
2603
2604   if ( !myPreviewMode ) {
2605     bool isDumpGroups = aGroups && aGroups->length() > 0;
2606     TPythonDump aPythonDump;
2607     if(isDumpGroups) {
2608       aPythonDump << "("<<aGroups;
2609     }
2610     if(isDumpGroups)
2611       aPythonDump << ", error)";
2612     else
2613       aPythonDump <<"error";
2614
2615     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
2616                 << theObject << ", "
2617                 << thePathMesh      << ", "
2618                 << thePathShape     << ", "
2619                 << theNodeStart     << ", "
2620                 << theHasAngles     << ", "
2621                 << theAngles        << ", "
2622                 << theHasRefPoint   << ", "
2623                 << "SMESH.PointStruct( "
2624                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2625                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2626                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2627   }
2628   return aGroups;
2629 }
2630
2631
2632 //=======================================================================
2633 //function : ExtrusionAlongPathObjX
2634 //purpose  : 
2635 //=======================================================================
2636 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2637 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
2638                        SMESH::SMESH_IDSource_ptr  Path,
2639                        CORBA::Long                NodeStart,
2640                        CORBA::Boolean             HasAngles,
2641                        const SMESH::double_array& Angles,
2642                        CORBA::Boolean             LinearVariation,
2643                        CORBA::Boolean             HasRefPoint,
2644                        const SMESH::PointStruct&  RefPoint,
2645                        CORBA::Boolean             MakeGroups,
2646                        SMESH::ElementType         ElemType,
2647                        SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2648 {
2649   SMESH::long_array_var anElementsId = Object->GetIDs();
2650   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
2651                                                       Path,
2652                                                       NodeStart,
2653                                                       HasAngles,
2654                                                       Angles,
2655                                                       LinearVariation,
2656                                                       HasRefPoint,
2657                                                       RefPoint,
2658                                                       MakeGroups,
2659                                                       (SMDSAbs_ElementType)ElemType,
2660                                                       Error);
2661
2662   if ( !myPreviewMode ) {
2663     bool isDumpGroups = aGroups && aGroups->length() > 0;
2664     TPythonDump aPythonDump;
2665     if(isDumpGroups) {
2666       aPythonDump << "("<<aGroups;
2667     }
2668     if(isDumpGroups)
2669       aPythonDump << ", error)";
2670     else
2671       aPythonDump <<"error";
2672
2673     aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
2674                 << Object      << ", "
2675                 << Path        << ", "
2676                 << NodeStart   << ", "
2677                 << HasAngles   << ", "
2678                 << Angles      << ", "
2679                 << LinearVariation << ", "
2680                 << HasRefPoint << ", "
2681                 << "SMESH.PointStruct( "
2682                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2683                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2684                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2685                 << MakeGroups << ", "
2686                 << ElemType << " )";
2687   }
2688   return aGroups;
2689 }
2690
2691
2692 //=======================================================================
2693 //function : ExtrusionAlongPathX
2694 //purpose  : 
2695 //=======================================================================
2696 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2697 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
2698                     SMESH::SMESH_IDSource_ptr  Path,
2699                     CORBA::Long                NodeStart,
2700                     CORBA::Boolean             HasAngles,
2701                     const SMESH::double_array& Angles,
2702                     CORBA::Boolean             LinearVariation,
2703                     CORBA::Boolean             HasRefPoint,
2704                     const SMESH::PointStruct&  RefPoint,
2705                     CORBA::Boolean             MakeGroups,
2706                     SMESH::ElementType         ElemType,
2707                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2708 {
2709   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
2710                                                       Path,
2711                                                       NodeStart,
2712                                                       HasAngles,
2713                                                       Angles,
2714                                                       LinearVariation,
2715                                                       HasRefPoint,
2716                                                       RefPoint,
2717                                                       MakeGroups,
2718                                                       (SMDSAbs_ElementType)ElemType,
2719                                                       Error);
2720
2721   if ( !myPreviewMode ) {
2722     bool isDumpGroups = aGroups && aGroups->length() > 0;
2723     TPythonDump aPythonDump;
2724     if(isDumpGroups) {
2725       aPythonDump << "("<<aGroups;
2726     }
2727     if(isDumpGroups)
2728       aPythonDump << ", error)";
2729     else
2730       aPythonDump <<"error";
2731
2732     aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
2733                 << IDsOfElements << ", "
2734                 << Path        << ", "
2735                 << NodeStart   << ", "
2736                 << HasAngles   << ", "
2737                 << Angles      << ", "
2738                 << LinearVariation << ", "
2739                 << HasRefPoint << ", "
2740                 << "SMESH.PointStruct( "
2741                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2742                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2743                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2744                 << ElemType << " )";
2745   }
2746   return aGroups;
2747 }
2748
2749
2750 //================================================================================
2751 /*!
2752  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2753  * of given angles along path steps
2754  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
2755  *                which proceeds the extrusion
2756  * \param PathShape is shape(edge); as the mesh can be complex, the edge 
2757  *                 is used to define the sub-mesh for the path
2758  */
2759 //================================================================================
2760
2761 SMESH::double_array*
2762 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
2763                                           GEOM::GEOM_Object_ptr       thePathShape,
2764                                           const SMESH::double_array & theAngles)
2765 {
2766   SMESH::double_array_var aResult = new SMESH::double_array();
2767   int nbAngles = theAngles.length();
2768   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2769   {
2770     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2771     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2772     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2773     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2774       return aResult._retn();
2775     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2776     if ( nbSteps == nbAngles )
2777     {
2778       aResult.inout() = theAngles;
2779     }
2780     else
2781     {
2782       aResult->length( nbSteps );
2783       double rAn2St = double( nbAngles ) / double( nbSteps );
2784       double angPrev = 0, angle;
2785       for ( int iSt = 0; iSt < nbSteps; ++iSt )
2786       {
2787         double angCur = rAn2St * ( iSt+1 );
2788         double angCurFloor  = floor( angCur );
2789         double angPrevFloor = floor( angPrev );
2790         if ( angPrevFloor == angCurFloor )
2791           angle = rAn2St * theAngles[ int( angCurFloor ) ];
2792         else
2793         {
2794           int iP = int( angPrevFloor );
2795           double angPrevCeil = ceil(angPrev);
2796           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2797
2798           int iC = int( angCurFloor );
2799           if ( iC < nbAngles )
2800             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2801
2802           iP = int( angPrevCeil );
2803           while ( iC-- > iP )
2804             angle += theAngles[ iC ];
2805         }
2806         aResult[ iSt ] = angle;
2807         angPrev = angCur;
2808       }
2809     }
2810   }
2811   // Update Python script
2812   TPythonDump() << "rotAngles = " << theAngles;
2813   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2814                 << thePathMesh  << ", "
2815                 << thePathShape << ", "
2816                 << "rotAngles )";
2817
2818   return aResult._retn();
2819 }
2820
2821
2822 //=======================================================================
2823 //function : mirror
2824 //purpose  : 
2825 //=======================================================================
2826
2827 SMESH::ListOfGroups*
2828 SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
2829                            const SMESH::AxisStruct &           theAxis,
2830                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2831                            CORBA::Boolean                      theCopy,
2832                            const bool                          theMakeGroups,
2833                            ::SMESH_Mesh*                       theTargetMesh)
2834 {
2835   initData();
2836
2837   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2838   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2839
2840   gp_Trsf aTrsf;
2841   switch ( theMirrorType ) {
2842   case  SMESH::SMESH_MeshEditor::POINT:
2843     aTrsf.SetMirror( P );
2844     break;
2845   case  SMESH::SMESH_MeshEditor::AXIS:
2846     aTrsf.SetMirror( gp_Ax1( P, V ));
2847     break;
2848   default:
2849     aTrsf.SetMirror( gp_Ax2( P, V ));
2850   }
2851
2852   ::SMESH_MeshEditor anEditor( myMesh );
2853   ::SMESH_MeshEditor::PGroupIDs groupIds =
2854       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2855
2856   if(theCopy)
2857     storeResult(anEditor);
2858   else
2859     myMesh->SetIsModified( true );
2860
2861   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2862 }
2863
2864 //=======================================================================
2865 //function : Mirror
2866 //purpose  :
2867 //=======================================================================
2868
2869 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
2870                                 const SMESH::AxisStruct &           theAxis,
2871                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2872                                 CORBA::Boolean                      theCopy)
2873 {
2874   if ( !myPreviewMode ) {
2875     TPythonDump() << this << ".Mirror( "
2876                   << theIDsOfElements << ", "
2877                   << theAxis          << ", "
2878                   << mirrorTypeName(theMirrorType) << ", "
2879                   << theCopy          << " )";
2880   }
2881   if ( theIDsOfElements.length() > 0 )
2882   {
2883     TIDSortedElemSet elements;
2884     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2885     mirror(elements, theAxis, theMirrorType, theCopy, false);
2886   }
2887 }
2888
2889
2890 //=======================================================================
2891 //function : MirrorObject
2892 //purpose  :
2893 //=======================================================================
2894
2895 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
2896                                       const SMESH::AxisStruct &           theAxis,
2897                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2898                                       CORBA::Boolean                      theCopy)
2899 {
2900   if ( !myPreviewMode ) {
2901     TPythonDump() << this << ".MirrorObject( "
2902                   << theObject << ", "
2903                   << theAxis   << ", "
2904                   << mirrorTypeName(theMirrorType) << ", "
2905                   << theCopy   << " )";
2906   }
2907   TIDSortedElemSet elements;
2908   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
2909     mirror(elements, theAxis, theMirrorType, theCopy, false);
2910 }
2911
2912 //=======================================================================
2913 //function : MirrorMakeGroups
2914 //purpose  : 
2915 //=======================================================================
2916
2917 SMESH::ListOfGroups*
2918 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
2919                                      const SMESH::AxisStruct&            theMirror,
2920                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2921 {
2922   SMESH::ListOfGroups * aGroups = 0;
2923   if ( theIDsOfElements.length() > 0 )
2924   {
2925     TIDSortedElemSet elements;
2926     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2927     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
2928   }
2929   if ( !myPreviewMode ) {
2930     TPythonDump aPythonDump;
2931     DumpGroupsList(aPythonDump,aGroups);
2932     aPythonDump << this << ".MirrorMakeGroups( "
2933                 << theIDsOfElements << ", "
2934                 << theMirror << ", "
2935                 << mirrorTypeName(theMirrorType) << " )";
2936   }
2937   return aGroups;
2938 }
2939
2940 //=======================================================================
2941 //function : MirrorObjectMakeGroups
2942 //purpose  : 
2943 //=======================================================================
2944
2945 SMESH::ListOfGroups*
2946 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
2947                                            const SMESH::AxisStruct&            theMirror,
2948                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2949 {
2950   SMESH::ListOfGroups * aGroups = 0;
2951   TIDSortedElemSet elements;
2952   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
2953     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
2954
2955   if ( !myPreviewMode )
2956   {
2957     TPythonDump aPythonDump;
2958     DumpGroupsList(aPythonDump,aGroups);
2959     aPythonDump << this << ".MirrorObjectMakeGroups( "
2960                 << theObject << ", "
2961                 << theMirror << ", "
2962                 << mirrorTypeName(theMirrorType) << " )";
2963   }
2964   return aGroups;
2965 }
2966
2967 //=======================================================================
2968 //function : MirrorMakeMesh
2969 //purpose  : 
2970 //=======================================================================
2971
2972 SMESH::SMESH_Mesh_ptr
2973 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
2974                                    const SMESH::AxisStruct&            theMirror,
2975                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2976                                    CORBA::Boolean                      theCopyGroups,
2977                                    const char*                         theMeshName)
2978 {
2979   SMESH_Mesh_i* mesh_i;
2980   SMESH::SMESH_Mesh_var mesh;
2981   { // open new scope to dump "MakeMesh" command
2982     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2983
2984     TPythonDump pydump; // to prevent dump at mesh creation
2985
2986     mesh = makeMesh( theMeshName );
2987     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2988     if (mesh_i && theIDsOfElements.length() > 0 )
2989     {
2990       TIDSortedElemSet elements;
2991       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2992       mirror(elements, theMirror, theMirrorType,
2993              false, theCopyGroups, & mesh_i->GetImpl());
2994       mesh_i->CreateGroupServants();
2995     }
2996
2997     if ( !myPreviewMode ) {
2998       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
2999              << theIDsOfElements << ", "
3000              << theMirror   << ", "
3001              << mirrorTypeName(theMirrorType) << ", "
3002              << theCopyGroups << ", '"
3003              << theMeshName << "' )";
3004     }
3005   }
3006
3007   //dump "GetGroups"
3008   if(!myPreviewMode && mesh_i)
3009     mesh_i->GetGroups();
3010
3011   return mesh._retn();
3012 }
3013
3014 //=======================================================================
3015 //function : MirrorObjectMakeMesh
3016 //purpose  : 
3017 //=======================================================================
3018
3019 SMESH::SMESH_Mesh_ptr
3020 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
3021                                          const SMESH::AxisStruct&            theMirror,
3022                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3023                                          CORBA::Boolean                      theCopyGroups,
3024                                          const char*                         theMeshName)
3025 {
3026   SMESH_Mesh_i* mesh_i;
3027   SMESH::SMESH_Mesh_var mesh;
3028   { // open new scope to dump "MakeMesh" command
3029     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3030
3031     TPythonDump pydump; // to prevent dump at mesh creation
3032
3033     mesh = makeMesh( theMeshName );
3034     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3035     TIDSortedElemSet elements;
3036     if ( mesh_i &&
3037          idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3038     {
3039       mirror(elements, theMirror, theMirrorType,
3040              false, theCopyGroups, & mesh_i->GetImpl());
3041       mesh_i->CreateGroupServants();
3042     }
3043     if ( !myPreviewMode ) {
3044       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3045              << theObject << ", "
3046              << theMirror   << ", "
3047              << mirrorTypeName(theMirrorType) << ", "
3048              << theCopyGroups << ", '"
3049              << theMeshName << "' )";
3050     }
3051   }
3052
3053   //dump "GetGroups"
3054   if(!myPreviewMode && mesh_i)
3055     mesh_i->GetGroups();
3056
3057   return mesh._retn();
3058 }
3059
3060 //=======================================================================
3061 //function : translate
3062 //purpose  : 
3063 //=======================================================================
3064
3065 SMESH::ListOfGroups*
3066 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
3067                               const SMESH::DirStruct &  theVector,
3068                               CORBA::Boolean            theCopy,
3069                               const bool                theMakeGroups,
3070                               ::SMESH_Mesh*             theTargetMesh)
3071 {
3072   initData();
3073
3074   gp_Trsf aTrsf;
3075   const SMESH::PointStruct * P = &theVector.PS;
3076   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3077
3078   ::SMESH_MeshEditor anEditor( myMesh );
3079   ::SMESH_MeshEditor::PGroupIDs groupIds =
3080       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3081
3082   if(theCopy)
3083     storeResult(anEditor);
3084   else
3085     myMesh->SetIsModified( true );
3086
3087   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3088 }
3089
3090 //=======================================================================
3091 //function : Translate
3092 //purpose  :
3093 //=======================================================================
3094
3095 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3096                                    const SMESH::DirStruct &  theVector,
3097                                    CORBA::Boolean            theCopy)
3098 {
3099   if ( !myPreviewMode ) {
3100     TPythonDump() << this << ".Translate( "
3101                   << theIDsOfElements << ", "
3102                   << theVector << ", "
3103                   << theCopy << " )";
3104   }
3105   if ( theIDsOfElements.length() )
3106   {
3107     TIDSortedElemSet elements;
3108     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3109     translate(elements,theVector,theCopy,false);
3110   }
3111 }
3112
3113 //=======================================================================
3114 //function : TranslateObject
3115 //purpose  :
3116 //=======================================================================
3117
3118 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3119                                          const SMESH::DirStruct &  theVector,
3120                                          CORBA::Boolean            theCopy)
3121 {
3122   if ( !myPreviewMode ) {
3123     TPythonDump() << this << ".TranslateObject( "
3124                   << theObject << ", "
3125                   << theVector << ", "
3126                   << theCopy << " )";
3127   }
3128   TIDSortedElemSet elements;
3129   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3130     translate( elements, theVector, theCopy, false);
3131 }
3132
3133 //=======================================================================
3134 //function : TranslateMakeGroups
3135 //purpose  : 
3136 //=======================================================================
3137
3138 SMESH::ListOfGroups*
3139 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3140                                         const SMESH::DirStruct&  theVector)
3141 {
3142   SMESH::ListOfGroups * aGroups = 0;
3143   if ( theIDsOfElements.length() )
3144   {
3145     TIDSortedElemSet elements;
3146     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3147     aGroups = translate(elements,theVector,true,true);
3148   }
3149   if ( !myPreviewMode ) {
3150     TPythonDump aPythonDump;
3151     DumpGroupsList(aPythonDump,aGroups);
3152     aPythonDump << this << ".TranslateMakeGroups( "
3153                 << theIDsOfElements << ", "
3154                 << theVector << " )";
3155   }
3156   return aGroups;
3157 }
3158
3159 //=======================================================================
3160 //function : TranslateObjectMakeGroups
3161 //purpose  : 
3162 //=======================================================================
3163
3164 SMESH::ListOfGroups*
3165 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3166                                               const SMESH::DirStruct&   theVector)
3167 {
3168   SMESH::ListOfGroups * aGroups = 0;
3169   TIDSortedElemSet elements;
3170   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3171     aGroups = translate(elements, theVector, true, true);
3172
3173   if ( !myPreviewMode ) {
3174
3175     TPythonDump aPythonDump;
3176     DumpGroupsList(aPythonDump,aGroups);
3177     aPythonDump << this << ".TranslateObjectMakeGroups( "
3178                 << theObject << ", "
3179                 << theVector << " )";
3180   }
3181   return aGroups;
3182 }
3183
3184 //=======================================================================
3185 //function : TranslateMakeMesh
3186 //purpose  : 
3187 //=======================================================================
3188
3189 SMESH::SMESH_Mesh_ptr
3190 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3191                                       const SMESH::DirStruct&  theVector,
3192                                       CORBA::Boolean           theCopyGroups,
3193                                       const char*              theMeshName)
3194 {
3195   SMESH_Mesh_i* mesh_i;
3196   SMESH::SMESH_Mesh_var mesh;
3197
3198   { // open new scope to dump "MakeMesh" command
3199     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3200
3201     TPythonDump pydump; // to prevent dump at mesh creation
3202
3203     mesh = makeMesh( theMeshName );
3204     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3205
3206     if ( mesh_i && theIDsOfElements.length() )
3207     {
3208       TIDSortedElemSet elements;
3209       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3210       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3211       mesh_i->CreateGroupServants();
3212     }
3213
3214     if ( !myPreviewMode ) {
3215       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3216              << theIDsOfElements << ", "
3217              << theVector   << ", "
3218              << theCopyGroups << ", '"
3219              << theMeshName << "' )";
3220     }
3221   }
3222
3223   //dump "GetGroups"
3224   if(!myPreviewMode && mesh_i)
3225     mesh_i->GetGroups();
3226
3227   return mesh._retn();
3228 }
3229
3230 //=======================================================================
3231 //function : TranslateObjectMakeMesh
3232 //purpose  : 
3233 //=======================================================================
3234
3235 SMESH::SMESH_Mesh_ptr
3236 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3237                                             const SMESH::DirStruct&   theVector,
3238                                             CORBA::Boolean            theCopyGroups,
3239                                             const char*               theMeshName)
3240 {
3241   SMESH_Mesh_i* mesh_i;
3242   SMESH::SMESH_Mesh_var mesh;
3243   { // open new scope to dump "MakeMesh" command
3244     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3245
3246     TPythonDump pydump; // to prevent dump at mesh creation
3247     mesh = makeMesh( theMeshName );
3248     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3249
3250     TIDSortedElemSet elements;
3251     if ( mesh_i &&
3252       idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3253     {
3254       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3255       mesh_i->CreateGroupServants();
3256     }
3257     if ( !myPreviewMode ) {
3258       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3259              << theObject << ", "
3260              << theVector   << ", "
3261              << theCopyGroups << ", '"
3262              << theMeshName << "' )";
3263     }
3264   }
3265
3266   //dump "GetGroups"
3267   if(!myPreviewMode && mesh_i)
3268     mesh_i->GetGroups();
3269
3270   return mesh._retn();
3271 }
3272
3273 //=======================================================================
3274 //function : rotate
3275 //purpose  : 
3276 //=======================================================================
3277
3278 SMESH::ListOfGroups*
3279 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
3280                            const SMESH::AxisStruct & theAxis,
3281                            CORBA::Double             theAngle,
3282                            CORBA::Boolean            theCopy,
3283                            const bool                theMakeGroups,
3284                            ::SMESH_Mesh*             theTargetMesh)
3285 {
3286   initData();
3287
3288   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3289   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3290
3291   gp_Trsf aTrsf;
3292   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3293
3294   ::SMESH_MeshEditor anEditor( myMesh );
3295   ::SMESH_MeshEditor::PGroupIDs groupIds =
3296       anEditor.Transform (theElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3297
3298   if(theCopy) 
3299     storeResult(anEditor);
3300   else
3301     myMesh->SetIsModified( true );
3302
3303   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3304 }
3305
3306 //=======================================================================
3307 //function : Rotate
3308 //purpose  :
3309 //=======================================================================
3310
3311 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3312                                 const SMESH::AxisStruct & theAxis,
3313                                 CORBA::Double             theAngle,
3314                                 CORBA::Boolean            theCopy)
3315 {
3316   if ( !myPreviewMode ) {
3317     TPythonDump() << this << ".Rotate( "
3318                   << theIDsOfElements << ", "
3319                   << theAxis << ", "
3320                   << theAngle << ", "
3321                   << theCopy << " )";
3322   }
3323   if ( theIDsOfElements.length() > 0 )
3324   {
3325     TIDSortedElemSet elements;
3326     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3327     rotate(elements,theAxis,theAngle,theCopy,false);
3328   }
3329 }
3330
3331 //=======================================================================
3332 //function : RotateObject
3333 //purpose  :
3334 //=======================================================================
3335
3336 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3337                                       const SMESH::AxisStruct & theAxis,
3338                                       CORBA::Double             theAngle,
3339                                       CORBA::Boolean            theCopy)
3340 {
3341   if ( !myPreviewMode ) {
3342     TPythonDump() << this << ".RotateObject( "
3343                   << theObject << ", "
3344                   << theAxis << ", "
3345                   << theAngle << ", "
3346                   << theCopy << " )";
3347   }
3348   TIDSortedElemSet elements;
3349   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3350     rotate(elements,theAxis,theAngle,theCopy,false);
3351 }
3352
3353 //=======================================================================
3354 //function : RotateMakeGroups
3355 //purpose  : 
3356 //=======================================================================
3357
3358 SMESH::ListOfGroups*
3359 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3360                                      const SMESH::AxisStruct& theAxis,
3361                                      CORBA::Double            theAngle)
3362 {
3363   SMESH::ListOfGroups * aGroups = 0;
3364   if ( theIDsOfElements.length() > 0 )
3365   {
3366     TIDSortedElemSet elements;
3367     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3368     aGroups = rotate(elements,theAxis,theAngle,true,true);
3369   }
3370   if ( !myPreviewMode ) {
3371     TPythonDump aPythonDump;
3372     DumpGroupsList(aPythonDump,aGroups);
3373     aPythonDump << this << ".RotateMakeGroups( "
3374                 << theIDsOfElements << ", "
3375                 << theAxis << ", "
3376                 << theAngle << " )";
3377   }
3378   return aGroups;
3379 }
3380
3381 //=======================================================================
3382 //function : RotateObjectMakeGroups
3383 //purpose  : 
3384 //=======================================================================
3385
3386 SMESH::ListOfGroups*
3387 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3388                                            const SMESH::AxisStruct&  theAxis,
3389                                            CORBA::Double             theAngle)
3390 {
3391   SMESH::ListOfGroups * aGroups = 0;
3392   TIDSortedElemSet elements;
3393   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3394     aGroups =  rotate(elements,theAxis,theAngle,true,true);
3395
3396   if ( !myPreviewMode ) {
3397     TPythonDump aPythonDump;
3398     DumpGroupsList(aPythonDump,aGroups);
3399     aPythonDump << this << ".RotateObjectMakeGroups( "
3400                 << theObject << ", "
3401                 << theAxis << ", "
3402                 << theAngle << " )";
3403   }
3404   return aGroups;
3405 }
3406
3407 //=======================================================================
3408 //function : RotateMakeMesh
3409 //purpose  : 
3410 //=======================================================================
3411
3412 SMESH::SMESH_Mesh_ptr 
3413 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3414                                    const SMESH::AxisStruct& theAxis,
3415                                    CORBA::Double            theAngleInRadians,
3416                                    CORBA::Boolean           theCopyGroups,
3417                                    const char*              theMeshName)
3418 {
3419   SMESH::SMESH_Mesh_var mesh;
3420   SMESH_Mesh_i* mesh_i;
3421
3422   { // open new scope to dump "MakeMesh" command
3423     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3424
3425     TPythonDump pydump; // to prevent dump at mesh creation
3426
3427     mesh = makeMesh( theMeshName );
3428     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3429
3430     if ( mesh_i && theIDsOfElements.length() > 0 )
3431     {
3432       TIDSortedElemSet elements;
3433       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3434       rotate(elements, theAxis, theAngleInRadians,
3435              false, theCopyGroups, & mesh_i->GetImpl());
3436       mesh_i->CreateGroupServants();
3437     }
3438     if ( !myPreviewMode ) {
3439       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3440              << theIDsOfElements << ", "
3441              << theAxis << ", "
3442              << theAngleInRadians   << ", "
3443              << theCopyGroups << ", '"
3444              << theMeshName << "' )";
3445     }
3446   }
3447
3448   //dump "GetGroups"
3449   if(!myPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3450     mesh_i->GetGroups();
3451
3452   return mesh._retn();
3453 }
3454
3455 //=======================================================================
3456 //function : RotateObjectMakeMesh
3457 //purpose  : 
3458 //=======================================================================
3459
3460 SMESH::SMESH_Mesh_ptr
3461 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3462                                          const SMESH::AxisStruct&  theAxis,
3463                                          CORBA::Double             theAngleInRadians,
3464                                          CORBA::Boolean            theCopyGroups,
3465                                          const char*               theMeshName)
3466 {
3467   SMESH::SMESH_Mesh_var mesh;
3468   SMESH_Mesh_i* mesh_i;
3469
3470   {// open new scope to dump "MakeMesh" command
3471    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3472
3473     TPythonDump pydump; // to prevent dump at mesh creation
3474     mesh = makeMesh( theMeshName );
3475     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3476
3477     TIDSortedElemSet elements;
3478     if (mesh_i &&
3479         idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3480     {
3481       rotate(elements, theAxis, theAngleInRadians,
3482              false, theCopyGroups, & mesh_i->GetImpl());
3483       mesh_i->CreateGroupServants();
3484     }
3485     if ( !myPreviewMode ) {
3486       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3487              << theObject << ", "
3488              << theAxis << ", "
3489              << theAngleInRadians   << ", "
3490              << theCopyGroups << ", '"
3491              << theMeshName << "' )";
3492     }
3493   }
3494
3495   //dump "GetGroups"
3496   if(!myPreviewMode && mesh_i)
3497     mesh_i->GetGroups();
3498
3499   return mesh._retn();
3500 }
3501
3502 //=======================================================================
3503 //function : scale
3504 //purpose  : 
3505 //=======================================================================
3506
3507 SMESH::ListOfGroups*
3508 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
3509                           const SMESH::PointStruct&  thePoint,
3510                           const SMESH::double_array& theScaleFact,
3511                           CORBA::Boolean             theCopy,
3512                           const bool                 theMakeGroups,
3513                           ::SMESH_Mesh*              theTargetMesh)
3514 {
3515   initData();
3516   if ( theScaleFact.length() < 1 )
3517     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3518   if ( theScaleFact.length() == 2 )
3519     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3520
3521   TIDSortedElemSet elements;
3522   if ( !idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/true))
3523     return 0;
3524
3525   vector<double> S(3);
3526   S[0] = theScaleFact[0];
3527   S[1] = (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1];
3528   S[2] = (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2];
3529   double tol = std::numeric_limits<double>::max();
3530   gp_Trsf aTrsf;
3531   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
3532                    0,    S[1], 0,    thePoint.y * (1-S[1]),
3533                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
3534
3535   ::SMESH_MeshEditor anEditor( myMesh );
3536   ::SMESH_MeshEditor::PGroupIDs groupIds =
3537       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3538
3539   if(theCopy)
3540     storeResult(anEditor);
3541   else
3542     myMesh->SetIsModified( true );
3543
3544   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3545 }
3546
3547 //=======================================================================
3548 //function : Scale
3549 //purpose  :
3550 //=======================================================================
3551
3552 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
3553                                const SMESH::PointStruct&  thePoint,
3554                                const SMESH::double_array& theScaleFact,
3555                                CORBA::Boolean             theCopy)
3556 {
3557   if ( !myPreviewMode ) {
3558     TPythonDump() << this << ".Scale( "
3559                   << theObject << ", "
3560                   << "SMESH.PointStruct( "  << thePoint.x << ", "
3561                   << thePoint.y << ", " << thePoint.z << " ) ,"
3562                   << theScaleFact << ", "
3563                   << theCopy << " )";
3564   }
3565   scale(theObject, thePoint, theScaleFact, theCopy, false);
3566 }
3567
3568
3569 //=======================================================================
3570 //function : ScaleMakeGroups
3571 //purpose  : 
3572 //=======================================================================
3573
3574 SMESH::ListOfGroups*
3575 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3576                                     const SMESH::PointStruct&  thePoint,
3577                                     const SMESH::double_array& theScaleFact)
3578 {
3579   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3580   if ( !myPreviewMode ) {
3581
3582     TPythonDump aPythonDump;
3583     DumpGroupsList(aPythonDump,aGroups);
3584     aPythonDump << this << ".Scale("
3585                 << theObject << ","
3586                 << "SMESH.PointStruct(" <<thePoint.x << ","
3587                 << thePoint.y << "," << thePoint.z << "),"
3588                 << theScaleFact << ",True,True)";
3589   }
3590   return aGroups;
3591 }
3592
3593
3594 //=======================================================================
3595 //function : ScaleMakeMesh
3596 //purpose  : 
3597 //=======================================================================
3598
3599 SMESH::SMESH_Mesh_ptr
3600 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
3601                                   const SMESH::PointStruct&  thePoint,
3602                                   const SMESH::double_array& theScaleFact,
3603                                   CORBA::Boolean             theCopyGroups,
3604                                   const char*                theMeshName)
3605 {
3606   SMESH_Mesh_i* mesh_i;
3607   SMESH::SMESH_Mesh_var mesh;
3608   { // open new scope to dump "MakeMesh" command
3609     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3610
3611     TPythonDump pydump; // to prevent dump at mesh creation
3612     mesh = makeMesh( theMeshName );
3613     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3614
3615     if ( mesh_i )
3616     {
3617       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3618       mesh_i->CreateGroupServants();
3619     }
3620     if ( !myPreviewMode )
3621       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3622              << theObject << ", "
3623              << "SMESH.PointStruct( "  << thePoint.x << ", "
3624              << thePoint.y << ", " << thePoint.z << " ) ,"
3625              << theScaleFact << ", "
3626              << theCopyGroups << ", '"
3627              << theMeshName << "' )";
3628   }
3629
3630   //dump "GetGroups"
3631   if(!myPreviewMode && mesh_i)
3632     mesh_i->GetGroups();
3633
3634   return mesh._retn();
3635 }
3636
3637
3638 //=======================================================================
3639 //function : FindCoincidentNodes
3640 //purpose  :
3641 //=======================================================================
3642
3643 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
3644                                               SMESH::array_of_long_array_out GroupsOfNodes)
3645 {
3646   initData();
3647
3648   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3649   ::SMESH_MeshEditor anEditor( myMesh );
3650   TIDSortedNodeSet nodes; // no input nodes
3651   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3652
3653   GroupsOfNodes = new SMESH::array_of_long_array;
3654   GroupsOfNodes->length( aListOfListOfNodes.size() );
3655   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3656   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3657     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3658     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3659     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3660     aGroup.length( aListOfNodes.size() );
3661     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3662       aGroup[ j ] = (*lIt)->GetID();
3663   }
3664   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3665                 << Tolerance << " )";
3666 }
3667
3668 //=======================================================================
3669 //function : FindCoincidentNodesOnPart
3670 //purpose  :
3671 //=======================================================================
3672 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
3673                                                    CORBA::Double                  Tolerance,
3674                                                    SMESH::array_of_long_array_out GroupsOfNodes)
3675 {
3676   initData();
3677
3678   TIDSortedNodeSet nodes;
3679   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3680
3681   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3682   ::SMESH_MeshEditor anEditor( myMesh );
3683   if(!nodes.empty())
3684     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3685
3686   GroupsOfNodes = new SMESH::array_of_long_array;
3687   GroupsOfNodes->length( aListOfListOfNodes.size() );
3688   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3689   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3690   {
3691     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3692     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3693     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3694     aGroup.length( aListOfNodes.size() );
3695     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3696       aGroup[ j ] = (*lIt)->GetID();
3697   }
3698   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3699                 <<theObject<<", "
3700                 << Tolerance << " )";
3701 }
3702
3703 //================================================================================
3704 /*!
3705  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3706  *        ExceptSubMeshOrGroups
3707  */
3708 //================================================================================
3709
3710 void SMESH_MeshEditor_i::
3711 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
3712                              CORBA::Double                  theTolerance,
3713                              SMESH::array_of_long_array_out theGroupsOfNodes,
3714                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
3715 {
3716   initData();
3717
3718   TIDSortedNodeSet nodes;
3719   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3720
3721   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3722   {
3723     TIDSortedNodeSet exceptNodes;
3724     idSourceToNodeSet( theExceptSubMeshOrGroups[i], GetMeshDS(), exceptNodes );
3725     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3726     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3727       nodes.erase( *avoidNode );
3728   }
3729   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3730   ::SMESH_MeshEditor anEditor( myMesh );
3731   if(!nodes.empty())
3732     anEditor.FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3733
3734   theGroupsOfNodes = new SMESH::array_of_long_array;
3735   theGroupsOfNodes->length( aListOfListOfNodes.size() );
3736   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3737   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3738   {
3739     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3740     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3741     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
3742     aGroup.length( aListOfNodes.size() );
3743     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3744       aGroup[ j ] = (*lIt)->GetID();
3745   }
3746   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
3747                 << theObject<<", "
3748                 << theTolerance << ", "
3749                 << theExceptSubMeshOrGroups << " )";
3750 }
3751
3752 //=======================================================================
3753 //function : MergeNodes
3754 //purpose  :
3755 //=======================================================================
3756
3757 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
3758 {
3759   initData();
3760
3761   SMESHDS_Mesh* aMesh = GetMeshDS();
3762
3763   TPythonDump aTPythonDump;
3764   aTPythonDump << this << ".MergeNodes([";
3765   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3766   for (int i = 0; i < GroupsOfNodes.length(); i++)
3767   {
3768     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
3769     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
3770     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
3771     for ( int j = 0; j < aNodeGroup.length(); j++ )
3772     {
3773       CORBA::Long index = aNodeGroup[ j ];
3774       const SMDS_MeshNode * node = aMesh->FindNode(index);
3775       if ( node )
3776         aListOfNodes.push_back( node );
3777     }
3778     if ( aListOfNodes.size() < 2 )
3779       aListOfListOfNodes.pop_back();
3780
3781     if ( i > 0 ) aTPythonDump << ", ";
3782     aTPythonDump << aNodeGroup;
3783   }
3784   ::SMESH_MeshEditor anEditor( myMesh );
3785   anEditor.MergeNodes( aListOfListOfNodes );
3786
3787   aTPythonDump <<  "])";
3788
3789   myMesh->SetIsModified( true );
3790 }
3791
3792 //=======================================================================
3793 //function : FindEqualElements
3794 //purpose  :
3795 //=======================================================================
3796 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
3797                                            SMESH::array_of_long_array_out GroupsOfElementsID)
3798 {
3799   initData();
3800
3801   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
3802   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
3803   {
3804     typedef list<int> TListOfIDs;
3805     set<const SMDS_MeshElement*> elems;
3806     SMESH::long_array_var aElementsId = theObject->GetIDs();
3807     SMESHDS_Mesh* aMesh = GetMeshDS();
3808
3809     for(int i = 0; i < aElementsId->length(); i++) {
3810       CORBA::Long anID = aElementsId[i];
3811       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
3812       if (elem) {
3813         elems.insert(elem);
3814       }
3815     }
3816
3817     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3818     ::SMESH_MeshEditor anEditor( myMesh );
3819     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
3820
3821     GroupsOfElementsID = new SMESH::array_of_long_array;
3822     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
3823
3824     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
3825     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
3826       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
3827       TListOfIDs& listOfIDs = *arraysIt;
3828       aGroup.length( listOfIDs.size() );
3829       TListOfIDs::iterator idIt = listOfIDs.begin();
3830       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
3831         aGroup[ k ] = *idIt;
3832       }
3833     }
3834
3835     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
3836                   <<theObject<<" )";
3837   }
3838 }
3839
3840 //=======================================================================
3841 //function : MergeElements
3842 //purpose  :
3843 //=======================================================================
3844
3845 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
3846 {
3847   initData();
3848
3849   TPythonDump aTPythonDump;
3850   aTPythonDump << this << ".MergeElements( [";
3851
3852   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3853
3854   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
3855     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
3856     aListOfListOfElementsID.push_back( list< int >() );
3857     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
3858     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
3859       CORBA::Long id = anElemsIDGroup[ j ];
3860       aListOfElemsID.push_back( id );
3861     }
3862     if ( aListOfElemsID.size() < 2 )
3863       aListOfListOfElementsID.pop_back();
3864     if ( i > 0 ) aTPythonDump << ", ";
3865     aTPythonDump << anElemsIDGroup;
3866   }
3867
3868   ::SMESH_MeshEditor anEditor( myMesh );
3869   anEditor.MergeElements(aListOfListOfElementsID);
3870
3871   myMesh->SetIsModified( true );
3872
3873   aTPythonDump << "] )";
3874 }
3875
3876 //=======================================================================
3877 //function : MergeEqualElements
3878 //purpose  :
3879 //=======================================================================
3880
3881 void SMESH_MeshEditor_i::MergeEqualElements()
3882 {
3883   initData();
3884
3885   ::SMESH_MeshEditor anEditor( myMesh );
3886   anEditor.MergeEqualElements();
3887
3888   TPythonDump() << this << ".MergeEqualElements()";
3889 }
3890
3891 //=============================================================================
3892 /*!
3893  * Move the node to a given point
3894  */
3895 //=============================================================================
3896
3897 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
3898                                             CORBA::Double x,
3899                                             CORBA::Double y,
3900                                             CORBA::Double z)
3901 {
3902   initData(/*deleteSearchers=*/false);
3903
3904   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
3905   if ( !node )
3906     return false;
3907
3908   if ( theNodeSearcher )
3909     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3910
3911   if ( myPreviewMode ) // make preview data
3912   {
3913     // in a preview mesh, make edges linked to a node
3914     TPreviewMesh tmpMesh;
3915     TIDSortedElemSet linkedNodes;
3916     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3917     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3918     for ( ; nIt != linkedNodes.end(); ++nIt )
3919     {
3920       SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3921       tmpMesh.Copy( &edge );
3922     }
3923     // move copied node
3924     node = tmpMesh.GetMeshDS()->FindNode( NodeID );
3925     if ( node )
3926       tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3927     // fill preview data
3928     ::SMESH_MeshEditor anEditor( & tmpMesh );
3929     storeResult( anEditor );
3930   }
3931   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3932     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3933   else
3934     GetMeshDS()->MoveNode(node, x, y, z);
3935
3936   if ( !myPreviewMode )
3937   {
3938     // Update Python script
3939     TPythonDump() << "isDone = " << this << ".MoveNode( "
3940                   << NodeID << ", " << x << ", " << y << ", " << z << " )";
3941
3942     myMesh->SetIsModified( true );
3943   }
3944
3945   return true;
3946 }
3947
3948 //================================================================================
3949 /*!
3950  * \brief Return ID of node closest to a given point
3951  */
3952 //================================================================================
3953
3954 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
3955                                                   CORBA::Double y,
3956                                                   CORBA::Double z)
3957 {
3958   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3959
3960   if ( !theNodeSearcher ) {
3961     ::SMESH_MeshEditor anEditor( myMesh );
3962     theNodeSearcher = anEditor.GetNodeSearcher();
3963   }
3964   gp_Pnt p( x,y,z );
3965   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
3966     return node->GetID();
3967
3968   return 0;
3969 }
3970
3971 //================================================================================
3972 /*!
3973  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
3974  * move the node closest to the point to point's location and return ID of the node
3975  */
3976 //================================================================================
3977
3978 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
3979                                                        CORBA::Double y,
3980                                                        CORBA::Double z,
3981                                                        CORBA::Long   theNodeID)
3982 {
3983   // We keep theNodeSearcher until any mesh modification:
3984   // 1) initData() deletes theNodeSearcher at any edition,
3985   // 2) TSearchersDeleter - at any mesh compute event and mesh change
3986
3987   initData(/*deleteSearchers=*/false);
3988
3989   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3990
3991   int nodeID = theNodeID;
3992   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
3993   if ( !node ) // preview moving node
3994   {
3995     if ( !theNodeSearcher ) {
3996       ::SMESH_MeshEditor anEditor( myMesh );
3997       theNodeSearcher = anEditor.GetNodeSearcher();
3998     }
3999     gp_Pnt p( x,y,z );
4000     node = theNodeSearcher->FindClosestTo( p );
4001   }
4002   if ( node ) {
4003     nodeID = node->GetID();
4004     if ( myPreviewMode ) // make preview data
4005     {
4006       // in a preview mesh, make edges linked to a node
4007       TPreviewMesh tmpMesh;
4008       TIDSortedElemSet linkedNodes;
4009       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4010       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4011       for ( ; nIt != linkedNodes.end(); ++nIt )
4012       {
4013         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
4014         tmpMesh.Copy( &edge );
4015       }
4016       // move copied node
4017       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4018       if ( node )
4019         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4020       // fill preview data
4021       ::SMESH_MeshEditor anEditor( & tmpMesh );
4022       storeResult( anEditor );
4023     }
4024     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4025     {
4026       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4027     }
4028     else
4029     {
4030       GetMeshDS()->MoveNode(node, x, y, z);
4031     }
4032   }
4033
4034   if ( !myPreviewMode )
4035   {
4036     TPythonDump() << "nodeID = " << this
4037                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4038                   << ", " << nodeID << " )";
4039
4040     myMesh->SetIsModified( true );
4041   }
4042
4043   return nodeID;
4044 }
4045
4046 //=======================================================================
4047 /*!
4048  * Return elements of given type where the given point is IN or ON.
4049  *
4050  * 'ALL' type means elements of any type excluding nodes
4051  */
4052 //=======================================================================
4053
4054 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
4055                                                            CORBA::Double      y,
4056                                                            CORBA::Double      z,
4057                                                            SMESH::ElementType type)
4058 {
4059   SMESH::long_array_var res = new SMESH::long_array;
4060   vector< const SMDS_MeshElement* > foundElems;
4061
4062   theSearchersDeleter.Set( myMesh );
4063   if ( !theElementSearcher ) {
4064     ::SMESH_MeshEditor anEditor( myMesh );
4065     theElementSearcher = anEditor.GetElementSearcher();
4066   }
4067   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4068                                            SMDSAbs_ElementType( type ),
4069                                            foundElems);
4070   res->length( foundElems.size() );
4071   for ( int i = 0; i < foundElems.size(); ++i )
4072     res[i] = foundElems[i]->GetID();
4073
4074   if ( !myPreviewMode ) // call from tui
4075     TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
4076                   << x << ", "
4077                   << y << ", "
4078                   << z << ", "
4079                   << type << " )";
4080
4081   return res._retn();
4082 }
4083
4084 //=======================================================================
4085 //function : GetPointState
4086 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4087 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4088 //=======================================================================
4089
4090 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4091                                                CORBA::Double y,
4092                                                CORBA::Double z)
4093 {
4094   theSearchersDeleter.Set( myMesh );
4095   if ( !theElementSearcher ) {
4096     ::SMESH_MeshEditor anEditor( myMesh );
4097     theElementSearcher = anEditor.GetElementSearcher();
4098   }
4099   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4100 }
4101
4102 //=======================================================================
4103 //function : convError
4104 //purpose  :
4105 //=======================================================================
4106
4107 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4108
4109 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4110 {
4111   switch ( e ) {
4112     RETCASE( SEW_OK );
4113     RETCASE( SEW_BORDER1_NOT_FOUND );
4114     RETCASE( SEW_BORDER2_NOT_FOUND );
4115     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4116     RETCASE( SEW_BAD_SIDE_NODES );
4117     RETCASE( SEW_VOLUMES_TO_SPLIT );
4118     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4119     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4120     RETCASE( SEW_BAD_SIDE1_NODES );
4121     RETCASE( SEW_BAD_SIDE2_NODES );
4122   }
4123   return SMESH::SMESH_MeshEditor::SEW_OK;
4124 }
4125
4126 //=======================================================================
4127 //function : SewFreeBorders
4128 //purpose  :
4129 //=======================================================================
4130
4131 SMESH::SMESH_MeshEditor::Sew_Error
4132 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4133                                    CORBA::Long SecondNodeID1,
4134                                    CORBA::Long LastNodeID1,
4135                                    CORBA::Long FirstNodeID2,
4136                                    CORBA::Long SecondNodeID2,
4137                                    CORBA::Long LastNodeID2,
4138                                    CORBA::Boolean CreatePolygons,
4139                                    CORBA::Boolean CreatePolyedrs)
4140 {
4141   initData();
4142
4143   SMESHDS_Mesh* aMesh = GetMeshDS();
4144
4145   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4146   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4147   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4148   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4149   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4150   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
4151
4152   if (!aBorderFirstNode ||
4153       !aBorderSecondNode||
4154       !aBorderLastNode)
4155     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4156   if (!aSide2FirstNode  ||
4157       !aSide2SecondNode ||
4158       !aSide2ThirdNode)
4159     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4160
4161   TPythonDump() << "error = " << this << ".SewFreeBorders( "
4162                 << FirstNodeID1  << ", "
4163                 << SecondNodeID1 << ", "
4164                 << LastNodeID1   << ", "
4165                 << FirstNodeID2  << ", "
4166                 << SecondNodeID2 << ", "
4167                 << LastNodeID2   << ", "
4168                 << CreatePolygons<< ", "
4169                 << CreatePolyedrs<< " )";
4170
4171   ::SMESH_MeshEditor anEditor( myMesh );
4172   SMESH::SMESH_MeshEditor::Sew_Error error =
4173     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4174                                        aBorderSecondNode,
4175                                        aBorderLastNode,
4176                                        aSide2FirstNode,
4177                                        aSide2SecondNode,
4178                                        aSide2ThirdNode,
4179                                        true,
4180                                        CreatePolygons,
4181                                        CreatePolyedrs) );
4182
4183   storeResult(anEditor);
4184
4185   myMesh->SetIsModified( true );
4186
4187   return error;
4188 }
4189
4190
4191 //=======================================================================
4192 //function : SewConformFreeBorders
4193 //purpose  :
4194 //=======================================================================
4195
4196 SMESH::SMESH_MeshEditor::Sew_Error
4197 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4198                                           CORBA::Long SecondNodeID1,
4199                                           CORBA::Long LastNodeID1,
4200                                           CORBA::Long FirstNodeID2,
4201                                           CORBA::Long SecondNodeID2)
4202 {
4203   initData();
4204
4205   SMESHDS_Mesh* aMesh = GetMeshDS();
4206
4207   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4208   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4209   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4210   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4211   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4212   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4213
4214   if (!aBorderFirstNode ||
4215       !aBorderSecondNode||
4216       !aBorderLastNode )
4217     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4218   if (!aSide2FirstNode  ||
4219       !aSide2SecondNode)
4220     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4221
4222   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4223                 << FirstNodeID1  << ", "
4224                 << SecondNodeID1 << ", "
4225                 << LastNodeID1   << ", "
4226                 << FirstNodeID2  << ", "
4227                 << SecondNodeID2 << " )";
4228
4229   ::SMESH_MeshEditor anEditor( myMesh );
4230   SMESH::SMESH_MeshEditor::Sew_Error error =
4231     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4232                                        aBorderSecondNode,
4233                                        aBorderLastNode,
4234                                        aSide2FirstNode,
4235                                        aSide2SecondNode,
4236                                        aSide2ThirdNode,
4237                                        true,
4238                                        false, false) );
4239
4240   storeResult(anEditor);
4241
4242   myMesh->SetIsModified( true );
4243
4244   return error;
4245 }
4246
4247
4248 //=======================================================================
4249 //function : SewBorderToSide
4250 //purpose  :
4251 //=======================================================================
4252
4253 SMESH::SMESH_MeshEditor::Sew_Error
4254 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4255                                     CORBA::Long SecondNodeIDOnFreeBorder,
4256                                     CORBA::Long LastNodeIDOnFreeBorder,
4257                                     CORBA::Long FirstNodeIDOnSide,
4258                                     CORBA::Long LastNodeIDOnSide,
4259                                     CORBA::Boolean CreatePolygons,
4260                                     CORBA::Boolean CreatePolyedrs)
4261 {
4262   initData();
4263
4264   SMESHDS_Mesh* aMesh = GetMeshDS();
4265
4266   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
4267   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4268   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
4269   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
4270   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
4271   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4272
4273   if (!aBorderFirstNode ||
4274       !aBorderSecondNode||
4275       !aBorderLastNode  )
4276     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4277   if (!aSide2FirstNode  ||
4278       !aSide2SecondNode)
4279     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4280
4281   TPythonDump() << "error = " << this << ".SewBorderToSide( "
4282                 << FirstNodeIDOnFreeBorder  << ", "
4283                 << SecondNodeIDOnFreeBorder << ", "
4284                 << LastNodeIDOnFreeBorder   << ", "
4285                 << FirstNodeIDOnSide        << ", "
4286                 << LastNodeIDOnSide         << ", "
4287                 << CreatePolygons           << ", "
4288                 << CreatePolyedrs           << ") ";
4289
4290   ::SMESH_MeshEditor anEditor( myMesh );
4291   SMESH::SMESH_MeshEditor::Sew_Error error =
4292     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4293                                        aBorderSecondNode,
4294                                        aBorderLastNode,
4295                                        aSide2FirstNode,
4296                                        aSide2SecondNode,
4297                                        aSide2ThirdNode,
4298                                        false,
4299                                        CreatePolygons,
4300                                        CreatePolyedrs) );
4301
4302   storeResult(anEditor);
4303
4304   myMesh->SetIsModified( true );
4305
4306   return error;
4307 }
4308
4309
4310 //=======================================================================
4311 //function : SewSideElements
4312 //purpose  :
4313 //=======================================================================
4314
4315 SMESH::SMESH_MeshEditor::Sew_Error
4316 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4317                                     const SMESH::long_array& IDsOfSide2Elements,
4318                                     CORBA::Long NodeID1OfSide1ToMerge,
4319                                     CORBA::Long NodeID1OfSide2ToMerge,
4320                                     CORBA::Long NodeID2OfSide1ToMerge,
4321                                     CORBA::Long NodeID2OfSide2ToMerge)
4322 {
4323   initData();
4324
4325   SMESHDS_Mesh* aMesh = GetMeshDS();
4326
4327   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
4328   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
4329   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4330   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4331
4332   if (!aFirstNode1ToMerge ||
4333       !aFirstNode2ToMerge )
4334     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4335   if (!aSecondNode1ToMerge||
4336       !aSecondNode2ToMerge)
4337     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4338
4339   TIDSortedElemSet aSide1Elems, aSide2Elems;
4340   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4341   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4342
4343   TPythonDump() << "error = " << this << ".SewSideElements( "
4344                 << IDsOfSide1Elements << ", "
4345                 << IDsOfSide2Elements << ", "
4346                 << NodeID1OfSide1ToMerge << ", "
4347                 << NodeID1OfSide2ToMerge << ", "
4348                 << NodeID2OfSide1ToMerge << ", "
4349                 << NodeID2OfSide2ToMerge << ")";
4350
4351   ::SMESH_MeshEditor anEditor( myMesh );
4352   SMESH::SMESH_MeshEditor::Sew_Error error =
4353     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
4354                                          aFirstNode1ToMerge,
4355                                          aFirstNode2ToMerge,
4356                                          aSecondNode1ToMerge,
4357                                          aSecondNode2ToMerge));
4358
4359   storeResult(anEditor);
4360
4361   myMesh->SetIsModified( true );
4362
4363   return error;
4364 }
4365
4366 //================================================================================
4367 /*!
4368  * \brief Set new nodes for given element
4369  * \param ide - element id
4370  * \param newIDs - new node ids
4371  * \retval CORBA::Boolean - true if result is OK
4372  */
4373 //================================================================================
4374
4375 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4376                                                    const SMESH::long_array& newIDs)
4377 {
4378   initData();
4379
4380   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4381   if(!elem) return false;
4382
4383   int nbn = newIDs.length();
4384   int i=0;
4385   vector<const SMDS_MeshNode*> aNodes(nbn);
4386   int nbn1=-1;
4387   for(; i<nbn; i++) {
4388     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4389     if(aNode) {
4390       nbn1++;
4391       aNodes[nbn1] = aNode;
4392     }
4393   }
4394   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4395                 << ide << ", " << newIDs << " )";
4396
4397   bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4398
4399   if ( res )
4400     myMesh->SetIsModified( true );
4401
4402   return res;
4403 }
4404
4405 //================================================================================
4406 /*!
4407  * \brief Update myLastCreated* or myPreviewData
4408  * \param anEditor - it contains last modification results
4409  */
4410 //================================================================================
4411
4412 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4413 {
4414   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
4415
4416     list<int> aNodesConnectivity;
4417     typedef map<int, int> TNodesMap;
4418     TNodesMap nodesMap;
4419
4420     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4421     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4422
4423     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4424     int nbEdges = aMeshDS->NbEdges();
4425     int nbFaces = aMeshDS->NbFaces();
4426     int nbVolum = aMeshDS->NbVolumes();
4427     switch ( previewType ) {
4428     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4429     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4430     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4431     default:;
4432     }
4433     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4434     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4435     int i = 0, j = 0;
4436     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4437
4438     while ( itMeshElems->more() ) {
4439       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4440       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4441         continue;
4442
4443       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4444       while ( itElemNodes->more() ) {
4445         const SMDS_MeshNode* aMeshNode = 
4446           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4447         int aNodeID = aMeshNode->GetID();
4448         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4449         if ( anIter == nodesMap.end() ) {
4450           // filling the nodes coordinates
4451           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4452           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4453           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4454           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4455           j++;
4456         }
4457         aNodesConnectivity.push_back(anIter->second);
4458       }
4459
4460       // filling the elements types
4461       SMDSAbs_ElementType aType;
4462       bool isPoly;
4463       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4464         aType = SMDSAbs_Node;
4465         isPoly = false;
4466         }
4467         else*/ {
4468         aType = aMeshElem->GetType();
4469         isPoly = aMeshElem->IsPoly();
4470       }
4471
4472       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4473       myPreviewData->elementTypes[i].isPoly = isPoly;
4474       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4475       i++;
4476
4477     }
4478     myPreviewData->nodesXYZ.length( j );
4479
4480     // filling the elements connectivities
4481     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4482     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4483     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4484       myPreviewData->elementConnectivities[i] = *aConnIter;
4485
4486     return;
4487   }
4488
4489   {
4490     // add new nodes into myLastCreatedNodes
4491     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4492     myLastCreatedNodes->length(aSeq.Length());
4493     for(int i=0; i<aSeq.Length(); i++)
4494       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
4495   }
4496   {
4497     // add new elements into myLastCreatedElems
4498     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4499     myLastCreatedElems->length(aSeq.Length());
4500     for(int i=0; i<aSeq.Length(); i++)
4501       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
4502   }
4503 }
4504
4505 //================================================================================
4506 /*!
4507  * Return data of mesh edition preview
4508  */
4509 //================================================================================
4510
4511 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4512 {
4513   return myPreviewData._retn();
4514 }
4515
4516 //================================================================================
4517 /*!
4518  * \brief Returns list of it's IDs of created nodes
4519  * \retval SMESH::long_array* - list of node ID
4520  */
4521 //================================================================================
4522
4523 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4524 {
4525   return myLastCreatedNodes._retn();
4526 }
4527
4528 //================================================================================
4529 /*!
4530  * \brief Returns list of it's IDs of created elements
4531  * \retval SMESH::long_array* - list of elements' ID
4532  */
4533 //================================================================================
4534
4535 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4536 {
4537   return myLastCreatedElems._retn();
4538 }
4539
4540 //=======================================================================
4541 //function : ConvertToQuadratic
4542 //purpose  :
4543 //=======================================================================
4544
4545 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4546 {
4547   ::SMESH_MeshEditor anEditor( myMesh );
4548   anEditor.ConvertToQuadratic(theForce3d);
4549   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4550   myMesh->SetIsModified( true );
4551 }
4552
4553 //=======================================================================
4554 //function : ConvertFromQuadratic
4555 //purpose  : 
4556 //=======================================================================
4557
4558 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4559 {
4560   ::SMESH_MeshEditor anEditor( myMesh );
4561   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
4562   TPythonDump() << this << ".ConvertFromQuadratic()";
4563   if ( isDone )
4564     myMesh->SetIsModified( true );
4565   return isDone;
4566 }
4567
4568 //=======================================================================
4569 //function : makeMesh
4570 //purpose  : create a named imported mesh 
4571 //=======================================================================
4572
4573 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4574 {
4575   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4576   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4577   SALOMEDS::Study_var study = gen->GetCurrentStudy();
4578   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
4579   gen->SetName( meshSO, theMeshName, "Mesh" );
4580   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4581
4582   return mesh._retn();
4583 }
4584
4585 //=======================================================================
4586 //function : DumpGroupsList
4587 //purpose  :
4588 //=======================================================================
4589 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython, 
4590                                         const SMESH::ListOfGroups * theGroupList)
4591 {
4592   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
4593   if(isDumpGroupList) {
4594     theDumpPython << theGroupList << " = ";
4595   }
4596 }
4597
4598 //================================================================================
4599 /*!
4600   \brief Generates the unique group name.
4601   \param thePrefix name prefix
4602   \return unique name
4603 */
4604 //================================================================================
4605 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4606 {
4607   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4608   set<string> groupNames;
4609   
4610   // Get existing group names
4611   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4612     SMESH::SMESH_GroupBase_var aGroup = groups[i];
4613     if (CORBA::is_nil(aGroup))
4614       continue;
4615
4616     groupNames.insert(aGroup->GetName());
4617   }
4618
4619   // Find new name
4620   string name = thePrefix;
4621   int index = 0;
4622
4623   while (!groupNames.insert(name).second) {
4624     if (index == 0) {
4625       name += "_1";
4626     }
4627     else {
4628       TCollection_AsciiString nbStr(index+1);
4629       name.resize( name.rfind('_')+1 );
4630       name += nbStr.ToCString();
4631     }
4632     ++index;
4633   }
4634   
4635   return name;
4636 }
4637
4638 //================================================================================
4639 /*!
4640   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4641   \param theNodes - identifiers of nodes to be doubled
4642   \param theModifiedElems - identifiers of elements to be updated by the new (doubled) 
4643          nodes. If list of element identifiers is empty then nodes are doubled but 
4644          they not assigned to elements
4645   \return TRUE if operation has been completed successfully, FALSE otherwise
4646   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
4647 */
4648 //================================================================================
4649
4650 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes, 
4651                                                 const SMESH::long_array& theModifiedElems )
4652 {
4653   initData();
4654
4655   ::SMESH_MeshEditor aMeshEditor( myMesh );
4656   list< int > aListOfNodes;
4657   int i, n;
4658   for ( i = 0, n = theNodes.length(); i < n; i++ )
4659     aListOfNodes.push_back( theNodes[ i ] );
4660
4661   list< int > aListOfElems;
4662   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4663     aListOfElems.push_back( theModifiedElems[ i ] );
4664
4665   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
4666
4667   storeResult( aMeshEditor) ;
4668   if ( aResult )
4669     myMesh->SetIsModified( true );
4670
4671   // Update Python script
4672   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
4673
4674   return aResult;
4675 }
4676
4677 //================================================================================
4678 /*!
4679   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4680   This method provided for convenience works as DoubleNodes() described above.
4681   \param theNodeId - identifier of node to be doubled.
4682   \param theModifiedElems - identifiers of elements to be updated.
4683   \return TRUE if operation has been completed successfully, FALSE otherwise
4684   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
4685 */
4686 //================================================================================
4687
4688 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId, 
4689                                                const SMESH::long_array& theModifiedElems )
4690 {
4691   SMESH::long_array_var aNodes = new SMESH::long_array;
4692   aNodes->length( 1 );
4693   aNodes[ 0 ] = theNodeId;
4694
4695   TPythonDump pyDump; // suppress dump by the next line
4696
4697   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
4698
4699   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
4700
4701   return done;
4702 }
4703
4704 //================================================================================
4705 /*!
4706   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4707   This method provided for convenience works as DoubleNodes() described above.
4708   \param theNodes - group of nodes to be doubled.
4709   \param theModifiedElems - group of elements to be updated.
4710   \return TRUE if operation has been completed successfully, FALSE otherwise
4711   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
4712 */
4713 //================================================================================
4714
4715 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
4716                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
4717 {
4718   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4719     return false;
4720
4721   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4722   SMESH::long_array_var aModifiedElems;
4723   if ( !CORBA::is_nil( theModifiedElems ) )
4724     aModifiedElems = theModifiedElems->GetListOfID();
4725   else 
4726   {
4727     aModifiedElems = new SMESH::long_array;
4728     aModifiedElems->length( 0 );
4729   }
4730
4731   TPythonDump pyDump; // suppress dump by the next line
4732
4733   bool done = DoubleNodes( aNodes, aModifiedElems );
4734
4735   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
4736
4737   return done;
4738 }
4739
4740 /*!
4741  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
4742  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
4743  * \param theNodes - group of nodes to be doubled.
4744  * \param theModifiedElems - group of elements to be updated.
4745  * \return a new group with newly created nodes
4746  * \sa DoubleNodeGroup()
4747  */
4748 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
4749                                                                SMESH::SMESH_GroupBase_ptr theModifiedElems )
4750 {
4751   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4752     return false;
4753   
4754   SMESH::SMESH_Group_var aNewGroup;
4755
4756   // Duplicate nodes
4757   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4758   SMESH::long_array_var aModifiedElems;
4759   if ( !CORBA::is_nil( theModifiedElems ) )
4760     aModifiedElems = theModifiedElems->GetListOfID();
4761   else {
4762     aModifiedElems = new SMESH::long_array;
4763     aModifiedElems->length( 0 );
4764   }
4765   
4766   TPythonDump pyDump; // suppress dump by the next line
4767
4768   bool aResult = DoubleNodes( aNodes, aModifiedElems );
4769
4770   if ( aResult )
4771   {
4772     // Create group with newly created nodes
4773     SMESH::long_array_var anIds = GetLastCreatedNodes();
4774     if (anIds->length() > 0) {
4775       string anUnindexedName (theNodes->GetName());
4776       string aNewName = generateGroupName(anUnindexedName + "_double");
4777       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
4778       aNewGroup->Add(anIds);
4779     }
4780   }
4781   
4782   pyDump << "createdNodes = " << this << ".DoubleNodeGroupNew( " << theNodes << ", "
4783     << theModifiedElems << " )";
4784
4785   return aNewGroup._retn();
4786 }
4787
4788 //================================================================================
4789 /*!
4790   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4791   This method provided for convenience works as DoubleNodes() described above.
4792   \param theNodes - list of groups of nodes to be doubled
4793   \param theModifiedElems - list of groups of elements to be updated.
4794   \return TRUE if operation has been completed successfully, FALSE otherwise
4795   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
4796 */
4797 //================================================================================
4798
4799 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
4800                                                     const SMESH::ListOfGroups& theModifiedElems )
4801 {
4802   initData();
4803
4804   ::SMESH_MeshEditor aMeshEditor( myMesh );
4805
4806   std::list< int > aNodes;
4807   int i, n, j, m;
4808   for ( i = 0, n = theNodes.length(); i < n; i++ )
4809   {
4810     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
4811     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
4812     {
4813       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4814       for ( j = 0, m = aCurr->length(); j < m; j++ )
4815         aNodes.push_back( aCurr[ j ] );
4816     }
4817   }
4818
4819   std::list< int > anElems;
4820   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4821   {
4822     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
4823     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
4824     {
4825       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4826       for ( j = 0, m = aCurr->length(); j < m; j++ )
4827         anElems.push_back( aCurr[ j ] );
4828     }
4829   }
4830
4831   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
4832
4833   storeResult( aMeshEditor) ;
4834
4835   if ( aResult )
4836     myMesh->SetIsModified( true );
4837
4838
4839   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
4840
4841   return aResult;
4842 }
4843
4844 //================================================================================
4845 /*!
4846   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4847   \param theElems - the list of elements (edges or faces) to be replicated
4848   The nodes for duplication could be found from these elements
4849   \param theNodesNot - list of nodes to NOT replicate
4850   \param theAffectedElems - the list of elements (cells and edges) to which the 
4851   replicated nodes should be associated to.
4852   \return TRUE if operation has been completed successfully, FALSE otherwise
4853   \sa DoubleNodeGroup(), DoubleNodeGroups()
4854 */
4855 //================================================================================
4856
4857 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems, 
4858                                                    const SMESH::long_array& theNodesNot,
4859                                                    const SMESH::long_array& theAffectedElems )
4860
4861 {
4862   initData();
4863
4864   ::SMESH_MeshEditor aMeshEditor( myMesh );
4865
4866   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4867   TIDSortedElemSet anElems, aNodes, anAffected;
4868   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4869   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4870   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
4871
4872   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4873
4874   storeResult( aMeshEditor) ;
4875
4876   if ( aResult )
4877     myMesh->SetIsModified( true );
4878
4879   // Update Python script
4880   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
4881                 << theNodesNot << ", " << theAffectedElems << " )";
4882   return aResult;
4883 }
4884
4885 //================================================================================
4886 /*!
4887   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4888   \param theElems - the list of elements (edges or faces) to be replicated
4889   The nodes for duplication could be found from these elements
4890   \param theNodesNot - list of nodes to NOT replicate
4891   \param theShape - shape to detect affected elements (element which geometric center
4892   located on or inside shape).
4893   The replicated nodes should be associated to affected elements.
4894   \return TRUE if operation has been completed successfully, FALSE otherwise
4895   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
4896 */
4897 //================================================================================
4898
4899 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems, 
4900                                                             const SMESH::long_array& theNodesNot,
4901                                                             GEOM::GEOM_Object_ptr    theShape )
4902
4903 {
4904   initData();
4905
4906   ::SMESH_MeshEditor aMeshEditor( myMesh );
4907
4908   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4909   TIDSortedElemSet anElems, aNodes;
4910   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4911   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4912
4913   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4914   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4915
4916   storeResult( aMeshEditor) ;
4917
4918   if ( aResult )
4919     myMesh->SetIsModified( true );
4920
4921   // Update Python script
4922   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
4923                 << theNodesNot << ", " << theShape << " )";
4924   return aResult;
4925 }
4926
4927 //================================================================================
4928 /*!
4929   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4930   \param theElems - group of of elements (edges or faces) to be replicated
4931   \param theNodesNot - group of nodes not to replicated
4932   \param theAffectedElems - group of elements to which the replicated nodes
4933   should be associated to.
4934   \return TRUE if operation has been completed successfully, FALSE otherwise
4935   \sa DoubleNodes(), DoubleNodeGroups()
4936 */
4937 //================================================================================
4938
4939 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
4940                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
4941                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
4942 {
4943   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4944     return false;
4945
4946   initData();
4947
4948   ::SMESH_MeshEditor aMeshEditor( myMesh );
4949
4950   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4951   TIDSortedElemSet anElems, aNodes, anAffected;
4952   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4953   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4954   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
4955
4956   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4957
4958   storeResult( aMeshEditor) ;
4959
4960   if ( aResult )
4961     myMesh->SetIsModified( true );
4962
4963   // Update Python script
4964   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
4965                 << theNodesNot << ", " << theAffectedElems << " )";
4966   return aResult;
4967 }
4968
4969 /*!
4970  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4971  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
4972  * \param theElems - group of of elements (edges or faces) to be replicated
4973  * \param theNodesNot - group of nodes not to replicated
4974  * \param theAffectedElems - group of elements to which the replicated nodes
4975  *        should be associated to.
4976  * \return a new group with newly created elements
4977  * \sa DoubleNodeElemGroup()
4978  */
4979 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
4980                                                                   SMESH::SMESH_GroupBase_ptr theNodesNot,
4981                                                                   SMESH::SMESH_GroupBase_ptr theAffectedElems)
4982 {
4983   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4984     return false;
4985
4986   SMESH::SMESH_Group_var aNewGroup;
4987
4988   initData();
4989
4990   ::SMESH_MeshEditor aMeshEditor( myMesh );
4991
4992   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4993   TIDSortedElemSet anElems, aNodes, anAffected;
4994   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4995   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4996   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
4997
4998   
4999   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5000   
5001   storeResult( aMeshEditor) ;
5002
5003   if ( aResult ) {
5004     myMesh->SetIsModified( true );
5005
5006     // Create group with newly created elements
5007     SMESH::long_array_var anIds = GetLastCreatedElems();
5008     if (anIds->length() > 0) {
5009       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5010       string anUnindexedName (theElems->GetName());
5011       string aNewName = generateGroupName(anUnindexedName + "_double");
5012       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5013       aNewGroup->Add(anIds);
5014     }
5015   }
5016
5017   // Update Python script
5018   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupNew( " << theElems << ", "
5019     << theNodesNot << ", " << theAffectedElems << " )";
5020   return aNewGroup._retn();
5021 }
5022
5023 //================================================================================
5024 /*!
5025   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5026   \param theElems - group of of elements (edges or faces) to be replicated
5027   \param theNodesNot - group of nodes not to replicated
5028   \param theShape - shape to detect affected elements (element which geometric center
5029   located on or inside shape).
5030   The replicated nodes should be associated to affected elements.
5031   \return TRUE if operation has been completed successfully, FALSE otherwise
5032   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5033 */
5034 //================================================================================
5035
5036 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5037                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
5038                                                                GEOM::GEOM_Object_ptr      theShape )
5039
5040 {
5041   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5042     return false;
5043
5044   initData();
5045
5046   ::SMESH_MeshEditor aMeshEditor( myMesh );
5047
5048   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5049   TIDSortedElemSet anElems, aNodes, anAffected;
5050   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
5051   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
5052
5053   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5054   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5055
5056   storeResult( aMeshEditor) ;
5057
5058   if ( aResult )
5059     myMesh->SetIsModified( true );
5060
5061   // Update Python script
5062   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5063                 << theNodesNot << ", " << theShape << " )";
5064   return aResult;
5065 }
5066
5067 //================================================================================
5068 /*!
5069   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5070   This method provided for convenience works as DoubleNodes() described above.
5071   \param theElems - list of groups of elements (edges or faces) to be replicated
5072   \param theNodesNot - list of groups of nodes not to replicated
5073   \param theAffectedElems - group of elements to which the replicated nodes
5074   should be associated to.
5075   \return TRUE if operation has been completed successfully, FALSE otherwise
5076   \sa DoubleNodeGroup(), DoubleNodes()
5077 */
5078 //================================================================================
5079
5080 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5081                              SMESHDS_Mesh*              theMeshDS,
5082                              TIDSortedElemSet&          theElemSet,
5083                              const bool                 theIsNodeGrp)
5084 {
5085   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5086   {
5087     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5088     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE 
5089                                     : aGrp->GetType() != SMESH::NODE ) )
5090     {
5091       SMESH::long_array_var anIDs = aGrp->GetIDs();
5092       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5093     }
5094   }
5095 }
5096
5097 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5098                                                         const SMESH::ListOfGroups& theNodesNot,
5099                                                         const SMESH::ListOfGroups& theAffectedElems)
5100 {
5101   initData();
5102
5103   ::SMESH_MeshEditor aMeshEditor( myMesh );
5104
5105   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5106   TIDSortedElemSet anElems, aNodes, anAffected;
5107   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5108   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5109   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5110
5111   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5112
5113   storeResult( aMeshEditor) ;
5114
5115   if ( aResult )
5116     myMesh->SetIsModified( true );
5117
5118   // Update Python script
5119   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5120                 << &theNodesNot << ", " << &theAffectedElems << " )";
5121   return aResult;
5122 }
5123
5124 //================================================================================
5125 /*!
5126   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5127   This method provided for convenience works as DoubleNodes() described above.
5128   \param theElems - list of groups of elements (edges or faces) to be replicated
5129   \param theNodesNot - list of groups of nodes not to replicated
5130   \param theShape - shape to detect affected elements (element which geometric center
5131   located on or inside shape).
5132   The replicated nodes should be associated to affected elements.
5133   \return TRUE if operation has been completed successfully, FALSE otherwise
5134   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5135 */
5136 //================================================================================
5137
5138 CORBA::Boolean
5139 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5140                                                  const SMESH::ListOfGroups& theNodesNot,
5141                                                  GEOM::GEOM_Object_ptr      theShape )
5142 {
5143   initData();
5144
5145   ::SMESH_MeshEditor aMeshEditor( myMesh );
5146
5147   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5148   TIDSortedElemSet anElems, aNodes;
5149   listOfGroupToSet(theElems, aMeshDS, anElems,false );
5150   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5151
5152   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5153   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5154
5155   storeResult( aMeshEditor) ;
5156
5157   if ( aResult )
5158     myMesh->SetIsModified( true );
5159
5160   // Update Python script
5161   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5162                 << &theNodesNot << ", " << theShape << " )";
5163   return aResult;
5164 }
5165
5166 //================================================================================
5167 /*!
5168   \brief Generated skin mesh (containing 2D cells) from 3D mesh
5169    The created 2D mesh elements based on nodes of free faces of boundary volumes
5170   \return TRUE if operation has been completed successfully, FALSE otherwise
5171 */
5172 //================================================================================
5173
5174 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5175 {
5176   initData();
5177
5178   ::SMESH_MeshEditor aMeshEditor( myMesh );
5179   bool aResult = aMeshEditor.Make2DMeshFrom3D();
5180   storeResult( aMeshEditor) ;
5181   
5182   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
5183   return aResult;
5184 }