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