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