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