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