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