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