Salome HOME
Merge from V6_main 06/03/2013
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_MeshEditor_i.cxx
23 //  Author : Nicolas REJNERI
24 //  Module : SMESH
25
26 #ifdef WNT
27 #define NOMINMAX
28 #endif
29
30 #include "SMESH_MeshEditor_i.hxx"
31
32 #include "SMDS_EdgePosition.hxx"
33 #include "SMDS_ElemIterator.hxx"
34 #include "SMDS_FacePosition.hxx"
35 #include "SMDS_IteratorOnIterators.hxx"
36 #include "SMDS_LinearEdge.hxx"
37 #include "SMDS_Mesh0DElement.hxx"
38 #include "SMDS_MeshFace.hxx"
39 #include "SMDS_MeshVolume.hxx"
40 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
41 #include "SMDS_SetIterator.hxx"
42 #include "SMDS_VolumeTool.hxx"
43 #include "SMESHDS_Group.hxx"
44 #include "SMESHDS_GroupOnGeom.hxx"
45 #include "SMESH_ControlsDef.hxx"
46 #include "SMESH_Filter_i.hxx"
47 #include "SMESH_Gen_i.hxx"
48 #include "SMESH_Group.hxx"
49 #include "SMESH_Group_i.hxx"
50 #include "SMESH_MeshPartDS.hxx"
51 #include "SMESH_MesherHelper.hxx"
52 #include "SMESH_PythonDump.hxx"
53 #include "SMESH_subMeshEventListener.hxx"
54 #include "SMESH_subMesh_i.hxx"
55
56 #include <utilities.h>
57 #include <Utils_ExceptHandlers.hxx>
58 #include <Utils_CorbaException.hxx>
59 #include <SALOMEDS_wrap.hxx>
60
61 #include <BRepAdaptor_Surface.hxx>
62 #include <BRep_Tool.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopoDS.hxx>
65 #include <TopoDS_Edge.hxx>
66 #include <TopoDS_Face.hxx>
67 #include <gp_Ax1.hxx>
68 #include <gp_Ax2.hxx>
69 #include <gp_Vec.hxx>
70
71 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
72 #define NO_CAS_CATCH
73 #endif
74
75 #include <Standard_Failure.hxx>
76
77 #ifdef NO_CAS_CATCH
78 #include <Standard_ErrorHandler.hxx>
79 #endif
80
81 #include <sstream>
82 #include <limits>
83
84 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85
86 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
87
88 using namespace std;
89 using SMESH::TPythonDump;
90 using SMESH::TVar;
91
92 namespace MeshEditor_I {
93
94   //=============================================================================
95   /*!
96    * \brief Mesh to apply modifications for preview purposes
97    */
98   //=============================================================================
99
100   struct TPreviewMesh: public SMESH_Mesh
101   {
102     SMDSAbs_ElementType myPreviewType; // type to show
103     //!< Constructor
104     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
105       _isShapeToMesh = (_id =_studyId = 0);
106       _myMeshDS  = new SMESHDS_Mesh( _id, true );
107       myPreviewType = previewElements;
108     }
109     //!< Destructor
110     virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; }
111     //!< Copy a set of elements
112     void Copy(const TIDSortedElemSet & theElements,
113               TIDSortedElemSet&        theCopyElements,
114               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
115               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
116     {
117       // loop on theIDsOfElements
118       TIDSortedElemSet::const_iterator eIt = theElements.begin();
119       for ( ; eIt != theElements.end(); ++eIt )
120       {
121         const SMDS_MeshElement* anElem = *eIt;
122         if ( !anElem ) continue;
123         SMDSAbs_ElementType type = anElem->GetType();
124         if ( type == theAvoidType ||
125              ( theSelectType != SMDSAbs_All && type != theSelectType ))
126           continue;
127         const SMDS_MeshElement* anElemCopy;
128         if ( type == SMDSAbs_Node)
129           anElemCopy = Copy( cast2Node(anElem) );
130         else
131           anElemCopy = Copy( anElem );
132         if ( anElemCopy )
133           theCopyElements.insert( theCopyElements.end(), anElemCopy );
134       }
135     }
136     //!< Copy an element
137     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
138     {
139       // copy element nodes
140       int anElemNbNodes = anElem->NbNodes();
141       vector< int > anElemNodesID( anElemNbNodes ) ;
142       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
143       for ( int i = 0; itElemNodes->more(); i++)
144       {
145         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
146         Copy( anElemNode );
147         anElemNodesID[i] = anElemNode->GetID();
148       }
149
150       // creates a corresponding element on copied nodes
151       SMDS_MeshElement* anElemCopy = 0;
152       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
153       {
154         const SMDS_VtkVolume* ph =
155           dynamic_cast<const SMDS_VtkVolume*> (anElem);
156         if ( ph )
157           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
158             (anElemNodesID, ph->GetQuantities(),anElem->GetID());
159       }
160       else {
161         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
162                                                           anElem->GetType(),
163                                                           anElem->IsPoly() );
164       }
165       return anElemCopy;
166     }
167     //!< Copy a node
168     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
169     {
170       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
171                                       anElemNode->GetID());
172     }
173   };// struct TPreviewMesh
174
175   static SMESH_NodeSearcher *    theNodeSearcher    = 0;
176   static SMESH_ElementSearcher * theElementSearcher = 0;
177
178   //=============================================================================
179   /*!
180    * \brief Deleter of theNodeSearcher at any compute event occured
181    */
182   //=============================================================================
183
184   struct TSearchersDeleter : public SMESH_subMeshEventListener
185   {
186     SMESH_Mesh* myMesh;
187     string      myMeshPartIOR;
188     //!< Constructor
189     TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
190                                                      "SMESH_MeshEditor_i::TSearchersDeleter"),
191                          myMesh(0) {}
192     //!< Delete theNodeSearcher
193     static void Delete()
194     {
195       if ( theNodeSearcher )    delete theNodeSearcher;    theNodeSearcher    = 0;
196       if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
197     }
198     typedef map < int, SMESH_subMesh * > TDependsOnMap;
199     //!< The meshod called by submesh: do my main job
200     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
201                       SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
202     {
203       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
204         Delete();
205         Unset( sm->GetFather() );
206       }
207     }
208     //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
209     void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
210     {
211       if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
212       {
213         if ( myMesh ) {
214           Delete();
215           Unset( myMesh );
216         }
217         myMesh = mesh;
218         myMeshPartIOR = meshPartIOR;
219         if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
220           const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
221           TDependsOnMap::const_iterator sm;
222           for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
223             sm->second->SetEventListener( this, 0, sm->second );
224         }
225       }
226     }
227     //!<  delete self from all submeshes
228     void Unset(SMESH_Mesh* mesh)
229     {
230       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
231         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
232         TDependsOnMap::const_iterator sm;
233         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
234           sm->second->DeleteEventListener( this );
235       }
236       myMesh = 0;
237     }
238
239   } theSearchersDeleter;
240
241   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
242   {
243     TCollection_AsciiString typeStr;
244     switch ( theMirrorType ) {
245     case  SMESH::SMESH_MeshEditor::POINT:
246       typeStr = "SMESH.SMESH_MeshEditor.POINT";
247       break;
248     case  SMESH::SMESH_MeshEditor::AXIS:
249       typeStr = "SMESH.SMESH_MeshEditor.AXIS";
250       break;
251     default:
252       typeStr = "SMESH.SMESH_MeshEditor.PLANE";
253     }
254     return typeStr;
255   }
256   //================================================================================
257   /*!
258    * \brief function for conversion of long_array to TIDSortedElemSet
259    * \param IDs - array of IDs
260    * \param aMesh - mesh
261    * \param aMap - collection to fill
262    * \param aType - element type
263    */
264   //================================================================================
265
266   void arrayToSet(const SMESH::long_array & IDs,
267                   const SMESHDS_Mesh*       aMesh,
268                   TIDSortedElemSet&         aMap,
269                   const SMDSAbs_ElementType aType = SMDSAbs_All )
270   {
271     for (int i=0; i<IDs.length(); i++) {
272       CORBA::Long ind = IDs[i];
273       const SMDS_MeshElement * elem =
274         (aType == SMDSAbs_Node ? aMesh->FindNode(ind) : aMesh->FindElement(ind));
275       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
276         aMap.insert( aMap.end(), elem );
277     }
278   }
279   //================================================================================
280   /*!
281    * \brief Retrieve elements of given type from SMESH_IDSource
282    */
283   //================================================================================
284
285   bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
286                      const SMESHDS_Mesh*        theMeshDS,
287                      TIDSortedElemSet&          theElemSet,
288                      const SMDSAbs_ElementType  theType,
289                      const bool                 emptyIfIsMesh=false)
290
291   {
292     if ( CORBA::is_nil( theIDSource ) )
293       return false;
294     if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
295       return true;
296
297     SMESH::long_array_var anIDs = theIDSource->GetIDs();
298     if ( anIDs->length() == 0 )
299       return false;
300     SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
301     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
302     {
303       if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
304         arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
305       else
306         return false;
307     }
308     else
309     {
310       arrayToSet( anIDs, theMeshDS, theElemSet, theType);
311       return bool(anIDs->length()) == bool(theElemSet.size());
312     }
313     return true;
314   }
315   //================================================================================
316   /*!
317    * \brief Retrieve nodes from SMESH_IDSource
318    */
319   //================================================================================
320
321   void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr  theObject,
322                          const SMESHDS_Mesh*        theMeshDS,
323                          TIDSortedNodeSet&          theNodeSet)
324
325   {
326     if ( CORBA::is_nil( theObject ) )
327       return;
328     SMESH::array_of_ElementType_var types = theObject->GetTypes();
329     SMESH::long_array_var     aElementsId = theObject->GetIDs();
330     if ( types->length() == 1 && types[0] == SMESH::NODE)
331     {
332       for(int i = 0; i < aElementsId->length(); i++)
333         if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
334           theNodeSet.insert( theNodeSet.end(), n);
335     }
336     else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
337     {
338       SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
339       while ( nIt->more( ))
340         if( const SMDS_MeshElement * elem = nIt->next() )
341           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
342     }
343     else
344     {
345       for(int i = 0; i < aElementsId->length(); i++)
346         if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
347           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
348     }
349   }
350
351   //================================================================================
352   /*!
353    * \brief Returns elements connected to the given elements
354    */
355   //================================================================================
356
357   void getElementsAround(const TIDSortedElemSet& theElements,
358                          const SMESHDS_Mesh*     theMeshDS,
359                          TIDSortedElemSet&       theElementsAround)
360   {
361     if ( theElements.empty() ) return;
362
363     SMDSAbs_ElementType elemType    = (*theElements.begin())->GetType();
364     bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
365     if ( sameElemType &&
366          theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
367       return; // all the elements are in theElements
368
369     if ( !sameElemType )
370       elemType = SMDSAbs_All;
371
372     TIDSortedElemSet visitedNodes;
373     TIDSortedElemSet::const_iterator elemIt = theElements.begin();
374     for ( ; elemIt != theElements.end(); ++elemIt )
375     {
376       const SMDS_MeshElement* e = *elemIt;
377       int i = e->NbCornerNodes();
378       while ( --i != -1 )
379       {
380         const SMDS_MeshNode* n = e->GetNode( i );
381         if ( visitedNodes.insert( n ).second )
382         {
383           SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
384           while ( invIt->more() )
385           {
386             const SMDS_MeshElement* elemAround = invIt->next();
387             if ( !theElements.count( elemAround ))
388               theElementsAround.insert( elemAround );
389           }
390         }
391       }
392     }
393   }
394
395   //================================================================================
396   /*!
397    * \brief Return a string used to detect change of mesh part on which theElementSearcher
398    * is going to be used
399    */
400   //================================================================================
401
402   string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
403   {
404     string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
405     if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
406       // take into account passible group modification
407       partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
408     partIOR += SMESH_Comment( type );
409     return partIOR;
410   }
411
412 } // namespace MeshEditor_I
413
414 using namespace MeshEditor_I;
415
416 //=============================================================================
417 /*!
418  *
419  */
420 //=============================================================================
421
422 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
423   myMesh_i( theMesh ),
424   myMesh( &theMesh->GetImpl() ),
425   myEditor( myMesh ),
426   myIsPreviewMode ( isPreview ),
427   myPreviewMesh( 0 ),
428   myPreviewEditor( 0 )
429 {
430 }
431
432 //================================================================================
433 /*!
434  * \brief Destructor
435  */
436 //================================================================================
437
438 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
439 {
440   deleteAuxIDSources();
441   delete myPreviewMesh;   myPreviewMesh = 0;
442   delete myPreviewEditor; myPreviewEditor = 0;
443 }
444
445 //================================================================================
446 /*!
447  * \brief Clear members
448  */
449 //================================================================================
450
451 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
452 {
453   if ( myIsPreviewMode ) {
454     if ( myPreviewMesh ) myPreviewMesh->Clear();
455   }
456   else {
457     if ( deleteSearchers )
458       TSearchersDeleter::Delete();
459   }
460   getEditor().GetError().reset();
461   getEditor().CrearLastCreated();
462 }
463
464 //================================================================================
465 /*!
466  * \brief Increment mesh modif time and optionally record that the performed
467  *        modification may influence futher mesh re-compute.
468  *  \param [in] isReComputeSafe - true if the modification does not infulence
469  *              futher mesh re-compute
470  */
471 //================================================================================
472
473 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
474 {
475   myMesh->GetMeshDS()->Modified();
476   if ( !isReComputeSafe )
477     myMesh->SetIsModified( true );
478 }
479
480 //================================================================================
481 /*!
482  * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
483  *        WARNING: in preview mode call getPreviewMesh() before getEditor()!
484  */
485 //================================================================================
486
487 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
488 {
489   if ( myIsPreviewMode && !myPreviewEditor ) {
490     if ( !myPreviewMesh ) getPreviewMesh();
491     myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
492   }
493   return myIsPreviewMode ? *myPreviewEditor : myEditor;
494 }
495
496 //================================================================================
497 /*!
498  * \brief Initialize and return myPreviewMesh
499  *  \param previewElements - type of elements to show in preview
500  *
501  *  WARNING: call it once par a method!
502  */
503 //================================================================================
504
505 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
506 {
507   if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
508   {
509     delete myPreviewEditor;
510     myPreviewEditor = 0;
511     delete myPreviewMesh;
512     myPreviewMesh = new TPreviewMesh( previewElements );
513   }
514   myPreviewMesh->Clear();
515   return myPreviewMesh;
516 }
517
518 //================================================================================
519 /*!
520  * Return data of mesh edition preview
521  */
522 //================================================================================
523
524 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
525   throw (SALOME::SALOME_Exception)
526
527   SMESH_TRY;
528   const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
529
530   if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
531
532     list<int> aNodesConnectivity;
533     typedef map<int, int> TNodesMap;
534     TNodesMap nodesMap;
535
536     SMESHDS_Mesh* aMeshDS;
537     std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
538     if ( hasBadElems ) {
539       aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
540       aMeshDS = aMeshPartDS.get();
541     }
542     else {
543       aMeshDS = getEditor().GetMeshDS();
544     }
545     myPreviewData = new SMESH::MeshPreviewStruct();
546     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
547
548     
549     SMDSAbs_ElementType previewType = SMDSAbs_All;
550     if ( !hasBadElems )
551       if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
552         previewType = aPreviewMesh->myPreviewType;
553         switch ( previewType ) {
554         case SMDSAbs_Edge  : break;
555         case SMDSAbs_Face  : break;
556         case SMDSAbs_Volume: break;
557         default:;
558           if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
559         }
560       }
561
562     myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
563     int i = 0, j = 0;
564     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
565
566     while ( itMeshElems->more() ) {
567       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
568       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
569       while ( itElemNodes->more() ) {
570         const SMDS_MeshNode* aMeshNode =
571           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
572         int aNodeID = aMeshNode->GetID();
573         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
574         if ( anIter == nodesMap.end() ) {
575           // filling the nodes coordinates
576           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
577           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
578           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
579           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
580           j++;
581         }
582         aNodesConnectivity.push_back(anIter->second);
583       }
584
585       // filling the elements types
586       SMDSAbs_ElementType aType = aMeshElem->GetType();
587       bool               isPoly = aMeshElem->IsPoly();
588
589       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
590       myPreviewData->elementTypes[i].isPoly = isPoly;
591       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
592       i++;
593
594     }
595     myPreviewData->nodesXYZ.length( j );
596
597     // filling the elements connectivities
598     list<int>::iterator aConnIter = aNodesConnectivity.begin();
599     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
600     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
601       myPreviewData->elementConnectivities[i] = *aConnIter;
602   }
603
604   return myPreviewData._retn();
605   SMESH_CATCH( SMESH::throwCorbaException );
606   return 0;
607 }
608
609 //================================================================================
610 /*!
611  * \brief Returns list of it's IDs of created nodes
612  * \retval SMESH::long_array* - list of node ID
613  */
614 //================================================================================
615
616 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
617   throw (SALOME::SALOME_Exception)
618 {
619   SMESH_TRY;
620   SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
621
622   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
623   myLastCreatedNodes->length( aSeq.Length() );
624   for (int i = 1; i <= aSeq.Length(); i++)
625     myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
626
627   return myLastCreatedNodes._retn();
628   SMESH_CATCH( SMESH::throwCorbaException );
629   return 0;
630 }
631
632 //================================================================================
633 /*!
634  * \brief Returns list of it's IDs of created elements
635  * \retval SMESH::long_array* - list of elements' ID
636  */
637 //================================================================================
638
639 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
640   throw (SALOME::SALOME_Exception)
641 {
642   SMESH_TRY;
643   SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
644
645   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
646   myLastCreatedElems->length( aSeq.Length() );
647   for ( int i = 1; i <= aSeq.Length(); i++ )
648     myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
649
650   return myLastCreatedElems._retn();
651   SMESH_CATCH( SMESH::throwCorbaException );
652   return 0;
653 }
654
655 //=======================================================================
656 /*
657  * Returns description of an error/warning occured during the last operation
658  */
659 //=======================================================================
660
661 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
662   throw (SALOME::SALOME_Exception)
663 {
664   SMESH_TRY;
665   SMESH::ComputeError_var errOut = new SMESH::ComputeError;
666   SMESH_ComputeErrorPtr&  errIn  = getEditor().GetError();
667   if ( errIn && !errIn->IsOK() )
668   {
669     errOut->code       = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
670     errOut->comment    = errIn->myComment.c_str();
671     errOut->subShapeID = -1;
672     errOut->hasBadMesh = !errIn->myBadElements.empty();
673   }
674   else
675   {
676     errOut->code       = 0;
677     errOut->subShapeID = -1;
678     errOut->hasBadMesh = false;
679   }
680
681   return errOut._retn();
682   SMESH_CATCH( SMESH::throwCorbaException );
683   return 0;
684 }
685
686 //=======================================================================
687 //function : MakeIDSource
688 //purpose  : Wrap a sequence of ids in a SMESH_IDSource
689 //=======================================================================
690
691 struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource
692 {
693   SMESH::long_array     _ids;
694   SMESH::ElementType    _type;
695   SMESH::SMESH_Mesh_ptr _mesh;
696   SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
697   SMESH::long_array* GetMeshInfo() { return 0; }
698   SMESH::SMESH_Mesh_ptr GetMesh()  { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
699   bool IsMeshInfoCorrect()         { return true; }
700   SMESH::array_of_ElementType* GetTypes()
701   {
702     SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
703     if ( _ids.length() > 0 ) {
704       types->length( 1 );
705       types[0] = _type;
706     }
707     return types._retn();
708   }
709 };
710
711 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
712                                                            SMESH::ElementType       type)
713 {
714   if ( myAuxIDSources.size() > 10 )
715     deleteAuxIDSources();
716
717   _IDSource* idSrc = new _IDSource;
718   idSrc->_mesh = myMesh_i->_this();
719   idSrc->_ids  = ids;
720   idSrc->_type = type;
721   myAuxIDSources.push_back( idSrc );
722
723   SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
724
725   return anIDSourceVar._retn();
726 }
727
728 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
729 {
730   return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
731 }
732
733 void SMESH_MeshEditor_i::deleteAuxIDSources()
734 {
735   std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
736   for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
737     delete *idSrcIt;
738   myAuxIDSources.clear();
739 }
740
741 //=============================================================================
742 /*!
743  *
744  */
745 //=============================================================================
746
747 CORBA::Boolean
748 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
749   throw (SALOME::SALOME_Exception)
750 {
751   SMESH_TRY;
752   initData();
753
754   list< int > IdList;
755
756   for (int i = 0; i < IDsOfElements.length(); i++)
757     IdList.push_back( IDsOfElements[i] );
758
759   // Update Python script
760   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
761
762   // Remove Elements
763   bool ret = getEditor().Remove( IdList, false );
764
765   declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
766   return ret;
767
768   SMESH_CATCH( SMESH::throwCorbaException );
769   return 0;
770 }
771
772 //=============================================================================
773 /*!
774  *
775  */
776 //=============================================================================
777
778 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
779   throw (SALOME::SALOME_Exception)
780 {
781   SMESH_TRY;
782   initData();
783
784   list< int > IdList;
785   for (int i = 0; i < IDsOfNodes.length(); i++)
786     IdList.push_back( IDsOfNodes[i] );
787
788   // Update Python script
789   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
790
791   bool ret = getEditor().Remove( IdList, true );
792
793   declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
794   return ret;
795
796   SMESH_CATCH( SMESH::throwCorbaException );
797   return 0;
798 }
799
800 //=============================================================================
801 /*!
802  *
803  */
804 //=============================================================================
805
806 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
807   throw (SALOME::SALOME_Exception)
808 {
809   SMESH_TRY;
810   initData();
811
812   // Update Python script
813   TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
814
815   // Create filter to find all orphan nodes
816   SMESH::Controls::Filter::TIdSequence seq;
817   SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
818   SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
819
820   // remove orphan nodes (if there are any)
821   list< int > IdList;
822   for ( int i = 0; i < seq.size(); i++ )
823     IdList.push_back( seq[i] );
824
825   int nbNodesBefore = myMesh->NbNodes();
826   getEditor().Remove( IdList, true );
827   int nbNodesAfter = myMesh->NbNodes();
828
829   declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
830   return nbNodesBefore - nbNodesAfter;
831
832   SMESH_CATCH( SMESH::throwCorbaException );
833   return 0;
834 }
835
836 //=============================================================================
837 /*!
838  * Add a new node.
839  */
840 //=============================================================================
841
842 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
843   throw (SALOME::SALOME_Exception)
844 {
845   SMESH_TRY;
846   initData();
847
848   const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
849
850   // Update Python script
851   TPythonDump() << "nodeID = " << this << ".AddNode( "
852                 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
853
854   declareMeshModified( /*isReComputeSafe=*/false );
855   return N->GetID();
856
857   SMESH_CATCH( SMESH::throwCorbaException );
858   return 0;
859 }
860
861 //=============================================================================
862 /*!
863  * Create 0D element on the given node.
864  */
865 //=============================================================================
866
867 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
868   throw (SALOME::SALOME_Exception)
869 {
870   SMESH_TRY;
871   initData();
872
873   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
874   SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
875
876   // Update Python script
877   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
878
879   declareMeshModified( /*isReComputeSafe=*/false );
880
881   return elem ? elem->GetID() : 0;
882
883   SMESH_CATCH( SMESH::throwCorbaException );
884   return 0;
885 }
886
887 //=============================================================================
888 /*!
889  * Create a ball element on the given node.
890  */
891 //=============================================================================
892
893 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
894   throw (SALOME::SALOME_Exception)
895 {
896   SMESH_TRY;
897   initData();
898
899   if ( diameter < std::numeric_limits<double>::min() )
900     THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
901
902   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
903   SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
904
905   // Update Python script
906   TPythonDump() << "ballElem = "
907                 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
908
909   declareMeshModified( /*isReComputeSafe=*/false );
910   return elem ? elem->GetID() : 0;
911
912   SMESH_CATCH( SMESH::throwCorbaException );
913   return 0;
914 }
915
916 //=============================================================================
917 /*!
918  * Create an edge, either linear and quadratic (this is determed
919  *  by number of given nodes, two or three)
920  */
921 //=============================================================================
922
923 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
924   throw (SALOME::SALOME_Exception)
925 {
926   SMESH_TRY;
927   initData();
928
929   int NbNodes = IDsOfNodes.length();
930   SMDS_MeshElement* elem = 0;
931   if (NbNodes == 2)
932   {
933     CORBA::Long index1 = IDsOfNodes[0];
934     CORBA::Long index2 = IDsOfNodes[1];
935     elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
936                                  getMeshDS()->FindNode(index2));
937
938     // Update Python script
939     TPythonDump() << "edge = " << this << ".AddEdge([ "
940                   << index1 << ", " << index2 <<" ])";
941   }
942   if (NbNodes == 3) {
943     CORBA::Long n1 = IDsOfNodes[0];
944     CORBA::Long n2 = IDsOfNodes[1];
945     CORBA::Long n12 = IDsOfNodes[2];
946     elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
947                                  getMeshDS()->FindNode(n2),
948                                  getMeshDS()->FindNode(n12));
949     // Update Python script
950     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
951                   <<n1<<", "<<n2<<", "<<n12<<" ])";
952   }
953
954   declareMeshModified( /*isReComputeSafe=*/false );
955   return elem ? elem->GetID() : 0;
956
957   SMESH_CATCH( SMESH::throwCorbaException );
958   return 0;
959 }
960
961 //=============================================================================
962 /*!
963  *  AddFace
964  */
965 //=============================================================================
966
967 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
968   throw (SALOME::SALOME_Exception)
969 {
970   SMESH_TRY;
971   initData();
972
973   int NbNodes = IDsOfNodes.length();
974   if (NbNodes < 3)
975   {
976     return 0;
977   }
978
979   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
980   for (int i = 0; i < NbNodes; i++)
981     nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
982
983   SMDS_MeshElement* elem = 0;
984   if (NbNodes == 3) {
985     elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
986   }
987   else if (NbNodes == 4) {
988     elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
989   }
990   else if (NbNodes == 6) {
991     elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
992                                 nodes[4], nodes[5]);
993   }
994   else if (NbNodes == 8) {
995     elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
996                                 nodes[4], nodes[5], nodes[6], nodes[7]);
997   }
998   else if (NbNodes == 9) {
999     elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1000                                 nodes[4], nodes[5], nodes[6], nodes[7], nodes[8] );
1001   }
1002   else if (NbNodes > 2) {
1003     elem = getMeshDS()->AddPolygonalFace(nodes);
1004   }
1005
1006   // Update Python script
1007   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1008
1009   declareMeshModified( /*isReComputeSafe=*/false );
1010
1011   return elem ? elem->GetID() : 0;
1012
1013   SMESH_CATCH( SMESH::throwCorbaException );
1014   return 0;
1015 }
1016
1017 //=============================================================================
1018 /*!
1019  *  AddPolygonalFace
1020  */
1021 //=============================================================================
1022 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1023   throw (SALOME::SALOME_Exception)
1024 {
1025   SMESH_TRY;
1026   initData();
1027
1028   int NbNodes = IDsOfNodes.length();
1029   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1030   for (int i = 0; i < NbNodes; i++)
1031     nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1032
1033   const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1034
1035   // Update Python script
1036   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1037
1038   declareMeshModified( /*isReComputeSafe=*/false );
1039   return elem ? elem->GetID() : 0;
1040
1041   SMESH_CATCH( SMESH::throwCorbaException );
1042   return 0;
1043 }
1044
1045 //=============================================================================
1046 /*!
1047  * Create volume, either linear and quadratic (this is determed
1048  *  by number of given nodes)
1049  */
1050 //=============================================================================
1051
1052 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1053   throw (SALOME::SALOME_Exception)
1054 {
1055   SMESH_TRY;
1056   initData();
1057
1058   int NbNodes = IDsOfNodes.length();
1059   vector< const SMDS_MeshNode*> n(NbNodes);
1060   for(int i=0;i<NbNodes;i++)
1061     n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1062
1063   SMDS_MeshElement* elem = 0;
1064   switch(NbNodes)
1065   {
1066   case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1067   case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1068   case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1069   case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1070   case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1071                                         n[6],n[7],n[8],n[9]);
1072     break;
1073   case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1074                                         n[6],n[7],n[8],n[9],n[10],n[11]);
1075     break;
1076   case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1077                                         n[7],n[8],n[9],n[10],n[11],n[12]);
1078     break;
1079   case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1080                                         n[9],n[10],n[11],n[12],n[13],n[14]);
1081     break;
1082   case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1083                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1084                                         n[15],n[16],n[17],n[18],n[19]);
1085     break;
1086   case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1087                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1088                                         n[15],n[16],n[17],n[18],n[19],
1089                                         n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1090     break;
1091   }
1092
1093   // Update Python script
1094   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1095
1096   declareMeshModified( /*isReComputeSafe=*/false );
1097   return elem ? elem->GetID() : 0;
1098
1099   SMESH_CATCH( SMESH::throwCorbaException );
1100   return 0;
1101 }
1102
1103 //=============================================================================
1104 /*!
1105  *  AddPolyhedralVolume
1106  */
1107 //=============================================================================
1108 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1109                                                      const SMESH::long_array & Quantities)
1110   throw (SALOME::SALOME_Exception)
1111 {
1112   SMESH_TRY;
1113   initData();
1114
1115   int NbNodes = IDsOfNodes.length();
1116   std::vector<const SMDS_MeshNode*> n (NbNodes);
1117   for (int i = 0; i < NbNodes; i++)
1118     {
1119       const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1120       if (!aNode) return 0;
1121       n[i] = aNode;
1122     }
1123
1124   int NbFaces = Quantities.length();
1125   std::vector<int> q (NbFaces);
1126   for (int j = 0; j < NbFaces; j++)
1127     q[j] = Quantities[j];
1128
1129   const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1130
1131   // Update Python script
1132   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1133                 << IDsOfNodes << ", " << Quantities << " )";
1134
1135   declareMeshModified( /*isReComputeSafe=*/false );
1136   return elem ? elem->GetID() : 0;
1137
1138   SMESH_CATCH( SMESH::throwCorbaException );
1139   return 0;
1140 }
1141
1142 //=============================================================================
1143 /*!
1144  *  AddPolyhedralVolumeByFaces
1145  */
1146 //=============================================================================
1147
1148 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1149   throw (SALOME::SALOME_Exception)
1150 {
1151   SMESH_TRY;
1152   initData();
1153
1154   int NbFaces = IdsOfFaces.length();
1155   std::vector<const SMDS_MeshNode*> poly_nodes;
1156   std::vector<int> quantities (NbFaces);
1157
1158   for (int i = 0; i < NbFaces; i++) {
1159     const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1160     quantities[i] = aFace->NbNodes();
1161
1162     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1163     while (It->more()) {
1164       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1165     }
1166   }
1167
1168   const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1169
1170   // Update Python script
1171   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1172                 << IdsOfFaces << " )";
1173
1174   declareMeshModified( /*isReComputeSafe=*/false );
1175   return elem ? elem->GetID() : 0;
1176
1177   SMESH_CATCH( SMESH::throwCorbaException );
1178   return 0;
1179 }
1180
1181 //=============================================================================
1182 //
1183 // \brief Create 0D elements on all nodes of the given object except those 
1184 //        nodes on which a 0D element already exists.
1185 //  \param theObject object on whose nodes 0D elements will be created.
1186 //  \param theGroupName optional name of a group to add 0D elements created
1187 //         and/or found on nodes of \a theObject.
1188 //  \return an object (a new group or a temporary SMESH_IDSource) holding
1189 //          ids of new and/or found 0D elements.
1190 //
1191 //=============================================================================
1192
1193 SMESH::SMESH_IDSource_ptr
1194 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1195                                                const char*               theGroupName)
1196   throw (SALOME::SALOME_Exception)
1197 {
1198   SMESH_TRY;
1199   initData();
1200
1201   SMESH::SMESH_IDSource_var result;
1202   TPythonDump pyDump;
1203
1204   TIDSortedElemSet elements, elems0D;
1205   if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1206     getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1207
1208   SMESH::long_array_var newElems = new SMESH::long_array;
1209   newElems->length( elems0D.size() );
1210   TIDSortedElemSet::iterator eIt = elems0D.begin();
1211   for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1212     newElems[ i ] = (*eIt)->GetID();
1213
1214   SMESH::SMESH_GroupBase_var groupToFill;
1215   if ( theGroupName && strlen( theGroupName ))
1216   {
1217     // Get existing group named theGroupName
1218     SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1219     for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1220       SMESH::SMESH_GroupBase_var group = groups[i];
1221       if ( !group->_is_nil() ) {
1222         CORBA::String_var name = group->GetName();
1223         if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1224           groupToFill = group;
1225           break;
1226         }
1227       }
1228     }
1229     if ( groupToFill->_is_nil() )
1230       groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1231     else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1232       groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1233   }
1234
1235   if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1236   {
1237     group_i->Add( newElems );
1238     result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1239     pyDump << groupToFill;
1240   }
1241   else
1242   {
1243     result = MakeIDSource( newElems, SMESH::ELEM0D );
1244     pyDump << "elem0DIDs";
1245   }
1246
1247   pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1248          << theObject << ", '" << theGroupName << "' )";
1249
1250   return result._retn();
1251
1252   SMESH_CATCH( SMESH::throwCorbaException );
1253   return 0;
1254 }
1255
1256 //=============================================================================
1257 /*!
1258  * \brief Bind a node to a vertex
1259  * \param NodeID - node ID
1260  * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1261  * \retval boolean - false if NodeID or VertexID is invalid
1262  */
1263 //=============================================================================
1264
1265 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1266   throw (SALOME::SALOME_Exception)
1267 {
1268   SMESH_TRY;
1269
1270   SMESHDS_Mesh * mesh = getMeshDS();
1271   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1272   if ( !node )
1273     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1274
1275   if ( mesh->MaxShapeIndex() < VertexID )
1276     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1277
1278   TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1279   if ( shape.ShapeType() != TopAbs_VERTEX )
1280     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1281
1282   mesh->SetNodeOnVertex( node, VertexID );
1283
1284   myMesh->SetIsModified( true );
1285
1286   SMESH_CATCH( SMESH::throwCorbaException );
1287 }
1288
1289 //=============================================================================
1290 /*!
1291  * \brief Store node position on an edge
1292  * \param NodeID - node ID
1293  * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1294  * \param paramOnEdge - parameter on edge where the node is located
1295  * \retval boolean - false if any parameter is invalid
1296  */
1297 //=============================================================================
1298
1299 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1300                                        CORBA::Double paramOnEdge)
1301   throw (SALOME::SALOME_Exception)
1302 {
1303   SMESH_TRY;
1304
1305   SMESHDS_Mesh * mesh = getMeshDS();
1306   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1307   if ( !node )
1308     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1309
1310   if ( mesh->MaxShapeIndex() < EdgeID )
1311     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1312
1313   TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1314   if ( shape.ShapeType() != TopAbs_EDGE )
1315     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1316
1317   Standard_Real f,l;
1318   BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1319   if ( paramOnEdge < f || paramOnEdge > l )
1320     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1321
1322   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1323
1324   myMesh->SetIsModified( true );
1325
1326   SMESH_CATCH( SMESH::throwCorbaException );
1327 }
1328
1329 //=============================================================================
1330 /*!
1331  * \brief Store node position on a face
1332  * \param NodeID - node ID
1333  * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1334  * \param u - U parameter on face where the node is located
1335  * \param v - V parameter on face where the node is located
1336  * \retval boolean - false if any parameter is invalid
1337  */
1338 //=============================================================================
1339
1340 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1341                                        CORBA::Double u, CORBA::Double v)
1342   throw (SALOME::SALOME_Exception)
1343 {
1344   SMESH_TRY;
1345   SMESHDS_Mesh * mesh = getMeshDS();
1346   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1347   if ( !node )
1348     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1349
1350   if ( mesh->MaxShapeIndex() < FaceID )
1351     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1352
1353   TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1354   if ( shape.ShapeType() != TopAbs_FACE )
1355     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1356
1357   BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1358   bool isOut = ( u < surf.FirstUParameter() ||
1359                  u > surf.LastUParameter()  ||
1360                  v < surf.FirstVParameter() ||
1361                  v > surf.LastVParameter() );
1362
1363   if ( isOut ) {
1364 #ifdef _DEBUG_
1365     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1366               << " u( " <<  surf.FirstUParameter()
1367               << "," <<  surf.LastUParameter()
1368               << ") v( " <<  surf.FirstVParameter()
1369               << "," <<  surf.LastVParameter() << ")" );
1370 #endif
1371     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1372   }
1373
1374   mesh->SetNodeOnFace( node, FaceID, u, v );
1375   myMesh->SetIsModified( true );
1376
1377   SMESH_CATCH( SMESH::throwCorbaException );
1378 }
1379
1380 //=============================================================================
1381 /*!
1382  * \brief Bind a node to a solid
1383  * \param NodeID - node ID
1384  * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1385  * \retval boolean - false if NodeID or SolidID is invalid
1386  */
1387 //=============================================================================
1388
1389 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1390   throw (SALOME::SALOME_Exception)
1391 {
1392   SMESH_TRY;
1393   SMESHDS_Mesh * mesh = getMeshDS();
1394   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1395   if ( !node )
1396     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1397
1398   if ( mesh->MaxShapeIndex() < SolidID )
1399     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1400
1401   TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1402   if ( shape.ShapeType() != TopAbs_SOLID &&
1403        shape.ShapeType() != TopAbs_SHELL)
1404     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1405
1406   mesh->SetNodeInVolume( node, SolidID );
1407
1408   SMESH_CATCH( SMESH::throwCorbaException );
1409 }
1410
1411 //=============================================================================
1412 /*!
1413  * \brief Bind an element to a shape
1414  * \param ElementID - element ID
1415  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1416  * \retval boolean - false if ElementID or ShapeID is invalid
1417  */
1418 //=============================================================================
1419
1420 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1421                                                CORBA::Long ShapeID)
1422   throw (SALOME::SALOME_Exception)
1423 {
1424   SMESH_TRY;
1425   SMESHDS_Mesh * mesh = getMeshDS();
1426   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1427   if ( !elem )
1428     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1429
1430   if ( mesh->MaxShapeIndex() < ShapeID )
1431     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1432
1433   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1434   if ( shape.ShapeType() != TopAbs_EDGE &&
1435        shape.ShapeType() != TopAbs_FACE &&
1436        shape.ShapeType() != TopAbs_SOLID &&
1437        shape.ShapeType() != TopAbs_SHELL )
1438     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1439
1440   mesh->SetMeshElementOnShape( elem, ShapeID );
1441
1442   myMesh->SetIsModified( true );
1443
1444   SMESH_CATCH( SMESH::throwCorbaException );
1445 }
1446
1447 //=============================================================================
1448 /*!
1449  *
1450  */
1451 //=============================================================================
1452
1453 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1454                                                CORBA::Long NodeID2)
1455   throw (SALOME::SALOME_Exception)
1456 {
1457   SMESH_TRY;
1458   initData();
1459
1460   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1461   const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1462   if ( !n1 || !n2 )
1463     return false;
1464
1465   // Update Python script
1466   TPythonDump() << "isDone = " << this << ".InverseDiag( "
1467                 << NodeID1 << ", " << NodeID2 << " )";
1468
1469   int ret =  getEditor().InverseDiag ( n1, n2 );
1470
1471   declareMeshModified( /*isReComputeSafe=*/false );
1472   return ret;
1473
1474   SMESH_CATCH( SMESH::throwCorbaException );
1475   return 0;
1476 }
1477
1478 //=============================================================================
1479 /*!
1480  *
1481  */
1482 //=============================================================================
1483
1484 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1485                                               CORBA::Long NodeID2)
1486   throw (SALOME::SALOME_Exception)
1487 {
1488   SMESH_TRY;
1489   initData();
1490
1491   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1492   const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1493   if ( !n1 || !n2 )
1494     return false;
1495
1496   // Update Python script
1497   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1498                 << NodeID1 << ", " << NodeID2 <<  " )";
1499
1500
1501   bool stat = getEditor().DeleteDiag ( n1, n2 );
1502
1503   declareMeshModified( /*isReComputeSafe=*/!stat );
1504
1505   return stat;
1506
1507   SMESH_CATCH( SMESH::throwCorbaException );
1508   return 0;
1509 }
1510
1511 //=============================================================================
1512 /*!
1513  *
1514  */
1515 //=============================================================================
1516
1517 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1518   throw (SALOME::SALOME_Exception)
1519 {
1520   SMESH_TRY;
1521   initData();
1522
1523   for (int i = 0; i < IDsOfElements.length(); i++)
1524   {
1525     CORBA::Long index = IDsOfElements[i];
1526     const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1527     if ( elem )
1528       getEditor().Reorient( elem );
1529   }
1530   // Update Python script
1531   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1532
1533   declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1534   return true;
1535
1536   SMESH_CATCH( SMESH::throwCorbaException );
1537   return 0;
1538 }
1539
1540 //=============================================================================
1541 /*!
1542  *
1543  */
1544 //=============================================================================
1545
1546 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1547   throw (SALOME::SALOME_Exception)
1548 {
1549   SMESH_TRY;
1550   initData();
1551
1552   TPythonDump aTPythonDump; // suppress dump in Reorient()
1553
1554   SMESH::long_array_var anElementsId = theObject->GetIDs();
1555   CORBA::Boolean isDone = Reorient(anElementsId);
1556
1557   // Update Python script
1558   aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1559
1560   declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1561   return isDone;
1562
1563   SMESH_CATCH( SMESH::throwCorbaException );
1564   return 0;
1565 }
1566
1567 //=======================================================================
1568 //function : Reorient2D
1569 //purpose  : Reorient faces contained in \a the2Dgroup.
1570 //           the2Dgroup   - the mesh or its part to reorient
1571 //           theDirection - desired direction of normal of \a theFace
1572 //           theFace      - ID of face whose orientation is checked.
1573 //           It can be < 1 then \a thePoint is used to find a face.
1574 //           thePoint     - is used to find a face if \a theFace < 1.
1575 //           return number of reoriented elements.
1576 //=======================================================================
1577
1578 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1579                                            const SMESH::DirStruct&   theDirection,
1580                                            CORBA::Long               theFace,
1581                                            const SMESH::PointStruct& thePoint)
1582   throw (SALOME::SALOME_Exception)
1583 {
1584   SMESH_TRY;
1585   initData(/*deleteSearchers=*/false);
1586
1587   TIDSortedElemSet elements;
1588   if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1))
1589     THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1590
1591
1592   const SMDS_MeshElement* face = 0;
1593   if ( theFace > 0 )
1594   {
1595     face = getMeshDS()->FindElement( theFace );
1596     if ( !face )
1597       THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1598     if ( face->GetType() != SMDSAbs_Face )
1599       THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1600   }
1601   else
1602   {
1603     // create theElementSearcher if needed
1604     theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1605     if ( !theElementSearcher )
1606     {
1607       if ( elements.empty() ) // search in the whole mesh
1608       {
1609         if ( myMesh->NbFaces() == 0 )
1610           THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1611
1612         theElementSearcher = myEditor.GetElementSearcher();
1613       }
1614       else
1615       {
1616         typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1617         SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1618
1619         theElementSearcher = myEditor.GetElementSearcher(elemsIt);
1620       }
1621     }
1622     // find a face
1623     gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1624     face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1625
1626     if ( !face )
1627       THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1628     if ( !elements.empty() && !elements.count( face ))
1629       THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1630   }
1631
1632   const SMESH::PointStruct * P = &theDirection.PS;
1633   gp_Vec dirVec( P->x, P->y, P->z );
1634   if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1635     THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1636
1637   int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1638
1639   if ( nbReori ) {
1640     declareMeshModified( /*isReComputeSafe=*/false );
1641   }
1642   TPythonDump() << this << ".Reorient2D( "
1643                 << the2Dgroup << ", "
1644                 << theDirection << ", "
1645                 << theFace << ", "
1646                 << thePoint << " )";
1647
1648   return nbReori;
1649
1650   SMESH_CATCH( SMESH::throwCorbaException );
1651   return 0;
1652 }
1653
1654 //=============================================================================
1655 /*!
1656  *
1657  */
1658 //=============================================================================
1659
1660 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
1661                                               SMESH::NumericalFunctor_ptr Criterion,
1662                                               CORBA::Double               MaxAngle)
1663   throw (SALOME::SALOME_Exception)
1664 {
1665   SMESH_TRY;
1666   initData();
1667
1668   SMESHDS_Mesh* aMesh = getMeshDS();
1669   TIDSortedElemSet faces;
1670   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1671
1672   SMESH::NumericalFunctor_i* aNumericalFunctor =
1673     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1674   SMESH::Controls::NumericalFunctorPtr aCrit;
1675   if ( !aNumericalFunctor )
1676     aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1677   else
1678     aCrit = aNumericalFunctor->GetNumericalFunctor();
1679
1680   // Update Python script
1681   TPythonDump() << "isDone = " << this << ".TriToQuad( "
1682                 << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1683
1684
1685   bool stat = getEditor().TriToQuad( faces, aCrit, MaxAngle );
1686
1687   declareMeshModified( /*isReComputeSafe=*/!stat );
1688   return stat;
1689
1690   SMESH_CATCH( SMESH::throwCorbaException );
1691   return 0;
1692 }
1693
1694 //=============================================================================
1695 /*!
1696  *
1697  */
1698 //=============================================================================
1699
1700 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
1701                                                     SMESH::NumericalFunctor_ptr Criterion,
1702                                                     CORBA::Double               MaxAngle)
1703   throw (SALOME::SALOME_Exception)
1704 {
1705   SMESH_TRY;
1706   initData();
1707
1708   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
1709   SMESH::long_array_var anElementsId = theObject->GetIDs();
1710   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1711
1712   SMESH::NumericalFunctor_i* aNumericalFunctor =
1713     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1714
1715   // Update Python script
1716   aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1717                << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1718
1719   return isDone;
1720
1721   SMESH_CATCH( SMESH::throwCorbaException );
1722   return 0;
1723 }
1724
1725 //=============================================================================
1726 /*!
1727  *
1728  */
1729 //=============================================================================
1730
1731 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
1732                                               SMESH::NumericalFunctor_ptr Criterion)
1733   throw (SALOME::SALOME_Exception)
1734 {
1735   SMESH_TRY;
1736   initData();
1737
1738   SMESHDS_Mesh* aMesh = getMeshDS();
1739   TIDSortedElemSet faces;
1740   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1741
1742   SMESH::NumericalFunctor_i* aNumericalFunctor =
1743     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1744   SMESH::Controls::NumericalFunctorPtr aCrit;
1745   if ( !aNumericalFunctor )
1746     aCrit.reset( new SMESH::Controls::AspectRatio() );
1747   else
1748     aCrit = aNumericalFunctor->GetNumericalFunctor();
1749
1750
1751   // Update Python script
1752   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1753
1754   CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1755
1756   declareMeshModified( /*isReComputeSafe=*/false );
1757   return stat;
1758
1759   SMESH_CATCH( SMESH::throwCorbaException );
1760   return 0;
1761 }
1762
1763
1764 //=============================================================================
1765 /*!
1766  *
1767  */
1768 //=============================================================================
1769 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1770                                                     SMESH::NumericalFunctor_ptr Criterion)
1771   throw (SALOME::SALOME_Exception)
1772 {
1773   SMESH_TRY;
1774   initData();
1775
1776   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
1777
1778   SMESH::long_array_var anElementsId = theObject->GetIDs();
1779   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1780
1781   SMESH::NumericalFunctor_i* aNumericalFunctor =
1782     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1783
1784   // Update Python script
1785   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1786
1787   declareMeshModified( /*isReComputeSafe=*/false );
1788   return isDone;
1789
1790   SMESH_CATCH( SMESH::throwCorbaException );
1791   return 0;
1792 }
1793
1794
1795 //=============================================================================
1796 /*!
1797  *
1798  */
1799 //=============================================================================
1800 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1801                                               CORBA::Boolean            Diag13)
1802   throw (SALOME::SALOME_Exception)
1803 {
1804   SMESH_TRY;
1805   initData();
1806
1807   SMESHDS_Mesh* aMesh = getMeshDS();
1808   TIDSortedElemSet faces;
1809   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1810
1811   // Update Python script
1812   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1813                 << IDsOfElements << ", " << Diag13 << " )";
1814
1815   CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1816
1817   declareMeshModified( /*isReComputeSafe=*/ !stat );
1818   return stat;
1819
1820   SMESH_CATCH( SMESH::throwCorbaException );
1821   return 0;
1822 }
1823
1824
1825 //=============================================================================
1826 /*!
1827  *
1828  */
1829 //=============================================================================
1830 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1831                                                     CORBA::Boolean            Diag13)
1832   throw (SALOME::SALOME_Exception)
1833 {
1834   SMESH_TRY;
1835   initData();
1836
1837   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
1838
1839   SMESH::long_array_var anElementsId = theObject->GetIDs();
1840   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1841
1842   // Update Python script
1843   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1844                << theObject << ", " << Diag13 << " )";
1845
1846   declareMeshModified( /*isReComputeSafe=*/!isDone );
1847   return isDone;
1848
1849   SMESH_CATCH( SMESH::throwCorbaException );
1850   return 0;
1851 }
1852
1853
1854 //=============================================================================
1855 /*!
1856  *  BestSplit
1857  */
1858 //=============================================================================
1859
1860 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
1861                                            SMESH::NumericalFunctor_ptr Criterion)
1862   throw (SALOME::SALOME_Exception)
1863 {
1864   SMESH_TRY;
1865   initData();
1866
1867   const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
1868   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1869   {
1870     SMESH::NumericalFunctor_i* aNumericalFunctor =
1871       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1872     SMESH::Controls::NumericalFunctorPtr aCrit;
1873     if (aNumericalFunctor)
1874       aCrit = aNumericalFunctor->GetNumericalFunctor();
1875     else
1876       aCrit.reset(new SMESH::Controls::AspectRatio());
1877
1878     int id = getEditor().BestSplit(quad, aCrit);
1879     declareMeshModified( /*isReComputeSafe=*/ id < 1 );
1880   }
1881
1882   SMESH_CATCH( SMESH::throwCorbaException );
1883   return 0;
1884 }
1885
1886 //================================================================================
1887 /*!
1888  * \brief Split volumic elements into tetrahedrons
1889  */
1890 //================================================================================
1891
1892 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
1893                                                 CORBA::Short              methodFlags)
1894   throw (SALOME::SALOME_Exception)
1895 {
1896   SMESH_TRY;
1897   initData();
1898
1899   SMESH::long_array_var anElementsId = elems->GetIDs();
1900   TIDSortedElemSet elemSet;
1901   arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume );
1902
1903   getEditor().SplitVolumesIntoTetra( elemSet, int( methodFlags ));
1904   declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
1905
1906   TPythonDump() << this << ".SplitVolumesIntoTetra( "
1907                 << elems << ", " << methodFlags << " )";
1908
1909   SMESH_CATCH( SMESH::throwCorbaException );
1910 }
1911
1912 //=======================================================================
1913 //function : Smooth
1914 //purpose  :
1915 //=======================================================================
1916
1917 CORBA::Boolean
1918 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
1919                            const SMESH::long_array &              IDsOfFixedNodes,
1920                            CORBA::Long                            MaxNbOfIterations,
1921                            CORBA::Double                          MaxAspectRatio,
1922                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1923   throw (SALOME::SALOME_Exception)
1924 {
1925   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1926                  MaxAspectRatio, Method, false );
1927 }
1928
1929
1930 //=======================================================================
1931 //function : SmoothParametric
1932 //purpose  :
1933 //=======================================================================
1934
1935 CORBA::Boolean
1936 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
1937                                      const SMESH::long_array &              IDsOfFixedNodes,
1938                                      CORBA::Long                            MaxNbOfIterations,
1939                                      CORBA::Double                          MaxAspectRatio,
1940                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
1941   throw (SALOME::SALOME_Exception)
1942 {
1943   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1944                  MaxAspectRatio, Method, true );
1945 }
1946
1947
1948 //=======================================================================
1949 //function : SmoothObject
1950 //purpose  :
1951 //=======================================================================
1952
1953 CORBA::Boolean
1954 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1955                                  const SMESH::long_array &              IDsOfFixedNodes,
1956                                  CORBA::Long                            MaxNbOfIterations,
1957                                  CORBA::Double                          MaxAspectRatio,
1958                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
1959   throw (SALOME::SALOME_Exception)
1960 {
1961   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1962                        MaxAspectRatio, Method, false);
1963 }
1964
1965
1966 //=======================================================================
1967 //function : SmoothParametricObject
1968 //purpose  :
1969 //=======================================================================
1970
1971 CORBA::Boolean
1972 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
1973                                            const SMESH::long_array &              IDsOfFixedNodes,
1974                                            CORBA::Long                            MaxNbOfIterations,
1975                                            CORBA::Double                          MaxAspectRatio,
1976                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1977   throw (SALOME::SALOME_Exception)
1978 {
1979   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1980                        MaxAspectRatio, Method, true);
1981 }
1982
1983
1984 //=============================================================================
1985 /*!
1986  *
1987  */
1988 //=============================================================================
1989
1990 CORBA::Boolean
1991 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1992                            const SMESH::long_array &              IDsOfFixedNodes,
1993                            CORBA::Long                            MaxNbOfIterations,
1994                            CORBA::Double                          MaxAspectRatio,
1995                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
1996                            bool                                   IsParametric)
1997   throw (SALOME::SALOME_Exception)
1998 {
1999   SMESH_TRY;
2000   initData();
2001
2002   SMESHDS_Mesh* aMesh = getMeshDS();
2003
2004   TIDSortedElemSet elements;
2005   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2006
2007   set<const SMDS_MeshNode*> fixedNodes;
2008   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2009     CORBA::Long index = IDsOfFixedNodes[i];
2010     const SMDS_MeshNode * node = aMesh->FindNode(index);
2011     if ( node )
2012       fixedNodes.insert( node );
2013   }
2014   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2015   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2016     method = ::SMESH_MeshEditor::CENTROIDAL;
2017
2018   getEditor().Smooth(elements, fixedNodes, method,
2019                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
2020
2021   declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2022
2023   // Update Python script
2024   TPythonDump() << "isDone = " << this << "."
2025                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2026                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
2027                 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2028                 << "SMESH.SMESH_MeshEditor."
2029                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2030                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2031
2032   return true;
2033
2034   SMESH_CATCH( SMESH::throwCorbaException );
2035   return 0;
2036 }
2037
2038
2039 //=============================================================================
2040 /*!
2041  *
2042  */
2043 //=============================================================================
2044
2045 CORBA::Boolean
2046 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
2047                                  const SMESH::long_array &              IDsOfFixedNodes,
2048                                  CORBA::Long                            MaxNbOfIterations,
2049                                  CORBA::Double                          MaxAspectRatio,
2050                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
2051                                  bool                                   IsParametric)
2052   throw (SALOME::SALOME_Exception)
2053 {
2054   SMESH_TRY;
2055   initData();
2056
2057   TPythonDump aTPythonDump;  // suppress dump in smooth()
2058
2059   SMESH::long_array_var anElementsId = theObject->GetIDs();
2060   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2061                                   MaxAspectRatio, Method, IsParametric);
2062
2063   // Update Python script
2064   aTPythonDump << "isDone = " << this << "."
2065                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2066                << theObject << ", " << IDsOfFixedNodes << ", "
2067                << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2068                << "SMESH.SMESH_MeshEditor."
2069                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2070                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2071
2072   return isDone;
2073
2074   SMESH_CATCH( SMESH::throwCorbaException );
2075   return 0;
2076 }
2077
2078
2079 //=============================================================================
2080 /*!
2081  *
2082  */
2083 //=============================================================================
2084
2085 void SMESH_MeshEditor_i::RenumberNodes()
2086   throw (SALOME::SALOME_Exception)
2087 {
2088   SMESH_TRY;
2089   // Update Python script
2090   TPythonDump() << this << ".RenumberNodes()";
2091
2092   getMeshDS()->Renumber( true );
2093
2094   SMESH_CATCH( SMESH::throwCorbaException );
2095 }
2096
2097 //=============================================================================
2098 /*!
2099  *
2100  */
2101 //=============================================================================
2102
2103 void SMESH_MeshEditor_i::RenumberElements()
2104   throw (SALOME::SALOME_Exception)
2105 {
2106   SMESH_TRY;
2107   // Update Python script
2108   TPythonDump() << this << ".RenumberElements()";
2109
2110   getMeshDS()->Renumber( false );
2111
2112   SMESH_CATCH( SMESH::throwCorbaException );
2113 }
2114
2115 //=======================================================================
2116 /*!
2117  * \brief Return groups by their IDs
2118  */
2119 //=======================================================================
2120
2121 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2122   throw (SALOME::SALOME_Exception)
2123 {
2124   SMESH_TRY;
2125   if ( !groupIDs )
2126     return 0;
2127   myMesh_i->CreateGroupServants();
2128   return myMesh_i->GetGroups( *groupIDs );
2129
2130   SMESH_CATCH( SMESH::throwCorbaException );
2131   return 0;
2132 }
2133
2134 //=======================================================================
2135 //function : rotationSweep
2136 //purpose  :
2137 //=======================================================================
2138
2139 SMESH::ListOfGroups*
2140 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
2141                                   const SMESH::AxisStruct & theAxis,
2142                                   CORBA::Double             theAngleInRadians,
2143                                   CORBA::Long               theNbOfSteps,
2144                                   CORBA::Double             theTolerance,
2145                                   const bool                theMakeGroups,
2146                                   const SMDSAbs_ElementType theElementType)
2147   throw (SALOME::SALOME_Exception)
2148 {
2149   SMESH_TRY;
2150   initData();
2151
2152   TIDSortedElemSet inElements, copyElements;
2153   arrayToSet(theIDsOfElements, getMeshDS(), inElements, theElementType);
2154
2155   TIDSortedElemSet* workElements = & inElements;
2156   bool              makeWalls=true;
2157   if ( myIsPreviewMode )
2158   {
2159     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2160     getPreviewMesh( SMDSAbs_Face )->Copy( inElements, copyElements, select, avoid );
2161     workElements = & copyElements;
2162     //makeWalls = false;
2163   }
2164
2165   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
2166               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2167
2168   ::SMESH_MeshEditor::PGroupIDs groupIds =
2169       getEditor().RotationSweep (*workElements, Ax1, theAngleInRadians,
2170                                  theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2171
2172   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2173
2174   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2175
2176   SMESH_CATCH( SMESH::throwCorbaException );
2177   return 0;
2178 }
2179
2180 //=======================================================================
2181 //function : RotationSweep
2182 //purpose  :
2183 //=======================================================================
2184
2185 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
2186                                        const SMESH::AxisStruct & theAxis,
2187                                        CORBA::Double             theAngleInRadians,
2188                                        CORBA::Long               theNbOfSteps,
2189                                        CORBA::Double             theTolerance)
2190   throw (SALOME::SALOME_Exception)
2191 {
2192   if ( !myIsPreviewMode ) {
2193     TPythonDump() << this << ".RotationSweep( "
2194                   << theIDsOfElements          << ", "
2195                   << theAxis                   << ", "
2196                   << TVar( theAngleInRadians ) << ", "
2197                   << TVar( theNbOfSteps      ) << ", "
2198                   << TVar( theTolerance      ) << " )";
2199   }
2200   rotationSweep(theIDsOfElements,
2201                 theAxis,
2202                 theAngleInRadians,
2203                 theNbOfSteps,
2204                 theTolerance,
2205                 false);
2206 }
2207
2208 //=======================================================================
2209 //function : RotationSweepMakeGroups
2210 //purpose  :
2211 //=======================================================================
2212
2213 SMESH::ListOfGroups*
2214 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2215                                             const SMESH::AxisStruct& theAxis,
2216                                             CORBA::Double            theAngleInRadians,
2217                                             CORBA::Long              theNbOfSteps,
2218                                             CORBA::Double            theTolerance)
2219   throw (SALOME::SALOME_Exception)
2220 {
2221   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2222
2223   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
2224                                                theAxis,
2225                                                theAngleInRadians,
2226                                                theNbOfSteps,
2227                                                theTolerance,
2228                                                true);
2229   if (!myIsPreviewMode) {
2230     dumpGroupsList(aPythonDump, aGroups);
2231     aPythonDump << this << ".RotationSweepMakeGroups( "
2232                 << theIDsOfElements        << ", "
2233                 << theAxis                   << ", "
2234                 << TVar( theAngleInRadians ) << ", "
2235                 << TVar( theNbOfSteps      ) << ", "
2236                 << TVar( theTolerance      ) << " )";
2237   }
2238   return aGroups;
2239 }
2240
2241 //=======================================================================
2242 //function : RotationSweepObject
2243 //purpose  :
2244 //=======================================================================
2245
2246 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2247                                              const SMESH::AxisStruct & theAxis,
2248                                              CORBA::Double             theAngleInRadians,
2249                                              CORBA::Long               theNbOfSteps,
2250                                              CORBA::Double             theTolerance)
2251   throw (SALOME::SALOME_Exception)
2252 {
2253   if ( !myIsPreviewMode ) {
2254     TPythonDump() << this << ".RotationSweepObject( "
2255                   << theObject << ", "
2256                   << theAxis << ", "
2257                   << theAngleInRadians << ", "
2258                   << theNbOfSteps << ", "
2259                   << theTolerance << " )";
2260   }
2261   SMESH::long_array_var anElementsId = theObject->GetIDs();
2262   rotationSweep(anElementsId,
2263                 theAxis,
2264                 theAngleInRadians,
2265                 theNbOfSteps,
2266                 theTolerance,
2267                 false);
2268 }
2269
2270 //=======================================================================
2271 //function : RotationSweepObject1D
2272 //purpose  :
2273 //=======================================================================
2274
2275 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2276                                                const SMESH::AxisStruct & theAxis,
2277                                                CORBA::Double             theAngleInRadians,
2278                                                CORBA::Long               theNbOfSteps,
2279                                                CORBA::Double             theTolerance)
2280   throw (SALOME::SALOME_Exception)
2281 {
2282   if ( !myIsPreviewMode ) {
2283     TPythonDump() << this << ".RotationSweepObject1D( "
2284                   << theObject                 << ", "
2285                   << theAxis                   << ", "
2286                   << TVar( theAngleInRadians ) << ", "
2287                   << TVar( theNbOfSteps      ) << ", "
2288                   << TVar( theTolerance      ) << " )";
2289   }
2290   SMESH::long_array_var anElementsId = theObject->GetIDs();
2291   rotationSweep(anElementsId,
2292                 theAxis,
2293                 theAngleInRadians,
2294                 theNbOfSteps,
2295                 theTolerance,
2296                 false,
2297                 SMDSAbs_Edge);
2298 }
2299
2300 //=======================================================================
2301 //function : RotationSweepObject2D
2302 //purpose  :
2303 //=======================================================================
2304
2305 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2306                                                const SMESH::AxisStruct & theAxis,
2307                                                CORBA::Double             theAngleInRadians,
2308                                                CORBA::Long               theNbOfSteps,
2309                                                CORBA::Double             theTolerance)
2310   throw (SALOME::SALOME_Exception)
2311 {
2312   if ( !myIsPreviewMode ) {
2313     TPythonDump() << this << ".RotationSweepObject2D( "
2314                   << theObject                 << ", "
2315                   << theAxis                   << ", "
2316                   << TVar( theAngleInRadians ) << ", "
2317                   << TVar( theNbOfSteps      ) << ", "
2318                   << TVar( theTolerance      ) << " )";
2319   }
2320   SMESH::long_array_var anElementsId = theObject->GetIDs();
2321   rotationSweep(anElementsId,
2322                 theAxis,
2323                 theAngleInRadians,
2324                 theNbOfSteps,
2325                 theTolerance,
2326                 false,
2327                 SMDSAbs_Face);
2328 }
2329
2330 //=======================================================================
2331 //function : RotationSweepObjectMakeGroups
2332 //purpose  :
2333 //=======================================================================
2334
2335 SMESH::ListOfGroups*
2336 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2337                                                   const SMESH::AxisStruct&  theAxis,
2338                                                   CORBA::Double             theAngleInRadians,
2339                                                   CORBA::Long               theNbOfSteps,
2340                                                   CORBA::Double             theTolerance)
2341   throw (SALOME::SALOME_Exception)
2342 {
2343   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2344
2345   SMESH::long_array_var anElementsId = theObject->GetIDs();
2346   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2347                                                theAxis,
2348                                                theAngleInRadians,
2349                                                theNbOfSteps,
2350                                                theTolerance,
2351                                                true);
2352   if (!myIsPreviewMode) {
2353     dumpGroupsList(aPythonDump, aGroups);
2354     aPythonDump << this << ".RotationSweepObjectMakeGroups( "
2355                 << theObject << ", "
2356                 << theAxis << ", "
2357                 << theAngleInRadians << ", "
2358                 << theNbOfSteps << ", "
2359                 << theTolerance << " )";
2360   }
2361   return aGroups;
2362 }
2363
2364 //=======================================================================
2365 //function : RotationSweepObject1DMakeGroups
2366 //purpose  :
2367 //=======================================================================
2368
2369 SMESH::ListOfGroups*
2370 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2371                                                     const SMESH::AxisStruct&  theAxis,
2372                                                     CORBA::Double             theAngleInRadians,
2373                                                     CORBA::Long               theNbOfSteps,
2374                                                     CORBA::Double             theTolerance)
2375   throw (SALOME::SALOME_Exception)
2376 {
2377   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2378
2379   SMESH::long_array_var anElementsId = theObject->GetIDs();
2380   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2381                                                theAxis,
2382                                                theAngleInRadians,
2383                                                theNbOfSteps,
2384                                                theTolerance,
2385                                                true,
2386                                                SMDSAbs_Edge);
2387   if (!myIsPreviewMode) {
2388     dumpGroupsList(aPythonDump, aGroups);
2389     aPythonDump << this << ".RotationSweepObject1DMakeGroups( "
2390                 << theObject                 << ", "
2391                 << theAxis                   << ", "
2392                 << TVar( theAngleInRadians ) << ", "
2393                 << TVar( theNbOfSteps )      << ", "
2394                 << TVar( theTolerance )      << " )";
2395   }
2396   return aGroups;
2397 }
2398
2399 //=======================================================================
2400 //function : RotationSweepObject2DMakeGroups
2401 //purpose  :
2402 //=======================================================================
2403
2404 SMESH::ListOfGroups*
2405 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2406                                                     const SMESH::AxisStruct&  theAxis,
2407                                                     CORBA::Double             theAngleInRadians,
2408                                                     CORBA::Long               theNbOfSteps,
2409                                                     CORBA::Double             theTolerance)
2410   throw (SALOME::SALOME_Exception)
2411 {
2412   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2413
2414   SMESH::long_array_var anElementsId = theObject->GetIDs();
2415   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2416                                                theAxis,
2417                                                theAngleInRadians,
2418                                                theNbOfSteps,
2419                                                theTolerance,
2420                                                true,
2421                                                SMDSAbs_Face);
2422   if (!myIsPreviewMode) {
2423     dumpGroupsList(aPythonDump, aGroups);
2424     aPythonDump << this << ".RotationSweepObject2DMakeGroups( "
2425                 << theObject                 << ", "
2426                 << theAxis                   << ", "
2427                 << TVar( theAngleInRadians ) << ", "
2428                 << TVar( theNbOfSteps      ) << ", "
2429                 << TVar( theTolerance      ) << " )";
2430   }
2431   return aGroups;
2432 }
2433
2434
2435 //=======================================================================
2436 //function : extrusionSweep
2437 //purpose  :
2438 //=======================================================================
2439
2440 SMESH::ListOfGroups*
2441 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
2442                                    const SMESH::DirStruct &  theStepVector,
2443                                    CORBA::Long               theNbOfSteps,
2444                                    bool                      theMakeGroups,
2445                                    const SMDSAbs_ElementType theElementType)
2446   throw (SALOME::SALOME_Exception)
2447 {
2448   SMESH_TRY;
2449   initData();
2450
2451   TIDSortedElemSet elements, copyElements;
2452   arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
2453
2454   const SMESH::PointStruct * P = &theStepVector.PS;
2455   gp_Vec stepVec( P->x, P->y, P->z );
2456
2457   TIDSortedElemSet* workElements = & elements;
2458
2459   SMDSAbs_ElementType aType = SMDSAbs_Face;
2460   if (theElementType == SMDSAbs_Node)
2461   {
2462     aType = SMDSAbs_Edge;
2463   }
2464   if ( myIsPreviewMode ) {
2465     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2466     getPreviewMesh( aType )->Copy( elements, copyElements, select, avoid );
2467     workElements = & copyElements;
2468     theMakeGroups = false;
2469   }
2470
2471   TElemOfElemListMap aHystory;
2472   ::SMESH_MeshEditor::PGroupIDs groupIds = 
2473       getEditor().ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
2474
2475   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2476
2477   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2478
2479   SMESH_CATCH( SMESH::throwCorbaException );
2480   return 0;
2481 }
2482
2483 //=======================================================================
2484 //function : ExtrusionSweep
2485 //purpose  :
2486 //=======================================================================
2487
2488 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
2489                                         const SMESH::DirStruct &  theStepVector,
2490                                         CORBA::Long               theNbOfSteps)
2491   throw (SALOME::SALOME_Exception)
2492 {
2493   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
2494   if (!myIsPreviewMode) {
2495     TPythonDump() << this << ".ExtrusionSweep( "
2496                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps) << " )";
2497   }
2498 }
2499
2500 //=======================================================================
2501 //function : ExtrusionSweep0D
2502 //purpose  :
2503 //=======================================================================
2504
2505 void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElements,
2506                                           const SMESH::DirStruct &  theStepVector,
2507                                           CORBA::Long               theNbOfSteps)
2508   throw (SALOME::SALOME_Exception)
2509 {
2510   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
2511   if (!myIsPreviewMode) {
2512     TPythonDump() << this << ".ExtrusionSweep0D( "
2513                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps)<< " )";
2514   }
2515 }
2516
2517 //=======================================================================
2518 //function : ExtrusionSweepObject
2519 //purpose  :
2520 //=======================================================================
2521
2522 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2523                                               const SMESH::DirStruct &  theStepVector,
2524                                               CORBA::Long               theNbOfSteps)
2525   throw (SALOME::SALOME_Exception)
2526 {
2527   SMESH::long_array_var anElementsId = theObject->GetIDs();
2528   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
2529   if (!myIsPreviewMode) {
2530     TPythonDump() << this << ".ExtrusionSweepObject( "
2531                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
2532   }
2533 }
2534
2535 //=======================================================================
2536 //function : ExtrusionSweepObject0D
2537 //purpose  :
2538 //=======================================================================
2539
2540 void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObject,
2541                                                 const SMESH::DirStruct &  theStepVector,
2542                                                 CORBA::Long               theNbOfSteps)
2543   throw (SALOME::SALOME_Exception)
2544 {
2545   SMESH::long_array_var anElementsId = theObject->GetIDs();
2546   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
2547   if ( !myIsPreviewMode ) {
2548     TPythonDump() << this << ".ExtrusionSweepObject0D( "
2549                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2550   }
2551 }
2552
2553 //=======================================================================
2554 //function : ExtrusionSweepObject1D
2555 //purpose  :
2556 //=======================================================================
2557
2558 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2559                                                 const SMESH::DirStruct &  theStepVector,
2560                                                 CORBA::Long               theNbOfSteps)
2561   throw (SALOME::SALOME_Exception)
2562 {
2563   SMESH::long_array_var anElementsId = theObject->GetIDs();
2564   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
2565   if ( !myIsPreviewMode ) {
2566     TPythonDump() << this << ".ExtrusionSweepObject1D( "
2567                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2568   }
2569 }
2570
2571 //=======================================================================
2572 //function : ExtrusionSweepObject2D
2573 //purpose  :
2574 //=======================================================================
2575
2576 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2577                                                 const SMESH::DirStruct &  theStepVector,
2578                                                 CORBA::Long               theNbOfSteps)
2579   throw (SALOME::SALOME_Exception)
2580 {
2581   SMESH::long_array_var anElementsId = theObject->GetIDs();
2582   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
2583   if ( !myIsPreviewMode ) {
2584     TPythonDump() << this << ".ExtrusionSweepObject2D( "
2585                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2586   }
2587 }
2588
2589 //=======================================================================
2590 //function : ExtrusionSweepMakeGroups
2591 //purpose  :
2592 //=======================================================================
2593
2594 SMESH::ListOfGroups*
2595 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2596                                              const SMESH::DirStruct&  theStepVector,
2597                                              CORBA::Long              theNbOfSteps)
2598   throw (SALOME::SALOME_Exception)
2599 {
2600   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2601
2602   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true);
2603
2604   if (!myIsPreviewMode) {
2605     dumpGroupsList(aPythonDump, aGroups);
2606     aPythonDump << this << ".ExtrusionSweepMakeGroups( " << theIDsOfElements
2607                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2608   }
2609   return aGroups;
2610 }
2611
2612 //=======================================================================
2613 //function : ExtrusionSweepMakeGroups0D
2614 //purpose  :
2615 //=======================================================================
2616
2617 SMESH::ListOfGroups*
2618 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOfElements,
2619                                                const SMESH::DirStruct&  theStepVector,
2620                                                CORBA::Long              theNbOfSteps)
2621   throw (SALOME::SALOME_Exception)
2622 {
2623   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2624
2625   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true,SMDSAbs_Node);
2626
2627   if (!myIsPreviewMode) {
2628     dumpGroupsList(aPythonDump, aGroups);
2629     aPythonDump << this << ".ExtrusionSweepMakeGroups0D( " << theIDsOfElements
2630                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2631   }
2632   return aGroups;
2633 }
2634
2635 //=======================================================================
2636 //function : ExtrusionSweepObjectMakeGroups
2637 //purpose  :
2638 //=======================================================================
2639
2640 SMESH::ListOfGroups*
2641 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2642                                                    const SMESH::DirStruct&   theStepVector,
2643                                                    CORBA::Long               theNbOfSteps)
2644   throw (SALOME::SALOME_Exception)
2645 {
2646   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2647
2648   SMESH::long_array_var anElementsId = theObject->GetIDs();
2649   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector, theNbOfSteps, true);
2650
2651   if (!myIsPreviewMode) {
2652     dumpGroupsList(aPythonDump, aGroups);
2653     aPythonDump << this << ".ExtrusionSweepObjectMakeGroups( " << theObject
2654                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2655   }
2656   return aGroups;
2657 }
2658
2659 //=======================================================================
2660 //function : ExtrusionSweepObject0DMakeGroups
2661 //purpose  :
2662 //=======================================================================
2663
2664 SMESH::ListOfGroups*
2665 SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2666                                                      const SMESH::DirStruct&   theStepVector,
2667                                                      CORBA::Long               theNbOfSteps)
2668   throw (SALOME::SALOME_Exception)
2669 {
2670   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2671
2672   SMESH::long_array_var anElementsId = theObject->GetIDs();
2673   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2674                                                  theNbOfSteps, true, SMDSAbs_Node);
2675   if (!myIsPreviewMode) {
2676     dumpGroupsList(aPythonDump, aGroups);
2677     aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
2678                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2679   }
2680   return aGroups;
2681 }
2682
2683 //=======================================================================
2684 //function : ExtrusionSweepObject1DMakeGroups
2685 //purpose  :
2686 //=======================================================================
2687
2688 SMESH::ListOfGroups*
2689 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2690                                                      const SMESH::DirStruct&   theStepVector,
2691                                                      CORBA::Long               theNbOfSteps)
2692   throw (SALOME::SALOME_Exception)
2693 {
2694   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2695
2696   SMESH::long_array_var anElementsId = theObject->GetIDs();
2697   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2698                                                  theNbOfSteps, true, SMDSAbs_Edge);
2699   if (!myIsPreviewMode) {
2700     dumpGroupsList(aPythonDump, aGroups);
2701     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
2702                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2703   }
2704   return aGroups;
2705 }
2706
2707 //=======================================================================
2708 //function : ExtrusionSweepObject2DMakeGroups
2709 //purpose  :
2710 //=======================================================================
2711
2712 SMESH::ListOfGroups*
2713 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2714                                                      const SMESH::DirStruct&   theStepVector,
2715                                                      CORBA::Long               theNbOfSteps)
2716   throw (SALOME::SALOME_Exception)
2717 {
2718   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2719
2720   SMESH::long_array_var anElementsId = theObject->GetIDs();
2721   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2722                                                  theNbOfSteps, true, SMDSAbs_Face);
2723   if (!myIsPreviewMode) {
2724     dumpGroupsList(aPythonDump, aGroups);
2725     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
2726                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2727   }
2728   return aGroups;
2729 }
2730
2731
2732 //=======================================================================
2733 //function : advancedExtrusion
2734 //purpose  :
2735 //=======================================================================
2736
2737 SMESH::ListOfGroups*
2738 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
2739                                       const SMESH::DirStruct &  theStepVector,
2740                                       CORBA::Long               theNbOfSteps,
2741                                       CORBA::Long               theExtrFlags,
2742                                       CORBA::Double             theSewTolerance,
2743                                       const bool                theMakeGroups)
2744   throw (SALOME::SALOME_Exception)
2745 {
2746   SMESH_TRY;
2747   initData();
2748
2749   TIDSortedElemSet elements;
2750   arrayToSet(theIDsOfElements, getMeshDS(), elements);
2751
2752   const SMESH::PointStruct * P = &theStepVector.PS;
2753   gp_Vec stepVec( P->x, P->y, P->z );
2754
2755   TElemOfElemListMap aHystory;
2756   ::SMESH_MeshEditor::PGroupIDs groupIds =
2757       getEditor().ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
2758                                   theMakeGroups, theExtrFlags, theSewTolerance);
2759
2760   declareMeshModified( /*isReComputeSafe=*/true );
2761
2762   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2763
2764   SMESH_CATCH( SMESH::throwCorbaException );
2765   return 0;
2766 }
2767
2768 //=======================================================================
2769 //function : AdvancedExtrusion
2770 //purpose  :
2771 //=======================================================================
2772
2773 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2774                                            const SMESH::DirStruct &  theStepVector,
2775                                            CORBA::Long               theNbOfSteps,
2776                                            CORBA::Long               theExtrFlags,
2777                                            CORBA::Double             theSewTolerance)
2778   throw (SALOME::SALOME_Exception)
2779 {
2780   if ( !myIsPreviewMode ) {
2781     TPythonDump() << "stepVector = " << theStepVector;
2782     TPythonDump() << this << ".AdvancedExtrusion("
2783                   << theIDsOfElements
2784                   << ", stepVector, "
2785                   << theNbOfSteps << ","
2786                   << theExtrFlags << ", "
2787                   << theSewTolerance <<  " )";
2788   }
2789   advancedExtrusion( theIDsOfElements,
2790                      theStepVector,
2791                      theNbOfSteps,
2792                      theExtrFlags,
2793                      theSewTolerance,
2794                      false);
2795 }
2796
2797 //=======================================================================
2798 //function : AdvancedExtrusionMakeGroups
2799 //purpose  :
2800 //=======================================================================
2801 SMESH::ListOfGroups*
2802 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
2803                                                 const SMESH::DirStruct&  theStepVector,
2804                                                 CORBA::Long              theNbOfSteps,
2805                                                 CORBA::Long              theExtrFlags,
2806                                                 CORBA::Double            theSewTolerance)
2807   throw (SALOME::SALOME_Exception)
2808 {
2809   if (!myIsPreviewMode) {
2810     TPythonDump() << "stepVector = " << theStepVector;
2811   }
2812   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2813
2814   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
2815                                                      theStepVector,
2816                                                      theNbOfSteps,
2817                                                      theExtrFlags,
2818                                                      theSewTolerance,
2819                                                      true);
2820
2821   if (!myIsPreviewMode) {
2822     dumpGroupsList(aPythonDump, aGroups);
2823     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
2824                 << theIDsOfElements
2825                 << ", stepVector, "
2826                 << theNbOfSteps << ","
2827                 << theExtrFlags << ", "
2828                 << theSewTolerance <<  " )";
2829   }
2830   return aGroups;
2831 }
2832
2833
2834 //================================================================================
2835 /*!
2836  * \brief Convert extrusion error to IDL enum
2837  */
2838 //================================================================================
2839
2840 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2841
2842 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
2843 {
2844   switch ( e ) {
2845     RETCASE( EXTR_OK );
2846     RETCASE( EXTR_NO_ELEMENTS );
2847     RETCASE( EXTR_PATH_NOT_EDGE );
2848     RETCASE( EXTR_BAD_PATH_SHAPE );
2849     RETCASE( EXTR_BAD_STARTING_NODE );
2850     RETCASE( EXTR_BAD_ANGLES_NUMBER );
2851     RETCASE( EXTR_CANT_GET_TANGENT );
2852   }
2853   return SMESH::SMESH_MeshEditor::EXTR_OK;
2854 }
2855
2856
2857 //=======================================================================
2858 //function : extrusionAlongPath
2859 //purpose  :
2860 //=======================================================================
2861 SMESH::ListOfGroups*
2862 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2863                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2864                                        GEOM::GEOM_Object_ptr       thePathShape,
2865                                        CORBA::Long                 theNodeStart,
2866                                        CORBA::Boolean              theHasAngles,
2867                                        const SMESH::double_array & theAngles,
2868                                        CORBA::Boolean              theHasRefPoint,
2869                                        const SMESH::PointStruct &  theRefPoint,
2870                                        const bool                  theMakeGroups,
2871                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
2872                                        const SMDSAbs_ElementType   theElementType)
2873   throw (SALOME::SALOME_Exception)
2874 {
2875   SMESH_TRY;
2876   MESSAGE("extrusionAlongPath");
2877   initData();
2878
2879   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
2880     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2881     return 0;
2882   }
2883   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2884
2885   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2886   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2887
2888   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
2889     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2890     return 0;
2891   }
2892
2893   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2894   if ( !nodeStart ) {
2895     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2896     return 0;
2897   }
2898
2899   TIDSortedElemSet elements;
2900   arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
2901
2902   list<double> angles;
2903   for (int i = 0; i < theAngles.length(); i++) {
2904     angles.push_back( theAngles[i] );
2905   }
2906
2907   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2908
2909   int nbOldGroups = myMesh->NbGroup();
2910
2911   ::SMESH_MeshEditor::Extrusion_Error error =
2912       getEditor().ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
2913                                     theHasAngles, angles, false,
2914                                     theHasRefPoint, refPnt, theMakeGroups );
2915
2916   declareMeshModified( /*isReComputeSafe=*/true );
2917   theError = convExtrError( error );
2918
2919   if ( theMakeGroups ) {
2920     list<int> groupIDs = myMesh->GetGroupIds();
2921     list<int>::iterator newBegin = groupIDs.begin();
2922     std::advance( newBegin, nbOldGroups ); // skip old groups
2923     groupIDs.erase( groupIDs.begin(), newBegin );
2924     return getGroups( & groupIDs );
2925   }
2926   return 0;
2927
2928   SMESH_CATCH( SMESH::throwCorbaException );
2929   return 0;
2930 }
2931
2932 //=======================================================================
2933 //function : extrusionAlongPathX
2934 //purpose  :
2935 //=======================================================================
2936
2937 SMESH::ListOfGroups*
2938 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
2939                                         SMESH::SMESH_IDSource_ptr  Path,
2940                                         CORBA::Long                NodeStart,
2941                                         CORBA::Boolean             HasAngles,
2942                                         const SMESH::double_array& Angles,
2943                                         CORBA::Boolean             LinearVariation,
2944                                         CORBA::Boolean             HasRefPoint,
2945                                         const SMESH::PointStruct&  RefPoint,
2946                                         bool                       MakeGroups,
2947                                         const SMDSAbs_ElementType  ElementType,
2948                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
2949   throw (SALOME::SALOME_Exception)
2950 {
2951   SMESH_TRY;
2952   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
2953
2954   initData();
2955
2956   list<double> angles;
2957   for (int i = 0; i < Angles.length(); i++) {
2958     angles.push_back( Angles[i] );
2959   }
2960   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
2961   int nbOldGroups = myMesh->NbGroup();
2962
2963   if ( Path->_is_nil() ) {
2964     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2965     return EmptyGr;
2966   }
2967
2968   TIDSortedElemSet elements, copyElements;
2969   arrayToSet(IDsOfElements, getMeshDS(), elements, ElementType);
2970
2971   TIDSortedElemSet* workElements = &elements;
2972
2973   if ( myIsPreviewMode )
2974   {
2975     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2976     getPreviewMesh( SMDSAbs_Face )->Copy( elements, copyElements, select, avoid );
2977     workElements = & copyElements;
2978     MakeGroups = false;
2979   }
2980
2981   ::SMESH_MeshEditor::Extrusion_Error error;
2982
2983   if ( SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path ))
2984   {
2985     // path as mesh
2986     SMDS_MeshNode* aNodeStart =
2987       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2988     if ( !aNodeStart ) {
2989       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2990       return EmptyGr;
2991     }
2992     error = getEditor().ExtrusionAlongTrack( *workElements, &(aMeshImp->GetImpl()), aNodeStart,
2993                                              HasAngles, angles, LinearVariation,
2994                                              HasRefPoint, refPnt, MakeGroups );
2995     declareMeshModified( /*isReComputeSafe=*/true );
2996   }
2997   else if ( SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path ))
2998   {
2999     // path as submesh
3000     SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
3001     aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
3002     SMDS_MeshNode* aNodeStart =
3003       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
3004     if ( !aNodeStart ) {
3005       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3006       return EmptyGr;
3007     }
3008     SMESH_subMesh* aSubMesh =
3009       aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
3010     error = getEditor().ExtrusionAlongTrack( *workElements, aSubMesh, aNodeStart,
3011                                              HasAngles, angles, LinearVariation,
3012                                              HasRefPoint, refPnt, MakeGroups );
3013     declareMeshModified( /*isReComputeSafe=*/true );
3014   }
3015   else if ( SMESH::DownCast<SMESH_Group_i*>( Path ))
3016   {
3017     // path as group of 1D elements
3018     // ????????
3019   }
3020   else
3021   {
3022     // invalid path
3023     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3024     return EmptyGr;
3025   }
3026
3027   Error = convExtrError( error );
3028
3029   if ( MakeGroups ) {
3030     list<int> groupIDs = myMesh->GetGroupIds();
3031     list<int>::iterator newBegin = groupIDs.begin();
3032     std::advance( newBegin, nbOldGroups ); // skip old groups
3033     groupIDs.erase( groupIDs.begin(), newBegin );
3034     return getGroups( & groupIDs );
3035   }
3036   return EmptyGr;
3037
3038   SMESH_CATCH( SMESH::throwCorbaException );