Salome HOME
22833: [CEA 1346] to extrude a group of faces following the normal of each face
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_MeshEditor_i.cxx
23 //  Author : Nicolas REJNERI
24 //  Module : SMESH
25
26 #ifdef WIN32
27 #define NOMINMAX
28 #endif
29
30 // A macro used in SMESH_TryCatch.hxx,
31 // it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
32 #define SMY_OWN_CATCH \
33   catch ( SALOME::SALOME_Exception & e ) { throw e; }
34
35 #include "SMESH_MeshEditor_i.hxx"
36
37 #include "SMDS_EdgePosition.hxx"
38 #include "SMDS_ElemIterator.hxx"
39 #include "SMDS_FacePosition.hxx"
40 #include "SMDS_IteratorOnIterators.hxx"
41 #include "SMDS_LinearEdge.hxx"
42 #include "SMDS_Mesh0DElement.hxx"
43 #include "SMDS_MeshFace.hxx"
44 #include "SMDS_MeshVolume.hxx"
45 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
46 #include "SMDS_SetIterator.hxx"
47 #include "SMDS_VolumeTool.hxx"
48 #include "SMESHDS_Group.hxx"
49 #include "SMESHDS_GroupOnGeom.hxx"
50 #include "SMESH_ControlsDef.hxx"
51 #include "SMESH_Filter_i.hxx"
52 #include "SMESH_Gen_i.hxx"
53 #include "SMESH_Group.hxx"
54 #include "SMESH_Group_i.hxx"
55 #include "SMESH_MeshAlgos.hxx"
56 #include "SMESH_MeshPartDS.hxx"
57 #include "SMESH_MesherHelper.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMeshEventListener.hxx"
60 #include "SMESH_subMesh_i.hxx"
61
62 #include <utilities.h>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <Utils_CorbaException.hxx>
65 #include <SALOMEDS_wrap.hxx>
66 #include <SALOME_GenericObj_i.hh>
67 #include <Basics_OCCTVersion.hxx>
68
69 #include <BRepAdaptor_Surface.hxx>
70 #include <BRep_Tool.hxx>
71 #include <TopExp_Explorer.hxx>
72 #include <TopoDS.hxx>
73 #include <TopoDS_Edge.hxx>
74 #include <TopoDS_Face.hxx>
75 #include <gp_Ax1.hxx>
76 #include <gp_Ax2.hxx>
77 #include <gp_Vec.hxx>
78
79 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
80 #define NO_CAS_CATCH
81 #endif
82
83 #include <Standard_Failure.hxx>
84
85 #ifdef NO_CAS_CATCH
86 #include <Standard_ErrorHandler.hxx>
87 #endif
88
89 #include <sstream>
90 #include <limits>
91
92 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
93
94 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
95
96 using namespace std;
97 using SMESH::TPythonDump;
98 using SMESH::TVar;
99
100 namespace MeshEditor_I {
101
102   //=============================================================================
103   /*!
104    * \brief Mesh to apply modifications for preview purposes
105    */
106   //=============================================================================
107
108   struct TPreviewMesh: public SMESH_Mesh
109   {
110     SMDSAbs_ElementType myPreviewType; // type to show
111     //!< Constructor
112     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
113       _isShapeToMesh = (_id =_studyId = 0);
114       _myMeshDS  = new SMESHDS_Mesh( _id, true );
115       myPreviewType = previewElements;
116     }
117     //!< Destructor
118     virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; }
119     //!< Copy a set of elements
120     void Copy(const TIDSortedElemSet & theElements,
121               TIDSortedElemSet&        theCopyElements,
122               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
123               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
124     {
125       // loop on theIDsOfElements
126       TIDSortedElemSet::const_iterator eIt = theElements.begin();
127       for ( ; eIt != theElements.end(); ++eIt )
128       {
129         const SMDS_MeshElement* anElem = *eIt;
130         if ( !anElem ) continue;
131         SMDSAbs_ElementType type = anElem->GetType();
132         if ( type == theAvoidType ||
133              ( theSelectType != SMDSAbs_All && type != theSelectType ))
134           continue;
135         const SMDS_MeshElement* anElemCopy;
136         if ( type == SMDSAbs_Node)
137           anElemCopy = Copy( cast2Node(anElem) );
138         else
139           anElemCopy = Copy( anElem );
140         if ( anElemCopy )
141           theCopyElements.insert( theCopyElements.end(), anElemCopy );
142       }
143     }
144     //!< Copy an element
145     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
146     {
147       // copy element nodes
148       int anElemNbNodes = anElem->NbNodes();
149       vector< int > anElemNodesID( anElemNbNodes ) ;
150       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
151       for ( int i = 0; itElemNodes->more(); i++)
152       {
153         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
154         Copy( anElemNode );
155         anElemNodesID[i] = anElemNode->GetID();
156       }
157
158       // creates a corresponding element on copied nodes
159       SMDS_MeshElement* anElemCopy = 0;
160       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
161       {
162         const SMDS_VtkVolume* ph =
163           dynamic_cast<const SMDS_VtkVolume*> (anElem);
164         if ( ph )
165           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
166             (anElemNodesID, ph->GetQuantities(),anElem->GetID());
167       }
168       else {
169         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
170                                                           anElem->GetType(),
171                                                           anElem->IsPoly() );
172       }
173       return anElemCopy;
174     }
175     //!< Copy a node
176     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
177     {
178       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
179                                       anElemNode->GetID());
180     }
181     void RemoveAll()
182     {
183       GetMeshDS()->ClearMesh();
184     }
185   };// struct TPreviewMesh
186
187   static SMESH_NodeSearcher *    theNodeSearcher    = 0;
188   static SMESH_ElementSearcher * theElementSearcher = 0;
189
190   //=============================================================================
191   /*!
192    * \brief Deleter of theNodeSearcher at any compute event occured
193    */
194   //=============================================================================
195
196   struct TSearchersDeleter : public SMESH_subMeshEventListener
197   {
198     SMESH_Mesh* myMesh;
199     string      myMeshPartIOR;
200     //!< Constructor
201     TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
202                                                      "SMESH_MeshEditor_i::TSearchersDeleter"),
203                          myMesh(0) {}
204     //!< Delete theNodeSearcher
205     static void Delete()
206     {
207       if ( theNodeSearcher )    delete theNodeSearcher;    theNodeSearcher    = 0;
208       if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
209     }
210     typedef map < int, SMESH_subMesh * > TDependsOnMap;
211     //!< The meshod called by submesh: do my main job
212     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
213                       SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
214     {
215       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
216         Delete();
217         Unset( sm->GetFather() );
218       }
219     }
220     //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
221     void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
222     {
223       if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
224       {
225         if ( myMesh ) {
226           Delete();
227           Unset( myMesh );
228         }
229         myMesh = mesh;
230         myMeshPartIOR = meshPartIOR;
231         SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
232         SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
233         while ( smIt->more() )
234         {
235           sm = smIt->next();
236           sm->SetEventListener( this, 0, sm );
237         }
238       }
239     }
240     //!<  delete self from all submeshes
241     void Unset(SMESH_Mesh* mesh)
242     {
243       if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
244         SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
245         while ( smIt->more() )
246           smIt->next()->DeleteEventListener( this );
247       }
248       myMesh = 0;
249     }
250
251   } theSearchersDeleter;
252
253   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
254   {
255     TCollection_AsciiString typeStr;
256     switch ( theMirrorType ) {
257     case  SMESH::SMESH_MeshEditor::POINT:
258       typeStr = "SMESH.SMESH_MeshEditor.POINT";
259       break;
260     case  SMESH::SMESH_MeshEditor::AXIS:
261       typeStr = "SMESH.SMESH_MeshEditor.AXIS";
262       break;
263     default:
264       typeStr = "SMESH.SMESH_MeshEditor.PLANE";
265     }
266     return typeStr;
267   }
268   //================================================================================
269   /*!
270    * \brief function for conversion of long_array to TIDSortedElemSet
271    * \param IDs - array of IDs
272    * \param aMesh - mesh
273    * \param aMap - collection to fill
274    * \param aType - element type
275    */
276   //================================================================================
277
278   void arrayToSet(const SMESH::long_array & IDs,
279                   const SMESHDS_Mesh*       aMesh,
280                   TIDSortedElemSet&         aMap,
281                   const SMDSAbs_ElementType aType = SMDSAbs_All,
282                   SMDS_MeshElement::Filter* aFilter = NULL)
283   {
284     SMDS_MeshElement::NonNullFilter filter1;
285     SMDS_MeshElement::TypeFilter    filter2( aType );
286
287     if ( aFilter == NULL )
288       aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
289     
290     SMDS_MeshElement::Filter & filter = *aFilter;
291
292     if ( aType == SMDSAbs_Node )
293       for (int i=0; i<IDs.length(); i++) {
294         const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
295         if ( filter( elem ))
296           aMap.insert( aMap.end(), elem );
297       }
298     else
299       for (int i=0; i<IDs.length(); i++) {
300         const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
301         if ( filter( elem ))
302           aMap.insert( aMap.end(), elem );
303       }
304   }
305   //================================================================================
306   /*!
307    * \brief Retrieve elements of given type from SMESH_IDSource
308    */
309   //================================================================================
310
311   enum IDSource_Error { IDSource_OK, IDSource_INVALID, IDSource_EMPTY };
312
313   bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
314                      const SMESHDS_Mesh*        theMeshDS,
315                      TIDSortedElemSet&          theElemSet,
316                      const SMDSAbs_ElementType  theType,
317                      const bool                 emptyIfIsMesh = false,
318                      IDSource_Error*            error = 0)
319
320   {
321     if ( error ) *error = IDSource_OK;
322
323     if ( CORBA::is_nil( theIDSource ) )
324     {
325       if ( error ) *error = IDSource_INVALID;
326       return false;
327     }
328     if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
329     {
330       if ( error && theMeshDS->GetMeshInfo().NbElements( theType ) == 0 )
331         *error = IDSource_EMPTY;
332       return true;
333     }
334     SMESH::long_array_var anIDs = theIDSource->GetIDs();
335     if ( anIDs->length() == 0 )
336     {
337       if ( error ) *error = IDSource_EMPTY;
338       return false;
339     }
340     SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
341     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
342     {
343       if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
344       {
345         arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
346       }
347       else
348       {
349         if ( error ) *error = IDSource_INVALID;
350         return false;
351       }
352     }
353     else
354     {
355       arrayToSet( anIDs, theMeshDS, theElemSet, theType);
356       if ( bool(anIDs->length()) != bool(theElemSet.size()))
357       {
358         if ( error ) *error = IDSource_INVALID;
359         return false;
360       }
361     }
362     return true;
363   }
364   //================================================================================
365   /*!
366    * \brief Retrieve nodes from SMESH_IDSource
367    */
368   //================================================================================
369
370   void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr  theObject,
371                          const SMESHDS_Mesh*        theMeshDS,
372                          TIDSortedNodeSet&          theNodeSet)
373
374   {
375     if ( CORBA::is_nil( theObject ) )
376       return;
377     SMESH::array_of_ElementType_var types = theObject->GetTypes();
378     SMESH::long_array_var     aElementsId = theObject->GetIDs();
379     if ( types->length() == 1 && types[0] == SMESH::NODE)
380     {
381       for(int i = 0; i < aElementsId->length(); i++)
382         if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
383           theNodeSet.insert( theNodeSet.end(), n);
384     }
385     else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
386     {
387       SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
388       while ( nIt->more( ))
389         if( const SMDS_MeshElement * elem = nIt->next() )
390           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
391     }
392     else
393     {
394       for(int i = 0; i < aElementsId->length(); i++)
395         if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
396           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
397     }
398   }
399
400   //================================================================================
401   /*!
402    * \brief Returns elements connected to the given elements
403    */
404   //================================================================================
405
406   void getElementsAround(const TIDSortedElemSet& theElements,
407                          const SMESHDS_Mesh*     theMeshDS,
408                          TIDSortedElemSet&       theElementsAround)
409   {
410     if ( theElements.empty() ) return;
411
412     SMDSAbs_ElementType elemType    = (*theElements.begin())->GetType();
413     bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
414     if ( sameElemType &&
415          theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
416       return; // all the elements are in theElements
417
418     if ( !sameElemType )
419       elemType = SMDSAbs_All;
420
421     vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
422
423     TIDSortedElemSet::const_iterator elemIt = theElements.begin();
424     for ( ; elemIt != theElements.end(); ++elemIt )
425     {
426       const SMDS_MeshElement* e = *elemIt;
427       int i = e->NbCornerNodes();
428       while ( --i != -1 )
429       {
430         const SMDS_MeshNode* n = e->GetNode( i );
431         if ( !isNodeChecked[ n->GetID() ])
432         {
433           isNodeChecked[ n->GetID() ] = true;
434           SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
435           while ( invIt->more() )
436           {
437             const SMDS_MeshElement* elemAround = invIt->next();
438             if ( !theElements.count( elemAround ))
439               theElementsAround.insert( elemAround );
440           }
441         }
442       }
443     }
444   }
445
446   //================================================================================
447   /*!
448    * \brief Return a string used to detect change of mesh part on which theElementSearcher
449    * is going to be used
450    */
451   //================================================================================
452
453   string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
454   {
455     string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
456     if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
457       // take into account passible group modification
458       partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
459     partIOR += SMESH_Comment( type );
460     return partIOR;
461   }
462
463 } // namespace MeshEditor_I
464
465 using namespace MeshEditor_I;
466
467 //=============================================================================
468 /*!
469  *
470  */
471 //=============================================================================
472
473 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
474   myMesh_i( theMesh ),
475   myMesh( &theMesh->GetImpl() ),
476   myEditor( myMesh ),
477   myIsPreviewMode ( isPreview ),
478   myPreviewMesh( 0 ),
479   myPreviewEditor( 0 )
480 {
481 }
482
483 //================================================================================
484 /*!
485  * \brief Destructor
486  */
487 //================================================================================
488
489 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
490 {
491   PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
492   PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
493   poa->deactivate_object(anObjectId.in());
494
495   //deleteAuxIDSources();
496   delete myPreviewMesh;   myPreviewMesh = 0;
497   delete myPreviewEditor; myPreviewEditor = 0;
498 }
499
500 //================================================================================
501 /*!
502  * \brief Clear members
503  */
504 //================================================================================
505
506 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
507 {
508   if ( myIsPreviewMode ) {
509     if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
510   }
511   else {
512     if ( deleteSearchers )
513       TSearchersDeleter::Delete();
514   }
515   getEditor().GetError().reset();
516   getEditor().CrearLastCreated();
517 }
518
519 //================================================================================
520 /*!
521  * \brief Increment mesh modif time and optionally record that the performed
522  *        modification may influence futher mesh re-compute.
523  *  \param [in] isReComputeSafe - true if the modification does not infulence
524  *              futher mesh re-compute
525  */
526 //================================================================================
527
528 void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
529 {
530   myMesh->GetMeshDS()->Modified();
531   if ( !isReComputeSafe )
532     myMesh->SetIsModified( true );
533 }
534
535 //================================================================================
536 /*!
537  * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
538  *        WARNING: in preview mode call getPreviewMesh() before getEditor()!
539  */
540 //================================================================================
541
542 ::SMESH_MeshEditor& SMESH_MeshEditor_i::getEditor()
543 {
544   if ( myIsPreviewMode && !myPreviewEditor ) {
545     if ( !myPreviewMesh ) getPreviewMesh();
546     myPreviewEditor = new ::SMESH_MeshEditor( myPreviewMesh );
547   }
548   return myIsPreviewMode ? *myPreviewEditor : myEditor;
549 }
550
551 //================================================================================
552 /*!
553  * \brief Initialize and return myPreviewMesh
554  *  \param previewElements - type of elements to show in preview
555  *
556  *  WARNING: call it once par a method!
557  */
558 //================================================================================
559
560 TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewElements)
561 {
562   if ( !myPreviewMesh || myPreviewMesh->myPreviewType != previewElements )
563   {
564     delete myPreviewEditor;
565     myPreviewEditor = 0;
566     delete myPreviewMesh;
567     myPreviewMesh = new TPreviewMesh( previewElements );
568   }
569   myPreviewMesh->Clear();
570   return myPreviewMesh;
571 }
572
573 //================================================================================
574 /*!
575  * Return data of mesh edition preview
576  */
577 //================================================================================
578
579 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
580   throw (SALOME::SALOME_Exception)
581
582   SMESH_TRY;
583   const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
584
585   if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
586
587     list<int> aNodesConnectivity;
588     typedef map<int, int> TNodesMap;
589     TNodesMap nodesMap;
590
591     SMESHDS_Mesh* aMeshDS;
592     std::auto_ptr< SMESH_MeshPartDS > aMeshPartDS;
593     if ( hasBadElems ) {
594       aMeshPartDS.reset( new SMESH_MeshPartDS( getEditor().GetError()->myBadElements ));
595       aMeshDS = aMeshPartDS.get();
596     }
597     else {
598       aMeshDS = getEditor().GetMeshDS();
599     }
600     myPreviewData = new SMESH::MeshPreviewStruct();
601     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
602
603     
604     SMDSAbs_ElementType previewType = SMDSAbs_All;
605     if ( !hasBadElems )
606       if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
607         previewType = aPreviewMesh->myPreviewType;
608         switch ( previewType ) {
609         case SMDSAbs_Edge  : break;
610         case SMDSAbs_Face  : break;
611         case SMDSAbs_Volume: break;
612         default:;
613           if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
614         }
615       }
616
617     myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
618     int i = 0, j = 0;
619     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
620
621     while ( itMeshElems->more() ) {
622       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
623       SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
624       while ( itElemNodes->more() ) {
625         const SMDS_MeshNode* aMeshNode = itElemNodes->next();
626         int aNodeID = aMeshNode->GetID();
627         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
628         if ( anIter == nodesMap.end() ) {
629           // filling the nodes coordinates
630           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
631           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
632           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
633           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
634           j++;
635         }
636         aNodesConnectivity.push_back(anIter->second);
637       }
638
639       // filling the elements types
640       SMDSAbs_ElementType aType = aMeshElem->GetType();
641       bool               isPoly = aMeshElem->IsPoly();
642       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
643       myPreviewData->elementTypes[i].isPoly           = isPoly;
644       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
645       i++;
646     }
647     myPreviewData->nodesXYZ.length( j );
648
649     // filling the elements connectivities
650     list<int>::iterator aConnIter = aNodesConnectivity.begin();
651     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
652     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
653       myPreviewData->elementConnectivities[i] = *aConnIter;
654   }
655   return myPreviewData._retn();
656
657   SMESH_CATCH( SMESH::throwCorbaException );
658   return 0;
659 }
660
661 //================================================================================
662 /*!
663  * \brief Returns list of it's IDs of created nodes
664  * \retval SMESH::long_array* - list of node ID
665  */
666 //================================================================================
667
668 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
669   throw (SALOME::SALOME_Exception)
670 {
671   SMESH_TRY;
672   SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
673
674   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
675   myLastCreatedNodes->length( aSeq.Length() );
676   for (int i = 1; i <= aSeq.Length(); i++)
677     myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
678
679   return myLastCreatedNodes._retn();
680   SMESH_CATCH( SMESH::throwCorbaException );
681   return 0;
682 }
683
684 //================================================================================
685 /*!
686  * \brief Returns list of it's IDs of created elements
687  * \retval SMESH::long_array* - list of elements' ID
688  */
689 //================================================================================
690
691 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
692   throw (SALOME::SALOME_Exception)
693 {
694   SMESH_TRY;
695   SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
696
697   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
698   myLastCreatedElems->length( aSeq.Length() );
699   for ( int i = 1; i <= aSeq.Length(); i++ )
700     myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
701
702   return myLastCreatedElems._retn();
703   SMESH_CATCH( SMESH::throwCorbaException );
704   return 0;
705 }
706
707 //=======================================================================
708 //function : ClearLastCreated
709 //purpose  : Clears sequences of last created elements and nodes 
710 //=======================================================================
711
712 void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
713 {
714   SMESH_TRY;
715   getEditor().CrearLastCreated();
716   SMESH_CATCH( SMESH::throwCorbaException );
717 }
718
719 //=======================================================================
720 /*
721  * Returns description of an error/warning occured during the last operation
722  * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
723  */
724 //=======================================================================
725
726 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
727   throw (SALOME::SALOME_Exception)
728 {
729   SMESH_TRY;
730   SMESH::ComputeError_var errOut = new SMESH::ComputeError;
731   SMESH_ComputeErrorPtr&  errIn  = getEditor().GetError();
732   if ( errIn && !errIn->IsOK() )
733   {
734     errOut->code       = -( errIn->myName < 0 ? errIn->myName + 1: errIn->myName ); // -1 -> 0
735     errOut->comment    = errIn->myComment.c_str();
736     errOut->subShapeID = -1;
737     errOut->hasBadMesh = !errIn->myBadElements.empty();
738   }
739   else
740   {
741     errOut->code       = 0;
742     errOut->subShapeID = -1;
743     errOut->hasBadMesh = false;
744   }
745
746   return errOut._retn();
747   SMESH_CATCH( SMESH::throwCorbaException );
748   return 0;
749 }
750
751 //=======================================================================
752 //function : MakeIDSource
753 //purpose  : Wrap a sequence of ids in a SMESH_IDSource.
754 //           Call UnRegister() as you fininsh using it!!
755 //=======================================================================
756
757 struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
758                                        public virtual SALOME::GenericObj_i
759 {
760   SMESH::long_array     _ids;
761   SMESH::ElementType    _type;
762   SMESH::SMESH_Mesh_ptr _mesh;
763   SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
764   SMESH::long_array* GetMeshInfo() { return 0; }
765   SMESH::long_array* GetNbElementsByType()
766   {
767     SMESH::long_array_var aRes = new SMESH::long_array();
768     aRes->length(SMESH::NB_ELEMENT_TYPES);
769     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
770       aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
771     return aRes._retn();  
772   }
773   SMESH::SMESH_Mesh_ptr GetMesh()  { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
774   bool IsMeshInfoCorrect()         { return true; }
775   SMESH::array_of_ElementType* GetTypes()
776   {
777     SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
778     if ( _ids.length() > 0 ) {
779       types->length( 1 );
780       types[0] = _type;
781     }
782     return types._retn();
783   }
784 };
785
786 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
787                                                            SMESH::ElementType       type)
788 {
789   _IDSource* idSrc = new _IDSource;
790   idSrc->_mesh = myMesh_i->_this();
791   idSrc->_ids  = ids;
792   idSrc->_type = type;
793   if ( type == SMESH::ALL && ids.length() > 0 )
794     idSrc->_type = myMesh_i->GetElementType( ids[0], true );
795
796   SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
797
798   return anIDSourceVar._retn();
799 }
800
801 bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
802 {
803   return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
804 }
805
806 CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
807                                                   int&                       nbIds)
808 {
809   if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
810   {
811     nbIds = (int) tmpIdSource->_ids.length();
812     return & tmpIdSource->_ids[0];
813   }
814   nbIds = 0;
815   return 0;
816 }
817
818 // void SMESH_MeshEditor_i::deleteAuxIDSources()
819 // {
820 //   std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
821 //   for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
822 //     delete *idSrcIt;
823 //   myAuxIDSources.clear();
824 // }
825
826 //=============================================================================
827 /*!
828  *
829  */
830 //=============================================================================
831
832 CORBA::Boolean
833 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
834   throw (SALOME::SALOME_Exception)
835 {
836   SMESH_TRY;
837   initData();
838
839   list< int > IdList;
840
841   for (int i = 0; i < IDsOfElements.length(); i++)
842     IdList.push_back( IDsOfElements[i] );
843
844   // Update Python script
845   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
846
847   // Remove Elements
848   bool ret = getEditor().Remove( IdList, false );
849
850   declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
851   return ret;
852
853   SMESH_CATCH( SMESH::throwCorbaException );
854   return 0;
855 }
856
857 //=============================================================================
858 /*!
859  *
860  */
861 //=============================================================================
862
863 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
864   throw (SALOME::SALOME_Exception)
865 {
866   SMESH_TRY;
867   initData();
868
869   list< int > IdList;
870   for (int i = 0; i < IDsOfNodes.length(); i++)
871     IdList.push_back( IDsOfNodes[i] );
872
873   // Update Python script
874   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
875
876   bool ret = getEditor().Remove( IdList, true );
877
878   declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
879   return ret;
880
881   SMESH_CATCH( SMESH::throwCorbaException );
882   return 0;
883 }
884
885 //=============================================================================
886 /*!
887  *
888  */
889 //=============================================================================
890
891 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
892   throw (SALOME::SALOME_Exception)
893 {
894   SMESH_TRY;
895   initData();
896
897   // Update Python script
898   TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
899
900   // Create filter to find all orphan nodes
901   SMESH::Controls::Filter::TIdSequence seq;
902   SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
903   SMESH::Controls::Filter::GetElementsId( getMeshDS(), predicate, seq );
904
905   // remove orphan nodes (if there are any)
906   list< int > IdList;
907   for ( int i = 0; i < seq.size(); i++ )
908     IdList.push_back( seq[i] );
909
910   int nbNodesBefore = myMesh->NbNodes();
911   getEditor().Remove( IdList, true );
912   int nbNodesAfter = myMesh->NbNodes();
913
914   declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
915   return nbNodesBefore - nbNodesAfter;
916
917   SMESH_CATCH( SMESH::throwCorbaException );
918   return 0;
919 }
920
921 //=============================================================================
922 /*!
923  * Add a new node.
924  */
925 //=============================================================================
926
927 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
928   throw (SALOME::SALOME_Exception)
929 {
930   SMESH_TRY;
931   initData();
932
933   const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
934
935   // Update Python script
936   TPythonDump() << "nodeID = " << this << ".AddNode( "
937                 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
938
939   declareMeshModified( /*isReComputeSafe=*/false );
940   return N->GetID();
941
942   SMESH_CATCH( SMESH::throwCorbaException );
943   return 0;
944 }
945
946 //=============================================================================
947 /*!
948  * Create 0D element on the given node.
949  */
950 //=============================================================================
951
952 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
953   throw (SALOME::SALOME_Exception)
954 {
955   SMESH_TRY;
956   initData();
957
958   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
959   SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
960
961   // Update Python script
962   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
963
964   declareMeshModified( /*isReComputeSafe=*/false );
965
966   return elem ? elem->GetID() : 0;
967
968   SMESH_CATCH( SMESH::throwCorbaException );
969   return 0;
970 }
971
972 //=============================================================================
973 /*!
974  * Create a ball element on the given node.
975  */
976 //=============================================================================
977
978 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
979   throw (SALOME::SALOME_Exception)
980 {
981   SMESH_TRY;
982   initData();
983
984   if ( diameter < std::numeric_limits<double>::min() )
985     THROW_SALOME_CORBA_EXCEPTION("Invalid diameter", SALOME::BAD_PARAM);
986
987   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
988   SMDS_MeshElement* elem = getMeshDS()->AddBall(aNode, diameter);
989
990   // Update Python script
991   TPythonDump() << "ballElem = "
992                 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
993
994   declareMeshModified( /*isReComputeSafe=*/false );
995   return elem ? elem->GetID() : 0;
996
997   SMESH_CATCH( SMESH::throwCorbaException );
998   return 0;
999 }
1000
1001 //=============================================================================
1002 /*!
1003  * Create an edge, either linear and quadratic (this is determed
1004  *  by number of given nodes, two or three)
1005  */
1006 //=============================================================================
1007
1008 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
1009   throw (SALOME::SALOME_Exception)
1010 {
1011   SMESH_TRY;
1012   initData();
1013
1014   int NbNodes = IDsOfNodes.length();
1015   SMDS_MeshElement* elem = 0;
1016   if (NbNodes == 2)
1017   {
1018     CORBA::Long index1 = IDsOfNodes[0];
1019     CORBA::Long index2 = IDsOfNodes[1];
1020     elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(index1),
1021                                  getMeshDS()->FindNode(index2));
1022
1023     // Update Python script
1024     TPythonDump() << "edge = " << this << ".AddEdge([ "
1025                   << index1 << ", " << index2 <<" ])";
1026   }
1027   if (NbNodes == 3) {
1028     CORBA::Long n1 = IDsOfNodes[0];
1029     CORBA::Long n2 = IDsOfNodes[1];
1030     CORBA::Long n12 = IDsOfNodes[2];
1031     elem = getMeshDS()->AddEdge( getMeshDS()->FindNode(n1),
1032                                  getMeshDS()->FindNode(n2),
1033                                  getMeshDS()->FindNode(n12));
1034     // Update Python script
1035     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
1036                   <<n1<<", "<<n2<<", "<<n12<<" ])";
1037   }
1038
1039   declareMeshModified( /*isReComputeSafe=*/false );
1040   return elem ? elem->GetID() : 0;
1041
1042   SMESH_CATCH( SMESH::throwCorbaException );
1043   return 0;
1044 }
1045
1046 //=============================================================================
1047 /*!
1048  *  AddFace
1049  */
1050 //=============================================================================
1051
1052 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
1053   throw (SALOME::SALOME_Exception)
1054 {
1055   SMESH_TRY;
1056   initData();
1057
1058   int NbNodes = IDsOfNodes.length();
1059   if (NbNodes < 3)
1060   {
1061     return 0;
1062   }
1063
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   SMDS_MeshElement* elem = 0;
1069   switch (NbNodes) {
1070   case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
1071   case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
1072   case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1073                                       nodes[4], nodes[5]); break;
1074   case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1075                                       nodes[4], nodes[5], nodes[6]); break;
1076   case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1077                                       nodes[4], nodes[5], nodes[6], nodes[7]); break;
1078   case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
1079                                       nodes[4], nodes[5], nodes[6], nodes[7],
1080                                       nodes[8] ); break;
1081   default: elem = getMeshDS()->AddPolygonalFace(nodes);
1082   }
1083
1084   // Update Python script
1085   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
1086
1087   declareMeshModified( /*isReComputeSafe=*/false );
1088
1089   return elem ? elem->GetID() : 0;
1090
1091   SMESH_CATCH( SMESH::throwCorbaException );
1092   return 0;
1093 }
1094
1095 //=============================================================================
1096 /*!
1097  *  AddPolygonalFace
1098  */
1099 //=============================================================================
1100 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
1101   throw (SALOME::SALOME_Exception)
1102 {
1103   SMESH_TRY;
1104   initData();
1105
1106   int NbNodes = IDsOfNodes.length();
1107   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
1108   for (int i = 0; i < NbNodes; i++)
1109     nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
1110
1111   const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes);
1112
1113   // Update Python script
1114   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
1115
1116   declareMeshModified( /*isReComputeSafe=*/false );
1117   return elem ? elem->GetID() : 0;
1118
1119   SMESH_CATCH( SMESH::throwCorbaException );
1120   return 0;
1121 }
1122
1123 //=============================================================================
1124 /*!
1125  * Create volume, either linear and quadratic (this is determed
1126  *  by number of given nodes)
1127  */
1128 //=============================================================================
1129
1130 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
1131   throw (SALOME::SALOME_Exception)
1132 {
1133   SMESH_TRY;
1134   initData();
1135
1136   int NbNodes = IDsOfNodes.length();
1137   vector< const SMDS_MeshNode*> n(NbNodes);
1138   for(int i=0;i<NbNodes;i++)
1139     n[i]= getMeshDS()->FindNode(IDsOfNodes[i]);
1140
1141   SMDS_MeshElement* elem = 0;
1142   switch(NbNodes)
1143   {
1144   case 4 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
1145   case 5 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
1146   case 6 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
1147   case 8 :elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
1148   case 10:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1149                                         n[6],n[7],n[8],n[9]);
1150     break;
1151   case 12:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
1152                                         n[6],n[7],n[8],n[9],n[10],n[11]);
1153     break;
1154   case 13:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
1155                                         n[7],n[8],n[9],n[10],n[11],n[12]);
1156     break;
1157   case 15:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
1158                                         n[9],n[10],n[11],n[12],n[13],n[14]);
1159     break;
1160   case 20:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1161                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1162                                         n[15],n[16],n[17],n[18],n[19]);
1163     break;
1164   case 27:elem = getMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
1165                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
1166                                         n[15],n[16],n[17],n[18],n[19],
1167                                         n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
1168     break;
1169   }
1170
1171   // Update Python script
1172   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
1173
1174   declareMeshModified( /*isReComputeSafe=*/false );
1175   return elem ? elem->GetID() : 0;
1176
1177   SMESH_CATCH( SMESH::throwCorbaException );
1178   return 0;
1179 }
1180
1181 //=============================================================================
1182 /*!
1183  *  AddPolyhedralVolume
1184  */
1185 //=============================================================================
1186 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
1187                                                      const SMESH::long_array & Quantities)
1188   throw (SALOME::SALOME_Exception)
1189 {
1190   SMESH_TRY;
1191   initData();
1192
1193   int NbNodes = IDsOfNodes.length();
1194   std::vector<const SMDS_MeshNode*> n (NbNodes);
1195   for (int i = 0; i < NbNodes; i++)
1196     {
1197       const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDsOfNodes[i]);
1198       if (!aNode) return 0;
1199       n[i] = aNode;
1200     }
1201
1202   int NbFaces = Quantities.length();
1203   std::vector<int> q (NbFaces);
1204   for (int j = 0; j < NbFaces; j++)
1205     q[j] = Quantities[j];
1206
1207   const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(n, q);
1208
1209   // Update Python script
1210   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
1211                 << IDsOfNodes << ", " << Quantities << " )";
1212
1213   declareMeshModified( /*isReComputeSafe=*/false );
1214   return elem ? elem->GetID() : 0;
1215
1216   SMESH_CATCH( SMESH::throwCorbaException );
1217   return 0;
1218 }
1219
1220 //=============================================================================
1221 /*!
1222  *  AddPolyhedralVolumeByFaces
1223  */
1224 //=============================================================================
1225
1226 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
1227   throw (SALOME::SALOME_Exception)
1228 {
1229   SMESH_TRY;
1230   initData();
1231
1232   int NbFaces = IdsOfFaces.length();
1233   std::vector<const SMDS_MeshNode*> poly_nodes;
1234   std::vector<int> quantities (NbFaces);
1235
1236   for (int i = 0; i < NbFaces; i++) {
1237     const SMDS_MeshElement* aFace = getMeshDS()->FindElement(IdsOfFaces[i]);
1238     quantities[i] = aFace->NbNodes();
1239
1240     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
1241     while (It->more()) {
1242       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
1243     }
1244   }
1245
1246   const SMDS_MeshElement* elem = getMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
1247
1248   // Update Python script
1249   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
1250                 << IdsOfFaces << " )";
1251
1252   declareMeshModified( /*isReComputeSafe=*/false );
1253   return elem ? elem->GetID() : 0;
1254
1255   SMESH_CATCH( SMESH::throwCorbaException );
1256   return 0;
1257 }
1258
1259 //=============================================================================
1260 //
1261 // \brief Create 0D elements on all nodes of the given object except those 
1262 //        nodes on which a 0D element already exists.
1263 //  \param theObject object on whose nodes 0D elements will be created.
1264 //  \param theGroupName optional name of a group to add 0D elements created
1265 //         and/or found on nodes of \a theObject.
1266 //  \return an object (a new group or a temporary SMESH_IDSource) holding
1267 //          ids of new and/or found 0D elements.
1268 //
1269 //=============================================================================
1270
1271 SMESH::SMESH_IDSource_ptr
1272 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
1273                                                const char*               theGroupName)
1274   throw (SALOME::SALOME_Exception)
1275 {
1276   SMESH_TRY;
1277   initData();
1278
1279   SMESH::SMESH_IDSource_var result;
1280   TPythonDump pyDump;
1281
1282   TIDSortedElemSet elements, elems0D;
1283   prepareIdSource( theObject );
1284   if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
1285     getEditor().Create0DElementsOnAllNodes( elements, elems0D );
1286
1287   SMESH::long_array_var newElems = new SMESH::long_array;
1288   newElems->length( elems0D.size() );
1289   TIDSortedElemSet::iterator eIt = elems0D.begin();
1290   for ( size_t i = 0; i < elems0D.size(); ++i, ++eIt )
1291     newElems[ i ] = (*eIt)->GetID();
1292
1293   SMESH::SMESH_GroupBase_var groupToFill;
1294   if ( theGroupName && strlen( theGroupName ))
1295   {
1296     // Get existing group named theGroupName
1297     SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
1298     for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
1299       SMESH::SMESH_GroupBase_var group = groups[i];
1300       if ( !group->_is_nil() ) {
1301         CORBA::String_var name = group->GetName();
1302         if ( strcmp( name.in(), theGroupName ) == 0 && group->GetType() == SMESH::ELEM0D ) {
1303           groupToFill = group;
1304           break;
1305         }
1306       }
1307     }
1308     if ( groupToFill->_is_nil() )
1309       groupToFill = myMesh_i->CreateGroup( SMESH::ELEM0D, theGroupName );
1310     else if ( !SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1311       groupToFill = myMesh_i->ConvertToStandalone( groupToFill );
1312   }
1313
1314   if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* > ( groupToFill ))
1315   {
1316     group_i->Add( newElems );
1317     result = SMESH::SMESH_IDSource::_narrow( groupToFill );
1318     pyDump << groupToFill;
1319   }
1320   else
1321   {
1322     result = MakeIDSource( newElems, SMESH::ELEM0D );
1323     pyDump << "elem0DIDs";
1324   }
1325
1326   pyDump << " = " << this << ".Create0DElementsOnAllNodes( "
1327          << theObject << ", '" << theGroupName << "' )";
1328
1329   return result._retn();
1330
1331   SMESH_CATCH( SMESH::throwCorbaException );
1332   return 0;
1333 }
1334
1335 //=============================================================================
1336 /*!
1337  * \brief Bind a node to a vertex
1338  * \param NodeID - node ID
1339  * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1340  * \retval boolean - false if NodeID or VertexID is invalid
1341  */
1342 //=============================================================================
1343
1344 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
1345   throw (SALOME::SALOME_Exception)
1346 {
1347   SMESH_TRY;
1348
1349   SMESHDS_Mesh * mesh = getMeshDS();
1350   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1351   if ( !node )
1352     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1353
1354   if ( mesh->MaxShapeIndex() < VertexID )
1355     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1356
1357   TopoDS_Shape shape = mesh->IndexToShape( VertexID );
1358   if ( shape.ShapeType() != TopAbs_VERTEX )
1359     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
1360
1361   mesh->SetNodeOnVertex( node, VertexID );
1362
1363   myMesh->SetIsModified( true );
1364
1365   SMESH_CATCH( SMESH::throwCorbaException );
1366 }
1367
1368 //=============================================================================
1369 /*!
1370  * \brief Store node position on an edge
1371  * \param NodeID - node ID
1372  * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
1373  * \param paramOnEdge - parameter on edge where the node is located
1374  * \retval boolean - false if any parameter is invalid
1375  */
1376 //=============================================================================
1377
1378 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
1379                                        CORBA::Double paramOnEdge)
1380   throw (SALOME::SALOME_Exception)
1381 {
1382   SMESH_TRY;
1383
1384   SMESHDS_Mesh * mesh = getMeshDS();
1385   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1386   if ( !node )
1387     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1388
1389   if ( mesh->MaxShapeIndex() < EdgeID )
1390     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1391
1392   TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
1393   if ( shape.ShapeType() != TopAbs_EDGE )
1394     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
1395
1396   Standard_Real f,l;
1397   BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
1398   if ( paramOnEdge < f || paramOnEdge > l )
1399     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
1400
1401   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
1402
1403   myMesh->SetIsModified( true );
1404
1405   SMESH_CATCH( SMESH::throwCorbaException );
1406 }
1407
1408 //=============================================================================
1409 /*!
1410  * \brief Store node position on a face
1411  * \param NodeID - node ID
1412  * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
1413  * \param u - U parameter on face where the node is located
1414  * \param v - V parameter on face where the node is located
1415  * \retval boolean - false if any parameter is invalid
1416  */
1417 //=============================================================================
1418
1419 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
1420                                        CORBA::Double u, CORBA::Double v)
1421   throw (SALOME::SALOME_Exception)
1422 {
1423   SMESH_TRY;
1424   SMESHDS_Mesh * mesh = getMeshDS();
1425   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1426   if ( !node )
1427     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1428
1429   if ( mesh->MaxShapeIndex() < FaceID )
1430     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1431
1432   TopoDS_Shape shape = mesh->IndexToShape( FaceID );
1433   if ( shape.ShapeType() != TopAbs_FACE )
1434     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
1435
1436   BRepAdaptor_Surface surf( TopoDS::Face( shape ));
1437   bool isOut = ( u < surf.FirstUParameter() ||
1438                  u > surf.LastUParameter()  ||
1439                  v < surf.FirstVParameter() ||
1440                  v > surf.LastVParameter() );
1441
1442   if ( isOut ) {
1443 #ifdef _DEBUG_
1444     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
1445               << " u( " <<  surf.FirstUParameter()
1446               << "," <<  surf.LastUParameter()
1447               << ") v( " <<  surf.FirstVParameter()
1448               << "," <<  surf.LastVParameter() << ")" );
1449 #endif
1450     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
1451   }
1452
1453   mesh->SetNodeOnFace( node, FaceID, u, v );
1454   myMesh->SetIsModified( true );
1455
1456   SMESH_CATCH( SMESH::throwCorbaException );
1457 }
1458
1459 //=============================================================================
1460 /*!
1461  * \brief Bind a node to a solid
1462  * \param NodeID - node ID
1463  * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
1464  * \retval boolean - false if NodeID or SolidID is invalid
1465  */
1466 //=============================================================================
1467
1468 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
1469   throw (SALOME::SALOME_Exception)
1470 {
1471   SMESH_TRY;
1472   SMESHDS_Mesh * mesh = getMeshDS();
1473   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
1474   if ( !node )
1475     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
1476
1477   if ( mesh->MaxShapeIndex() < SolidID )
1478     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1479
1480   TopoDS_Shape shape = mesh->IndexToShape( SolidID );
1481   if ( shape.ShapeType() != TopAbs_SOLID &&
1482        shape.ShapeType() != TopAbs_SHELL)
1483     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
1484
1485   mesh->SetNodeInVolume( node, SolidID );
1486
1487   SMESH_CATCH( SMESH::throwCorbaException );
1488 }
1489
1490 //=============================================================================
1491 /*!
1492  * \brief Bind an element to a shape
1493  * \param ElementID - element ID
1494  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
1495  */
1496 //=============================================================================
1497
1498 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
1499                                                CORBA::Long ShapeID)
1500   throw (SALOME::SALOME_Exception)
1501 {
1502   SMESH_TRY;
1503   SMESHDS_Mesh * mesh = getMeshDS();
1504   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1505   if ( !elem )
1506     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1507
1508   if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
1509     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1510
1511   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1512   if ( shape.ShapeType() != TopAbs_EDGE &&
1513        shape.ShapeType() != TopAbs_FACE &&
1514        shape.ShapeType() != TopAbs_SOLID &&
1515        shape.ShapeType() != TopAbs_SHELL )
1516     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1517
1518   mesh->SetMeshElementOnShape( elem, ShapeID );
1519
1520   myMesh->SetIsModified( true );
1521
1522   SMESH_CATCH( SMESH::throwCorbaException );
1523 }
1524
1525 //=============================================================================
1526 /*!
1527  *
1528  */
1529 //=============================================================================
1530
1531 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1532                                                CORBA::Long NodeID2)
1533   throw (SALOME::SALOME_Exception)
1534 {
1535   SMESH_TRY;
1536   initData();
1537
1538   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1539   const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1540   if ( !n1 || !n2 )
1541     return false;
1542
1543   // Update Python script
1544   TPythonDump() << "isDone = " << this << ".InverseDiag( "
1545                 << NodeID1 << ", " << NodeID2 << " )";
1546
1547   int ret =  getEditor().InverseDiag ( n1, n2 );
1548
1549   declareMeshModified( /*isReComputeSafe=*/false );
1550   return ret;
1551
1552   SMESH_CATCH( SMESH::throwCorbaException );
1553   return 0;
1554 }
1555
1556 //=============================================================================
1557 /*!
1558  *
1559  */
1560 //=============================================================================
1561
1562 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1563                                               CORBA::Long NodeID2)
1564   throw (SALOME::SALOME_Exception)
1565 {
1566   SMESH_TRY;
1567   initData();
1568
1569   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
1570   const SMDS_MeshNode * n2 = getMeshDS()->FindNode( NodeID2 );
1571   if ( !n1 || !n2 )
1572     return false;
1573
1574   // Update Python script
1575   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1576                 << NodeID1 << ", " << NodeID2 <<  " )";
1577
1578
1579   bool stat = getEditor().DeleteDiag ( n1, n2 );
1580
1581   declareMeshModified( /*isReComputeSafe=*/!stat );
1582
1583   return stat;
1584
1585   SMESH_CATCH( SMESH::throwCorbaException );
1586   return 0;
1587 }
1588
1589 //=============================================================================
1590 /*!
1591  *
1592  */
1593 //=============================================================================
1594
1595 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1596   throw (SALOME::SALOME_Exception)
1597 {
1598   SMESH_TRY;
1599   initData();
1600
1601   for (int i = 0; i < IDsOfElements.length(); i++)
1602   {
1603     CORBA::Long index = IDsOfElements[i];
1604     const SMDS_MeshElement * elem = getMeshDS()->FindElement(index);
1605     if ( elem )
1606       getEditor().Reorient( elem );
1607   }
1608   // Update Python script
1609   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1610
1611   declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
1612   return true;
1613
1614   SMESH_CATCH( SMESH::throwCorbaException );
1615   return 0;
1616 }
1617
1618 //=============================================================================
1619 /*!
1620  *
1621  */
1622 //=============================================================================
1623
1624 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1625   throw (SALOME::SALOME_Exception)
1626 {
1627   SMESH_TRY;
1628   initData();
1629
1630   TPythonDump aTPythonDump; // suppress dump in Reorient()
1631
1632   prepareIdSource( theObject );
1633
1634   SMESH::long_array_var anElementsId = theObject->GetIDs();
1635   CORBA::Boolean isDone = Reorient(anElementsId);
1636
1637   // Update Python script
1638   aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1639
1640   declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
1641   return isDone;
1642
1643   SMESH_CATCH( SMESH::throwCorbaException );
1644   return 0;
1645 }
1646
1647 //=======================================================================
1648 //function : Reorient2D
1649 //purpose  : Reorient faces contained in \a the2Dgroup.
1650 //           the2Dgroup   - the mesh or its part to reorient
1651 //           theDirection - desired direction of normal of \a theFace
1652 //           theFace      - ID of face whose orientation is checked.
1653 //           It can be < 1 then \a thePoint is used to find a face.
1654 //           thePoint     - is used to find a face if \a theFace < 1.
1655 //           return number of reoriented elements.
1656 //=======================================================================
1657
1658 CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
1659                                            const SMESH::DirStruct&   theDirection,
1660                                            CORBA::Long               theFace,
1661                                            const SMESH::PointStruct& thePoint)
1662   throw (SALOME::SALOME_Exception)
1663 {
1664   SMESH_TRY;
1665   initData(/*deleteSearchers=*/false);
1666
1667   TIDSortedElemSet elements;
1668   prepareIdSource( the2Dgroup );
1669   IDSource_Error error;
1670   idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1671   if ( error == IDSource_EMPTY )
1672     return 0;
1673   if ( error == IDSource_INVALID )
1674     THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
1675
1676
1677   const SMDS_MeshElement* face = 0;
1678   if ( theFace > 0 )
1679   {
1680     face = getMeshDS()->FindElement( theFace );
1681     if ( !face )
1682       THROW_SALOME_CORBA_EXCEPTION("Inexistent face given", SALOME::BAD_PARAM);
1683     if ( face->GetType() != SMDSAbs_Face )
1684       THROW_SALOME_CORBA_EXCEPTION("Wrong element type", SALOME::BAD_PARAM);
1685   }
1686   else
1687   {
1688     // create theElementSearcher if needed
1689     theSearchersDeleter.Set( myMesh, getPartIOR( the2Dgroup, SMESH::FACE ));
1690     if ( !theElementSearcher )
1691     {
1692       if ( elements.empty() ) // search in the whole mesh
1693       {
1694         if ( myMesh->NbFaces() == 0 )
1695           THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
1696
1697         theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
1698       }
1699       else
1700       {
1701         typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
1702         SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
1703
1704         theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
1705       }
1706     }
1707     // find a face
1708     gp_Pnt p( thePoint.x, thePoint.y, thePoint.z );
1709     face = theElementSearcher->FindClosestTo( p, SMDSAbs_Face );
1710
1711     if ( !face )
1712       THROW_SALOME_CORBA_EXCEPTION("No face found by point", SALOME::INTERNAL_ERROR );
1713     if ( !elements.empty() && !elements.count( face ))
1714       THROW_SALOME_CORBA_EXCEPTION("Found face is not in the group", SALOME::BAD_PARAM );
1715   }
1716
1717   const SMESH::PointStruct * P = &theDirection.PS;
1718   gp_Vec dirVec( P->x, P->y, P->z );
1719   if ( dirVec.Magnitude() < std::numeric_limits< double >::min() )
1720     THROW_SALOME_CORBA_EXCEPTION("Zero size vector", SALOME::BAD_PARAM);
1721
1722   int nbReori = getEditor().Reorient2D( elements, dirVec, face );
1723
1724   if ( nbReori ) {
1725     declareMeshModified( /*isReComputeSafe=*/false );
1726   }
1727   TPythonDump() << this << ".Reorient2D( "
1728                 << the2Dgroup << ", "
1729                 << theDirection << ", "
1730                 << theFace << ", "
1731                 << thePoint << " )";
1732
1733   return nbReori;
1734
1735   SMESH_CATCH( SMESH::throwCorbaException );
1736   return 0;
1737 }
1738
1739 //=======================================================================
1740 //function : Reorient2DBy3D
1741 //purpose  : Reorient faces basing on orientation of adjacent volumes.
1742 //=======================================================================
1743
1744 CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
1745                                                SMESH::SMESH_IDSource_ptr     volumeGroup,
1746                                                CORBA::Boolean                outsideNormal)
1747   throw (SALOME::SALOME_Exception)
1748 {
1749   SMESH_TRY;
1750   initData();
1751
1752   TIDSortedElemSet volumes;
1753   prepareIdSource( volumeGroup );
1754   IDSource_Error volsError;
1755   idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
1756
1757   int nbReori = 0;
1758   for ( size_t i = 0; i < faceGroups.length(); ++i )
1759   {
1760     SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
1761     prepareIdSource( faceGrp );
1762
1763     TIDSortedElemSet faces;
1764     IDSource_Error error;
1765     idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
1766     if ( error == IDSource_INVALID && faceGroups.length() == 1 )
1767       THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
1768     if ( error == IDSource_OK && volsError != IDSource_OK )
1769       THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
1770
1771     nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
1772
1773     if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
1774       break;
1775   }
1776
1777   if ( nbReori ) {
1778     declareMeshModified( /*isReComputeSafe=*/false );
1779   }
1780   TPythonDump() << this << ".Reorient2DBy3D( "
1781                 << faceGroups << ", "
1782                 << volumeGroup << ", "
1783                 << outsideNormal << " )";
1784
1785   return nbReori;
1786
1787   SMESH_CATCH( SMESH::throwCorbaException );
1788   return 0;
1789 }
1790
1791 //=============================================================================
1792 /*!
1793  * \brief Fuse neighbour triangles into quadrangles.
1794  */
1795 //=============================================================================
1796
1797 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
1798                                               SMESH::NumericalFunctor_ptr Criterion,
1799                                               CORBA::Double               MaxAngle)
1800   throw (SALOME::SALOME_Exception)
1801 {
1802   SMESH_TRY;
1803   initData();
1804
1805   SMESHDS_Mesh* aMesh = getMeshDS();
1806   TIDSortedElemSet faces,copyFaces;
1807   SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1808   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1809   TIDSortedElemSet* workElements = & faces;
1810
1811   if ( myIsPreviewMode ) {
1812     SMDSAbs_ElementType select =  SMDSAbs_Face;
1813     getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1814     workElements = & copyFaces;
1815   }
1816
1817   SMESH::NumericalFunctor_i* aNumericalFunctor =
1818     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1819   SMESH::Controls::NumericalFunctorPtr aCrit;
1820   if ( !aNumericalFunctor )
1821     aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1822   else
1823     aCrit = aNumericalFunctor->GetNumericalFunctor();
1824
1825   if ( !myIsPreviewMode ) {
1826     // Update Python script
1827     TPythonDump() << "isDone = " << this << ".TriToQuad( "
1828                   << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1829   }
1830
1831   bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1832
1833   declareMeshModified( /*isReComputeSafe=*/!stat );
1834   return stat;
1835
1836   SMESH_CATCH( SMESH::throwCorbaException );
1837   return 0;
1838 }
1839
1840 //=============================================================================
1841 /*!
1842  * \brief Fuse neighbour triangles into quadrangles.
1843  */
1844 //=============================================================================
1845
1846 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
1847                                                     SMESH::NumericalFunctor_ptr Criterion,
1848                                                     CORBA::Double               MaxAngle)
1849   throw (SALOME::SALOME_Exception)
1850 {
1851   SMESH_TRY;
1852   initData();
1853
1854   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
1855
1856   prepareIdSource( theObject );
1857   SMESH::long_array_var anElementsId = theObject->GetIDs();
1858   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1859
1860   if ( !myIsPreviewMode ) {
1861     SMESH::NumericalFunctor_i* aNumericalFunctor =
1862       SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1863
1864     // Update Python script
1865     aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1866                  << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1867   }
1868
1869   return isDone;
1870
1871   SMESH_CATCH( SMESH::throwCorbaException );
1872   return 0;
1873 }
1874
1875 //=============================================================================
1876 /*!
1877  * \brief Split quadrangles into triangles.
1878  */
1879 //=============================================================================
1880
1881 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
1882                                               SMESH::NumericalFunctor_ptr Criterion)
1883   throw (SALOME::SALOME_Exception)
1884 {
1885   SMESH_TRY;
1886   initData();
1887
1888   SMESHDS_Mesh* aMesh = getMeshDS();
1889   TIDSortedElemSet faces;
1890   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1891
1892   SMESH::NumericalFunctor_i* aNumericalFunctor =
1893     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1894   SMESH::Controls::NumericalFunctorPtr aCrit;
1895   if ( !aNumericalFunctor )
1896     aCrit.reset( new SMESH::Controls::AspectRatio() );
1897   else
1898     aCrit = aNumericalFunctor->GetNumericalFunctor();
1899
1900
1901   // Update Python script
1902   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1903
1904   CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1905
1906   declareMeshModified( /*isReComputeSafe=*/false );
1907   return stat;
1908
1909   SMESH_CATCH( SMESH::throwCorbaException );
1910   return 0;
1911 }
1912
1913 //=============================================================================
1914 /*!
1915  * \brief Split quadrangles into triangles.
1916  */
1917 //=============================================================================
1918
1919 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1920                                                     SMESH::NumericalFunctor_ptr Criterion)
1921   throw (SALOME::SALOME_Exception)
1922 {
1923   SMESH_TRY;
1924   initData();
1925
1926   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
1927
1928   prepareIdSource( theObject );
1929   SMESH::long_array_var anElementsId = theObject->GetIDs();
1930   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1931
1932   SMESH::NumericalFunctor_i* aNumericalFunctor =
1933     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1934
1935   // Update Python script
1936   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1937
1938   declareMeshModified( /*isReComputeSafe=*/false );
1939   return isDone;
1940
1941   SMESH_CATCH( SMESH::throwCorbaException );
1942   return 0;
1943 }
1944
1945 //================================================================================
1946 /*!
1947  * \brief Split each of quadrangles into 4 triangles.
1948  *  \param [in] theObject - theQuads Container of quadrangles to split.
1949  */
1950 //================================================================================
1951
1952 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1953   throw (SALOME::SALOME_Exception)
1954 {
1955   SMESH_TRY;
1956   initData();
1957
1958   TIDSortedElemSet faces;
1959   prepareIdSource( theObject );
1960   if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1961        faces.empty() )
1962     THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1963
1964   getEditor().QuadTo4Tri( faces );
1965   TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1966
1967   SMESH_CATCH( SMESH::throwCorbaException );
1968 }
1969
1970 //=============================================================================
1971 /*!
1972  * \brief Split quadrangles into triangles.
1973  */
1974 //=============================================================================
1975
1976 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1977                                               CORBA::Boolean            Diag13)
1978   throw (SALOME::SALOME_Exception)
1979 {
1980   SMESH_TRY;
1981   initData();
1982
1983   SMESHDS_Mesh* aMesh = getMeshDS();
1984   TIDSortedElemSet faces;
1985   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1986
1987   // Update Python script
1988   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1989                 << IDsOfElements << ", " << Diag13 << " )";
1990
1991   CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1992
1993   declareMeshModified( /*isReComputeSafe=*/ !stat );
1994   return stat;
1995
1996   SMESH_CATCH( SMESH::throwCorbaException );
1997   return 0;
1998 }
1999
2000 //=============================================================================
2001 /*!
2002  * \brief Split quadrangles into triangles.
2003  */
2004 //=============================================================================
2005
2006 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
2007                                                     CORBA::Boolean            Diag13)
2008   throw (SALOME::SALOME_Exception)
2009 {
2010   SMESH_TRY;
2011   initData();
2012
2013   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
2014
2015   prepareIdSource( theObject );
2016   SMESH::long_array_var anElementsId = theObject->GetIDs();
2017   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
2018
2019   // Update Python script
2020   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
2021                << theObject << ", " << Diag13 << " )";
2022
2023   declareMeshModified( /*isReComputeSafe=*/!isDone );
2024   return isDone;
2025
2026   SMESH_CATCH( SMESH::throwCorbaException );
2027   return 0;
2028 }
2029
2030
2031 //=============================================================================
2032 /*!
2033  * Find better splitting of the given quadrangle.
2034  *  \param IDOfQuad  ID of the quadrangle to be splitted.
2035  *  \param Criterion A criterion to choose a diagonal for splitting.
2036  *  \return 1 if 1-3 diagonal is better, 2 if 2-4
2037  *          diagonal is better, 0 if error occurs.
2038  */
2039 //=============================================================================
2040
2041 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
2042                                            SMESH::NumericalFunctor_ptr Criterion)
2043   throw (SALOME::SALOME_Exception)
2044 {
2045   SMESH_TRY;
2046   initData();
2047
2048   const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
2049   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
2050   {
2051     SMESH::NumericalFunctor_i* aNumericalFunctor =
2052       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
2053     SMESH::Controls::NumericalFunctorPtr aCrit;
2054     if (aNumericalFunctor)
2055       aCrit = aNumericalFunctor->GetNumericalFunctor();
2056     else
2057       aCrit.reset(new SMESH::Controls::AspectRatio());
2058
2059     int id = getEditor().BestSplit(quad, aCrit);
2060     declareMeshModified( /*isReComputeSafe=*/ id < 1 );
2061     return id;
2062   }
2063
2064   SMESH_CATCH( SMESH::throwCorbaException );
2065   return 0;
2066 }
2067
2068 //================================================================================
2069 /*!
2070  * \brief Split volumic elements into tetrahedrons
2071  */
2072 //================================================================================
2073
2074 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
2075                                                 CORBA::Short              methodFlags)
2076   throw (SALOME::SALOME_Exception)
2077 {
2078   SMESH_TRY;
2079   initData();
2080   prepareIdSource( elems );
2081
2082   ::SMESH_MeshEditor::TFacetOfElem elemSet;
2083   const int noneFacet = -1;
2084   SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
2085   while( volIt->more() )
2086     elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
2087
2088   getEditor().SplitVolumes( elemSet, int( methodFlags ));
2089   declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2090
2091   TPythonDump() << this << ".SplitVolumesIntoTetra( "
2092                 << elems << ", " << methodFlags << " )";
2093
2094   SMESH_CATCH( SMESH::throwCorbaException );
2095 }
2096
2097 //================================================================================
2098 /*!
2099  * \brief Split hexahedra into triangular prisms
2100  *  \param elems - elements to split
2101  *  \param facetToSplitNormal - normal used to find a facet of hexahedron
2102  *         to split into triangles
2103  *  \param methodFlags - flags passing splitting method:
2104  *         1 - split the hexahedron into 2 prisms
2105  *         2 - split the hexahedron into 4 prisms
2106  */
2107 //================================================================================
2108
2109 void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr  elems,
2110                                                    const SMESH::PointStruct & startHexPoint,
2111                                                    const SMESH::DirStruct&    facetToSplitNormal,
2112                                                    CORBA::Short               methodFlags,
2113                                                    CORBA::Boolean             allDomains)
2114   throw (SALOME::SALOME_Exception)
2115 {
2116   SMESH_TRY;
2117   initData();
2118   prepareIdSource( elems );
2119
2120   gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
2121                             startHexPoint.y,
2122                             startHexPoint.z ),
2123                     gp_Dir( facetToSplitNormal.PS.x,
2124                             facetToSplitNormal.PS.y,
2125                             facetToSplitNormal.PS.z ));
2126   TIDSortedElemSet elemSet;
2127   SMESH::long_array_var anElementsId = elems->GetIDs();
2128   SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
2129   arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
2130
2131   ::SMESH_MeshEditor::TFacetOfElem elemFacets;
2132   while ( !elemSet.empty() )
2133   {
2134     getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
2135     if ( !allDomains )
2136       break;
2137
2138     ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
2139     for ( ; ef != elemFacets.end(); ++ef )
2140       elemSet.erase( ef->first );
2141   }
2142
2143   if ( methodFlags == 2 )
2144     methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
2145   else
2146     methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
2147
2148   getEditor().SplitVolumes( elemFacets, int( methodFlags ));
2149   declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2150
2151   TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
2152                 << elems << ", "
2153                 << startHexPoint << ", "
2154                 << facetToSplitNormal<< ", "
2155                 << methodFlags<< ", "
2156                 << allDomains << " )";
2157
2158   SMESH_CATCH( SMESH::throwCorbaException );
2159 }
2160
2161 //=======================================================================
2162 //function : Smooth
2163 //purpose  :
2164 //=======================================================================
2165
2166 CORBA::Boolean
2167 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
2168                            const SMESH::long_array &              IDsOfFixedNodes,
2169                            CORBA::Long                            MaxNbOfIterations,
2170                            CORBA::Double                          MaxAspectRatio,
2171                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
2172   throw (SALOME::SALOME_Exception)
2173 {
2174   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2175                  MaxAspectRatio, Method, false );
2176 }
2177
2178
2179 //=======================================================================
2180 //function : SmoothParametric
2181 //purpose  :
2182 //=======================================================================
2183
2184 CORBA::Boolean
2185 SMESH_MeshEditor_i::SmoothParametric(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, true );
2194 }
2195
2196
2197 //=======================================================================
2198 //function : SmoothObject
2199 //purpose  :
2200 //=======================================================================
2201
2202 CORBA::Boolean
2203 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
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 smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2211                        MaxAspectRatio, Method, false);
2212 }
2213
2214
2215 //=======================================================================
2216 //function : SmoothParametricObject
2217 //purpose  :
2218 //=======================================================================
2219
2220 CORBA::Boolean
2221 SMESH_MeshEditor_i::SmoothParametricObject(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, true);
2230 }
2231
2232
2233 //=============================================================================
2234 /*!
2235  *
2236  */
2237 //=============================================================================
2238
2239 CORBA::Boolean
2240 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
2241                            const SMESH::long_array &              IDsOfFixedNodes,
2242                            CORBA::Long                            MaxNbOfIterations,
2243                            CORBA::Double                          MaxAspectRatio,
2244                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
2245                            bool                                   IsParametric)
2246   throw (SALOME::SALOME_Exception)
2247 {
2248   SMESH_TRY;
2249   initData();
2250
2251   SMESHDS_Mesh* aMesh = getMeshDS();
2252
2253   TIDSortedElemSet elements;
2254   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2255
2256   set<const SMDS_MeshNode*> fixedNodes;
2257   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2258     CORBA::Long index = IDsOfFixedNodes[i];
2259     const SMDS_MeshNode * node = aMesh->FindNode(index);
2260     if ( node )
2261       fixedNodes.insert( node );
2262   }
2263   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2264   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2265     method = ::SMESH_MeshEditor::CENTROIDAL;
2266
2267   getEditor().Smooth(elements, fixedNodes, method,
2268                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
2269
2270   declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2271
2272   // Update Python script
2273   TPythonDump() << "isDone = " << this << "."
2274                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2275                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
2276                 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2277                 << "SMESH.SMESH_MeshEditor."
2278                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2279                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2280
2281   return true;
2282
2283   SMESH_CATCH( SMESH::throwCorbaException );
2284   return 0;
2285 }
2286
2287 //=============================================================================
2288 /*!
2289  *
2290  */
2291 //=============================================================================
2292
2293 CORBA::Boolean
2294 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
2295                                  const SMESH::long_array &              IDsOfFixedNodes,
2296                                  CORBA::Long                            MaxNbOfIterations,
2297                                  CORBA::Double                          MaxAspectRatio,
2298                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
2299                                  bool                                   IsParametric)
2300   throw (SALOME::SALOME_Exception)
2301 {
2302   SMESH_TRY;
2303   initData();
2304
2305   TPythonDump aTPythonDump;  // suppress dump in smooth()
2306
2307   prepareIdSource( theObject );
2308   SMESH::long_array_var anElementsId = theObject->GetIDs();
2309   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2310                                   MaxAspectRatio, Method, IsParametric);
2311
2312   // Update Python script
2313   aTPythonDump << "isDone = " << this << "."
2314                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2315                << theObject << ", " << IDsOfFixedNodes << ", "
2316                << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2317                << "SMESH.SMESH_MeshEditor."
2318                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2319                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2320
2321   return isDone;
2322
2323   SMESH_CATCH( SMESH::throwCorbaException );
2324   return 0;
2325 }
2326
2327 //=============================================================================
2328 /*!
2329  *
2330  */
2331 //=============================================================================
2332
2333 void SMESH_MeshEditor_i::RenumberNodes()
2334   throw (SALOME::SALOME_Exception)
2335 {
2336   SMESH_TRY;
2337   // Update Python script
2338   TPythonDump() << this << ".RenumberNodes()";
2339
2340   getMeshDS()->Renumber( true );
2341
2342   SMESH_CATCH( SMESH::throwCorbaException );
2343 }
2344
2345 //=============================================================================
2346 /*!
2347  *
2348  */
2349 //=============================================================================
2350
2351 void SMESH_MeshEditor_i::RenumberElements()
2352   throw (SALOME::SALOME_Exception)
2353 {
2354   SMESH_TRY;
2355   // Update Python script
2356   TPythonDump() << this << ".RenumberElements()";
2357
2358   getMeshDS()->Renumber( false );
2359
2360   SMESH_CATCH( SMESH::throwCorbaException );
2361 }
2362
2363 //=======================================================================
2364 /*!
2365  * \brief Return groups by their IDs
2366  */
2367 //=======================================================================
2368
2369 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2370   throw (SALOME::SALOME_Exception)
2371 {
2372   SMESH_TRY;
2373   if ( !groupIDs )
2374     return 0;
2375   myMesh_i->CreateGroupServants();
2376   return myMesh_i->GetGroups( *groupIDs );
2377
2378   SMESH_CATCH( SMESH::throwCorbaException );
2379   return 0;
2380 }
2381
2382 //=======================================================================
2383 //function : rotationSweep
2384 //purpose  :
2385 //=======================================================================
2386
2387 SMESH::ListOfGroups*
2388 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
2389                                   const SMESH::AxisStruct & theAxis,
2390                                   CORBA::Double             theAngleInRadians,
2391                                   CORBA::Long               theNbOfSteps,
2392                                   CORBA::Double             theTolerance,
2393                                   const bool                theMakeGroups,
2394                                   const SMDSAbs_ElementType theElementType)
2395   throw (SALOME::SALOME_Exception)
2396 {
2397   SMESH_TRY;
2398   initData();
2399
2400   TIDSortedElemSet inElements, copyElements;
2401   arrayToSet(theIDsOfElements, getMeshDS(), inElements, theElementType);
2402
2403   TIDSortedElemSet* workElements = & inElements;
2404   bool              makeWalls=true;
2405   if ( myIsPreviewMode )
2406   {
2407     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2408     getPreviewMesh( SMDSAbs_Face )->Copy( inElements, copyElements, select, avoid );
2409     workElements = & copyElements;
2410     //makeWalls = false;
2411   }
2412
2413   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
2414               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2415
2416   ::SMESH_MeshEditor::PGroupIDs groupIds =
2417       getEditor().RotationSweep (*workElements, Ax1, theAngleInRadians,
2418                                  theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2419
2420   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2421
2422   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2423
2424   SMESH_CATCH( SMESH::throwCorbaException );
2425   return 0;
2426 }
2427
2428 //=======================================================================
2429 //function : RotationSweep
2430 //purpose  :
2431 //=======================================================================
2432
2433 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
2434                                        const SMESH::AxisStruct & theAxis,
2435                                        CORBA::Double             theAngleInRadians,
2436                                        CORBA::Long               theNbOfSteps,
2437                                        CORBA::Double             theTolerance)
2438   throw (SALOME::SALOME_Exception)
2439 {
2440   if ( !myIsPreviewMode ) {
2441     TPythonDump() << this << ".RotationSweep( "
2442                   << theIDsOfElements          << ", "
2443                   << theAxis                   << ", "
2444                   << TVar( theAngleInRadians ) << ", "
2445                   << TVar( theNbOfSteps      ) << ", "
2446                   << TVar( theTolerance      ) << " )";
2447   }
2448   rotationSweep(theIDsOfElements,
2449                 theAxis,
2450                 theAngleInRadians,
2451                 theNbOfSteps,
2452                 theTolerance,
2453                 false);
2454 }
2455
2456 //=======================================================================
2457 //function : RotationSweepMakeGroups
2458 //purpose  :
2459 //=======================================================================
2460
2461 SMESH::ListOfGroups*
2462 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2463                                             const SMESH::AxisStruct& theAxis,
2464                                             CORBA::Double            theAngleInRadians,
2465                                             CORBA::Long              theNbOfSteps,
2466                                             CORBA::Double            theTolerance)
2467   throw (SALOME::SALOME_Exception)
2468 {
2469   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2470
2471   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
2472                                                theAxis,
2473                                                theAngleInRadians,
2474                                                theNbOfSteps,
2475                                                theTolerance,
2476                                                true);
2477   if (!myIsPreviewMode) {
2478     dumpGroupsList(aPythonDump, aGroups);
2479     aPythonDump << this << ".RotationSweepMakeGroups( "
2480                 << theIDsOfElements        << ", "
2481                 << theAxis                   << ", "
2482                 << TVar( theAngleInRadians ) << ", "
2483                 << TVar( theNbOfSteps      ) << ", "
2484                 << TVar( theTolerance      ) << " )";
2485   }
2486   return aGroups;
2487 }
2488
2489 //=======================================================================
2490 //function : RotationSweepObject
2491 //purpose  :
2492 //=======================================================================
2493
2494 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2495                                              const SMESH::AxisStruct & theAxis,
2496                                              CORBA::Double             theAngleInRadians,
2497                                              CORBA::Long               theNbOfSteps,
2498                                              CORBA::Double             theTolerance)
2499   throw (SALOME::SALOME_Exception)
2500 {
2501   if ( !myIsPreviewMode ) {
2502     TPythonDump() << this << ".RotationSweepObject( "
2503                   << theObject << ", "
2504                   << theAxis << ", "
2505                   << theAngleInRadians << ", "
2506                   << theNbOfSteps << ", "
2507                   << theTolerance << " )";
2508   }
2509   prepareIdSource( theObject );
2510   SMESH::long_array_var anElementsId = theObject->GetIDs();
2511   rotationSweep(anElementsId,
2512                 theAxis,
2513                 theAngleInRadians,
2514                 theNbOfSteps,
2515                 theTolerance,
2516                 false);
2517 }
2518
2519 //=======================================================================
2520 //function : RotationSweepObject1D
2521 //purpose  :
2522 //=======================================================================
2523
2524 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2525                                                const SMESH::AxisStruct & theAxis,
2526                                                CORBA::Double             theAngleInRadians,
2527                                                CORBA::Long               theNbOfSteps,
2528                                                CORBA::Double             theTolerance)
2529   throw (SALOME::SALOME_Exception)
2530 {
2531   if ( !myIsPreviewMode ) {
2532     TPythonDump() << this << ".RotationSweepObject1D( "
2533                   << theObject                 << ", "
2534                   << theAxis                   << ", "
2535                   << TVar( theAngleInRadians ) << ", "
2536                   << TVar( theNbOfSteps      ) << ", "
2537                   << TVar( theTolerance      ) << " )";
2538   }
2539   prepareIdSource( theObject );
2540   SMESH::long_array_var anElementsId = theObject->GetIDs();
2541   rotationSweep(anElementsId,
2542                 theAxis,
2543                 theAngleInRadians,
2544                 theNbOfSteps,
2545                 theTolerance,
2546                 false,
2547                 SMDSAbs_Edge);
2548 }
2549
2550 //=======================================================================
2551 //function : RotationSweepObject2D
2552 //purpose  :
2553 //=======================================================================
2554
2555 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2556                                                const SMESH::AxisStruct & theAxis,
2557                                                CORBA::Double             theAngleInRadians,
2558                                                CORBA::Long               theNbOfSteps,
2559                                                CORBA::Double             theTolerance)
2560   throw (SALOME::SALOME_Exception)
2561 {
2562   if ( !myIsPreviewMode ) {
2563     TPythonDump() << this << ".RotationSweepObject2D( "
2564                   << theObject                 << ", "
2565                   << theAxis                   << ", "
2566                   << TVar( theAngleInRadians ) << ", "
2567                   << TVar( theNbOfSteps      ) << ", "
2568                   << TVar( theTolerance      ) << " )";
2569   }
2570   prepareIdSource( theObject );
2571   SMESH::long_array_var anElementsId = theObject->GetIDs();
2572   rotationSweep(anElementsId,
2573                 theAxis,
2574                 theAngleInRadians,
2575                 theNbOfSteps,
2576                 theTolerance,
2577                 false,
2578                 SMDSAbs_Face);
2579 }
2580
2581 //=======================================================================
2582 //function : RotationSweepObjectMakeGroups
2583 //purpose  :
2584 //=======================================================================
2585
2586 SMESH::ListOfGroups*
2587 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2588                                                   const SMESH::AxisStruct&  theAxis,
2589                                                   CORBA::Double             theAngleInRadians,
2590                                                   CORBA::Long               theNbOfSteps,
2591                                                   CORBA::Double             theTolerance)
2592   throw (SALOME::SALOME_Exception)
2593 {
2594   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2595
2596   prepareIdSource( theObject );
2597   SMESH::long_array_var anElementsId = theObject->GetIDs();
2598   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2599                                                theAxis,
2600                                                theAngleInRadians,
2601                                                theNbOfSteps,
2602                                                theTolerance,
2603                                                true);
2604   if (!myIsPreviewMode) {
2605     dumpGroupsList(aPythonDump, aGroups);
2606     aPythonDump << this << ".RotationSweepObjectMakeGroups( "
2607                 << theObject << ", "
2608                 << theAxis << ", "
2609                 << theAngleInRadians << ", "
2610                 << theNbOfSteps << ", "
2611                 << theTolerance << " )";
2612   }
2613   return aGroups;
2614 }
2615
2616 //=======================================================================
2617 //function : RotationSweepObject1DMakeGroups
2618 //purpose  :
2619 //=======================================================================
2620
2621 SMESH::ListOfGroups*
2622 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2623                                                     const SMESH::AxisStruct&  theAxis,
2624                                                     CORBA::Double             theAngleInRadians,
2625                                                     CORBA::Long               theNbOfSteps,
2626                                                     CORBA::Double             theTolerance)
2627   throw (SALOME::SALOME_Exception)
2628 {
2629   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2630
2631   prepareIdSource( theObject );
2632   SMESH::long_array_var anElementsId = theObject->GetIDs();
2633   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2634                                                theAxis,
2635                                                theAngleInRadians,
2636                                                theNbOfSteps,
2637                                                theTolerance,
2638                                                true,
2639                                                SMDSAbs_Edge);
2640   if (!myIsPreviewMode) {
2641     dumpGroupsList(aPythonDump, aGroups);
2642     aPythonDump << this << ".RotationSweepObject1DMakeGroups( "
2643                 << theObject                 << ", "
2644                 << theAxis                   << ", "
2645                 << TVar( theAngleInRadians ) << ", "
2646                 << TVar( theNbOfSteps )      << ", "
2647                 << TVar( theTolerance )      << " )";
2648   }
2649   return aGroups;
2650 }
2651
2652 //=======================================================================
2653 //function : RotationSweepObject2DMakeGroups
2654 //purpose  :
2655 //=======================================================================
2656
2657 SMESH::ListOfGroups*
2658 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2659                                                     const SMESH::AxisStruct&  theAxis,
2660                                                     CORBA::Double             theAngleInRadians,
2661                                                     CORBA::Long               theNbOfSteps,
2662                                                     CORBA::Double             theTolerance)
2663   throw (SALOME::SALOME_Exception)
2664 {
2665   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2666
2667   prepareIdSource( theObject );
2668   SMESH::long_array_var anElementsId = theObject->GetIDs();
2669   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2670                                                theAxis,
2671                                                theAngleInRadians,
2672                                                theNbOfSteps,
2673                                                theTolerance,
2674                                                true,
2675                                                SMDSAbs_Face);
2676   if (!myIsPreviewMode) {
2677     dumpGroupsList(aPythonDump, aGroups);
2678     aPythonDump << this << ".RotationSweepObject2DMakeGroups( "
2679                 << theObject                 << ", "
2680                 << theAxis                   << ", "
2681                 << TVar( theAngleInRadians ) << ", "
2682                 << TVar( theNbOfSteps      ) << ", "
2683                 << TVar( theTolerance      ) << " )";
2684   }
2685   return aGroups;
2686 }
2687
2688 namespace MeshEditor_I
2689 {
2690   /*!
2691    * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
2692    */
2693   struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
2694   {
2695     bool myIsExtrusionByNormal;
2696
2697     static int makeFlags( CORBA::Boolean MakeGroups,
2698                           CORBA::Boolean ByAverageNormal = false,
2699                           CORBA::Boolean UseInputElemsOnly = false,
2700                           CORBA::Long    Flags = 0,
2701                           CORBA::Boolean MakeBoundary = true )
2702     {
2703       if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
2704       if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
2705       if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
2706       if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
2707       return Flags;
2708     }
2709     // standard params
2710     ExtrusionParams(const SMESH::DirStruct &  theDir,
2711                     CORBA::Long               theNbOfSteps,
2712                     CORBA::Boolean            theMakeGroups):
2713       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2714                                                 theDir.PS.y,
2715                                                 theDir.PS.z ),
2716                                         theNbOfSteps,
2717                                         makeFlags( theMakeGroups )),
2718       myIsExtrusionByNormal( false )
2719     {
2720     }
2721     // advanced params
2722     ExtrusionParams(const SMESH::DirStruct &  theDir,
2723                     CORBA::Long               theNbOfSteps,
2724                     CORBA::Boolean            theMakeGroups,
2725                     CORBA::Long               theExtrFlags,
2726                     CORBA::Double             theSewTolerance):
2727       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
2728                                                 theDir.PS.y,
2729                                                 theDir.PS.z ),
2730                                         theNbOfSteps,
2731                                         makeFlags( theMakeGroups, false, false,
2732                                                    theExtrFlags, false ),
2733                                         theSewTolerance ),
2734       myIsExtrusionByNormal( false )
2735     {
2736     }
2737     // params for extrusion by normal
2738     ExtrusionParams(CORBA::Double  theStepSize,
2739                     CORBA::Long    theNbOfSteps,
2740                     CORBA::Short   theDim,
2741                     CORBA::Boolean theUseInputElemsOnly,
2742                     CORBA::Boolean theByAverageNormal,
2743                     CORBA::Boolean theMakeGroups ):
2744       ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
2745                                         theNbOfSteps,
2746                                         makeFlags( theMakeGroups,
2747                                                    theByAverageNormal, theUseInputElemsOnly ),
2748                                         theDim),
2749       myIsExtrusionByNormal( true )
2750     {
2751     }
2752
2753     void SetNoGroups()
2754     {
2755       Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
2756     }
2757   };
2758 }
2759
2760 //=======================================================================
2761 //function : extrusionSweep
2762 //purpose  :
2763 //=======================================================================
2764
2765 SMESH::ListOfGroups*
2766 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array &      theIDsOfElements,
2767                                    MeshEditor_I::ExtrusionParams& theParams,
2768                                    const SMDSAbs_ElementType      theElementType)
2769   throw (SALOME::SALOME_Exception)
2770 {
2771   SMESH_TRY;
2772   initData();
2773
2774   TIDSortedElemSet elements, copyElements;
2775   arrayToSet( theIDsOfElements, getMeshDS(), elements, theElementType );
2776
2777   TIDSortedElemSet* workElements = & elements;
2778
2779   if ( myIsPreviewMode )
2780   {
2781     SMDSAbs_ElementType previewType = SMDSAbs_Face;
2782     if (theElementType == SMDSAbs_Node)
2783       previewType = SMDSAbs_Edge;
2784
2785     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2786     getPreviewMesh( previewType )->Copy( elements, copyElements, select, avoid );
2787     workElements = & copyElements;
2788     theParams.SetNoGroups();
2789
2790     if ( theParams.myIsExtrusionByNormal && !theParams.ToUseInpElemsOnly() )
2791     {
2792       TIDSortedElemSet elemsAround, elemsAroundCopy;
2793       getElementsAround( elements, getMeshDS(), elemsAround );
2794       getPreviewMesh( previewType )->Copy( elemsAround, elemsAroundCopy, select, avoid );
2795     }
2796   }
2797
2798   ::SMESH_MeshEditor::TTElemOfElemListMap aHystory;
2799   ::SMESH_MeshEditor::PGroupIDs groupIds =
2800       getEditor().ExtrusionSweep (*workElements, theParams, aHystory );
2801
2802   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2803
2804   return theParams.ToMakeGroups() ? getGroups(groupIds.get()) : 0;
2805
2806   SMESH_CATCH( SMESH::throwCorbaException );
2807   return 0;
2808 }
2809
2810 //=======================================================================
2811 //function : ExtrusionSweep
2812 //purpose  :
2813 //=======================================================================
2814
2815 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
2816                                         const SMESH::DirStruct &  theStepVector,
2817                                         CORBA::Long               theNbOfSteps)
2818   throw (SALOME::SALOME_Exception)
2819 {
2820   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2821   extrusionSweep( theIDsOfElements, params );
2822   if (!myIsPreviewMode) {
2823     TPythonDump() << this << ".ExtrusionSweep( "
2824                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps) << " )";
2825   }
2826 }
2827
2828 //=======================================================================
2829 //function : ExtrusionSweep0D
2830 //purpose  :
2831 //=======================================================================
2832
2833 void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElements,
2834                                           const SMESH::DirStruct &  theStepVector,
2835                                           CORBA::Long               theNbOfSteps)
2836   throw (SALOME::SALOME_Exception)
2837 {
2838   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2839   extrusionSweep( theIDsOfElements, params, SMDSAbs_Node );
2840   if (!myIsPreviewMode) {
2841     TPythonDump() << this << ".ExtrusionSweep0D( "
2842                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps)<< " )";
2843   }
2844 }
2845
2846 //=======================================================================
2847 //function : ExtrusionSweepObject
2848 //purpose  :
2849 //=======================================================================
2850
2851 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2852                                               const SMESH::DirStruct &  theStepVector,
2853                                               CORBA::Long               theNbOfSteps)
2854   throw (SALOME::SALOME_Exception)
2855 {
2856   prepareIdSource( theObject );
2857   SMESH::long_array_var anElementsId = theObject->GetIDs();
2858   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2859   extrusionSweep( anElementsId, params );
2860   if (!myIsPreviewMode) {
2861     TPythonDump() << this << ".ExtrusionSweepObject( "
2862                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
2863   }
2864 }
2865
2866 //=======================================================================
2867 //function : ExtrusionSweepObject0D
2868 //purpose  :
2869 //=======================================================================
2870
2871 void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObject,
2872                                                 const SMESH::DirStruct &  theStepVector,
2873                                                 CORBA::Long               theNbOfSteps)
2874   throw (SALOME::SALOME_Exception)
2875 {
2876   prepareIdSource( theObject );
2877   SMESH::long_array_var anElementsId = theObject->GetIDs();
2878   if ( anElementsId->length() == 0 )
2879     if ( SMESH_Mesh_i* mesh = SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
2880       anElementsId = mesh->GetNodesId();
2881
2882   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2883   extrusionSweep( anElementsId, params, SMDSAbs_Node );
2884   if ( !myIsPreviewMode ) {
2885     TPythonDump() << this << ".ExtrusionSweepObject0D( "
2886                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2887   }
2888 }
2889
2890 //=======================================================================
2891 //function : ExtrusionSweepObject1D
2892 //purpose  :
2893 //=======================================================================
2894
2895 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2896                                                 const SMESH::DirStruct &  theStepVector,
2897                                                 CORBA::Long               theNbOfSteps)
2898   throw (SALOME::SALOME_Exception)
2899 {
2900   prepareIdSource( theObject );
2901   SMESH::long_array_var anElementsId = theObject->GetIDs();
2902   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2903   extrusionSweep( anElementsId, params, SMDSAbs_Edge );
2904   if ( !myIsPreviewMode ) {
2905     TPythonDump() << this << ".ExtrusionSweepObject1D( "
2906                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2907   }
2908 }
2909
2910 //=======================================================================
2911 //function : ExtrusionSweepObject2D
2912 //purpose  :
2913 //=======================================================================
2914
2915 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2916                                                 const SMESH::DirStruct &  theStepVector,
2917                                                 CORBA::Long               theNbOfSteps)
2918   throw (SALOME::SALOME_Exception)
2919 {
2920   prepareIdSource( theObject );
2921   SMESH::long_array_var anElementsId = theObject->GetIDs();
2922   ExtrusionParams params( theStepVector, theNbOfSteps, false );
2923   extrusionSweep( anElementsId, params, SMDSAbs_Face );
2924   if ( !myIsPreviewMode ) {
2925     TPythonDump() << this << ".ExtrusionSweepObject2D( "
2926                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2927   }
2928 }
2929
2930 //=======================================================================
2931 //function : ExtrusionSweepMakeGroups
2932 //purpose  :
2933 //=======================================================================
2934
2935 SMESH::ListOfGroups*
2936 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2937                                              const SMESH::DirStruct&  theStepVector,
2938                                              CORBA::Long              theNbOfSteps)
2939   throw (SALOME::SALOME_Exception)
2940 {
2941   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2942
2943   ExtrusionParams params( theStepVector, theNbOfSteps, true );
2944   SMESH::ListOfGroups* aGroups = extrusionSweep( theIDsOfElements, params );
2945
2946   if (!myIsPreviewMode) {
2947     dumpGroupsList(aPythonDump, aGroups);
2948     aPythonDump << this << ".ExtrusionSweepMakeGroups( " << theIDsOfElements
2949                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2950   }
2951   return aGroups;
2952 }
2953
2954 //=======================================================================
2955 //function : ExtrusionSweepMakeGroups0D
2956 //purpose  :
2957 //=======================================================================
2958
2959 SMESH::ListOfGroups*
2960 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOfElements,
2961                                                const SMESH::DirStruct&  theStepVector,
2962                                                CORBA::Long              theNbOfSteps)
2963   throw (SALOME::SALOME_Exception)
2964 {
2965   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2966
2967   ExtrusionParams params( theStepVector, theNbOfSteps, true );
2968   SMESH::ListOfGroups* aGroups = extrusionSweep( theIDsOfElements, params, SMDSAbs_Node );
2969
2970   if (!myIsPreviewMode) {
2971     dumpGroupsList(aPythonDump, aGroups);
2972     aPythonDump << this << ".ExtrusionSweepMakeGroups0D( " << theIDsOfElements
2973                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2974   }
2975   return aGroups;
2976 }
2977
2978 //=======================================================================
2979 //function : ExtrusionSweepObjectMakeGroups
2980 //purpose  :
2981 //=======================================================================
2982
2983 SMESH::ListOfGroups*
2984 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2985                                                    const SMESH::DirStruct&   theStepVector,
2986                                                    CORBA::Long               theNbOfSteps)
2987   throw (SALOME::SALOME_Exception)
2988 {
2989   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2990
2991   prepareIdSource( theObject );
2992   SMESH::long_array_var anElementsId = theObject->GetIDs();
2993   ExtrusionParams params( theStepVector, theNbOfSteps, true );
2994   SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params );
2995
2996   if (!myIsPreviewMode) {
2997     dumpGroupsList(aPythonDump, aGroups);
2998     aPythonDump << this << ".ExtrusionSweepObjectMakeGroups( " << theObject
2999                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
3000   }
3001   return aGroups;
3002 }
3003
3004 //=======================================================================
3005 //function : ExtrusionSweepObject0DMakeGroups
3006 //purpose  :
3007 //=======================================================================
3008
3009 SMESH::ListOfGroups*
3010 SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3011                                                      const SMESH::DirStruct&   theStepVector,
3012                                                      CORBA::Long               theNbOfSteps)
3013   throw (SALOME::SALOME_Exception)
3014 {
3015   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3016
3017   prepareIdSource( theObject );
3018   SMESH::long_array_var anElementsId = theObject->GetIDs();
3019   ExtrusionParams params( theStepVector, theNbOfSteps, true );
3020   SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Node );
3021
3022   if (!myIsPreviewMode) {
3023     dumpGroupsList(aPythonDump, aGroups);
3024     aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
3025                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
3026   }
3027   return aGroups;
3028 }
3029
3030 //=======================================================================
3031 //function : ExtrusionSweepObject1DMakeGroups
3032 //purpose  :
3033 //=======================================================================
3034
3035 SMESH::ListOfGroups*
3036 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3037                                                      const SMESH::DirStruct&   theStepVector,
3038                                                      CORBA::Long               theNbOfSteps)
3039   throw (SALOME::SALOME_Exception)
3040 {
3041   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3042
3043   prepareIdSource( theObject );
3044   SMESH::long_array_var anElementsId = theObject->GetIDs();
3045   ExtrusionParams params( theStepVector, theNbOfSteps, true );
3046   SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Edge );
3047
3048   if (!myIsPreviewMode) {
3049     dumpGroupsList(aPythonDump, aGroups);
3050     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
3051                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
3052   }
3053   return aGroups;
3054 }
3055
3056 //=======================================================================
3057 //function : ExtrusionSweepObject2DMakeGroups
3058 //purpose  :
3059 //=======================================================================
3060
3061 SMESH::ListOfGroups*
3062 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3063                                                      const SMESH::DirStruct&   theStepVector,
3064                                                      CORBA::Long               theNbOfSteps)
3065   throw (SALOME::SALOME_Exception)
3066 {
3067   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3068
3069   prepareIdSource( theObject );
3070   SMESH::long_array_var anElementsId = theObject->GetIDs();
3071   ExtrusionParams params( theStepVector, theNbOfSteps, true );
3072   SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, SMDSAbs_Face );
3073
3074   if (!myIsPreviewMode) {
3075     dumpGroupsList(aPythonDump, aGroups);
3076     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
3077                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
3078   }
3079   return aGroups;
3080 }
3081
3082 //=======================================================================
3083 //function : ExtrusionByNormal
3084 //purpose  :
3085 //=======================================================================
3086
3087 SMESH::ListOfGroups*
3088 SMESH_MeshEditor_i::ExtrusionByNormal(SMESH::SMESH_IDSource_ptr object,
3089                                       CORBA::Double             stepSize,
3090                                       CORBA::Long               nbOfSteps,
3091                                       CORBA::Boolean            byAverageNormal,
3092                                       CORBA::Boolean            useInputElemsOnly,
3093                                       CORBA::Boolean            makeGroups,
3094                                       CORBA::Short              dim)
3095   throw (SALOME::SALOME_Exception)
3096 {
3097   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3098
3099   ExtrusionParams params( stepSize, nbOfSteps, dim,
3100                           byAverageNormal, useInputElemsOnly, makeGroups );
3101
3102   SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
3103   if ( !SMESH::DownCast<SMESH_Mesh_i*>( object ))
3104   {
3105     SMESH::array_of_ElementType_var elemTypes = object->GetTypes();
3106     if (( elemTypes->length() == 1 ) &&
3107         ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
3108       elemType = ( SMDSAbs_ElementType ) elemTypes[0];
3109   }
3110   prepareIdSource( object );
3111   SMESH::long_array_var anElementsId = object->GetIDs();
3112   SMESH::ListOfGroups* aGroups = extrusionSweep( anElementsId, params, elemType );
3113
3114   if (!myIsPreviewMode) {
3115     dumpGroupsList(aPythonDump, aGroups);
3116     aPythonDump << this << ".ExtrusionByNormal( " << object
3117                 << ", " << TVar( stepSize )
3118                 << ", " << TVar( nbOfSteps )
3119                 << ", " << byAverageNormal
3120                 << ", " << makeGroups
3121                 << ", " << dim
3122                 << " )";
3123   }
3124   return aGroups;
3125 }
3126
3127 //=======================================================================
3128 //function : AdvancedExtrusion
3129 //purpose  :
3130 //=======================================================================
3131
3132 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
3133                                            const SMESH::DirStruct &  theStepVector,
3134                                            CORBA::Long               theNbOfSteps,
3135                                            CORBA::Long               theExtrFlags,
3136                                            CORBA::Double             theSewTolerance)
3137   throw (SALOME::SALOME_Exception)
3138 {
3139   ExtrusionParams params( theStepVector, theNbOfSteps, false, theExtrFlags, theSewTolerance);
3140   extrusionSweep( theIDsOfElements, params );
3141
3142   if ( !myIsPreviewMode ) {
3143     TPythonDump() << "stepVector = " << theStepVector;
3144     TPythonDump() << this << ".AdvancedExtrusion("
3145                   << theIDsOfElements
3146                   << ", stepVector, "
3147                   << theNbOfSteps << ","
3148                   << theExtrFlags << ", "
3149                   << theSewTolerance <<  " )";
3150   }
3151 }
3152
3153 //=======================================================================
3154 //function : AdvancedExtrusionMakeGroups
3155 //purpose  :
3156 //=======================================================================
3157 SMESH::ListOfGroups*
3158 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
3159                                                 const SMESH::DirStruct&  theStepVector,
3160                                                 CORBA::Long              theNbOfSteps,
3161                                                 CORBA::Long              theExtrFlags,
3162                                                 CORBA::Double            theSewTolerance)
3163   throw (SALOME::SALOME_Exception)
3164 {
3165   if (!myIsPreviewMode) {
3166     TPythonDump() << "stepVector = " << theStepVector;
3167   }
3168   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3169
3170   ExtrusionParams params( theStepVector, theNbOfSteps, true, theExtrFlags, theSewTolerance);
3171   SMESH::ListOfGroups * aGroups = extrusionSweep( theIDsOfElements, params );
3172
3173   if (!myIsPreviewMode) {
3174     dumpGroupsList(aPythonDump, aGroups);
3175     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
3176                 << theIDsOfElements
3177                 << ", stepVector, "
3178                 << theNbOfSteps << ","
3179                 << theExtrFlags << ", "
3180                 << theSewTolerance <<  " )";
3181   }
3182   return aGroups;
3183 }
3184
3185
3186 //================================================================================
3187 /*!
3188  * \brief Convert extrusion error to IDL enum
3189  */
3190 //================================================================================
3191
3192 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
3193
3194 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
3195 {
3196   switch ( e ) {
3197     RETCASE( EXTR_OK );
3198     RETCASE( EXTR_NO_ELEMENTS );
3199     RETCASE( EXTR_PATH_NOT_EDGE );
3200     RETCASE( EXTR_BAD_PATH_SHAPE );
3201     RETCASE( EXTR_BAD_STARTING_NODE );
3202     RETCASE( EXTR_BAD_ANGLES_NUMBER );
3203     RETCASE( EXTR_CANT_GET_TANGENT );
3204   }
3205   return SMESH::SMESH_MeshEditor::EXTR_OK;
3206 }
3207
3208
3209 //=======================================================================
3210 //function : extrusionAlongPath
3211 //purpose  :
3212 //=======================================================================
3213 SMESH::ListOfGroups*
3214 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
3215                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
3216                                        GEOM::GEOM_Object_ptr       thePathShape,
3217                                        CORBA::Long                 theNodeStart,
3218                                        CORBA::Boolean              theHasAngles,
3219                                        const SMESH::double_array & theAngles,
3220                                        CORBA::Boolean              theHasRefPoint,
3221                                        const SMESH::PointStruct &  theRefPoint,
3222                                        const bool                  theMakeGroups,
3223                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
3224                                        const SMDSAbs_ElementType   theElementType)
3225   throw (SALOME::SALOME_Exception)
3226 {
3227   SMESH_TRY;
3228   MESSAGE("extrusionAlongPath");
3229   initData();
3230
3231   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
3232     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3233     return 0;
3234   }
3235   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3236
3237   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3238   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3239
3240   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
3241     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3242     return 0;
3243   }
3244
3245   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
3246   if ( !nodeStart ) {
3247     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3248     return 0;
3249   }
3250
3251   TIDSortedElemSet elements;
3252   arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
3253
3254   list<double> angles;
3255   for (int i = 0; i < theAngles.length(); i++) {
3256     angles.push_back( theAngles[i] );
3257   }
3258
3259   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
3260
3261   int nbOldGroups = myMesh->NbGroup();
3262
3263   ::SMESH_MeshEditor::Extrusion_Error error =
3264       getEditor().ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
3265                                     theHasAngles, angles, false,
3266                                     theHasRefPoint, refPnt, theMakeGroups );
3267
3268   declareMeshModified( /*isReComputeSafe=*/true );
3269   theError = convExtrError( error );
3270
3271   if ( theMakeGroups ) {
3272     list<int> groupIDs = myMesh->GetGroupIds();
3273     list<int>::iterator newBegin = groupIDs.begin();
3274     std::advance( newBegin, nbOldGroups ); // skip old groups
3275     groupIDs.erase( groupIDs.begin(), newBegin );
3276     return getGroups( & groupIDs );
3277   }
3278   return 0;
3279
3280   SMESH_CATCH( SMESH::throwCorbaException );
3281   return 0;
3282 }
3283
3284 //=======================================================================
3285 //function : extrusionAlongPathX
3286 //purpose  :
3287 //=======================================================================
3288
3289 SMESH::ListOfGroups*
3290 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
3291                                         SMESH::SMESH_IDSource_ptr  Path,
3292                                         CORBA::Long                NodeStart,
3293                                         CORBA::Boolean             HasAngles,
3294                                         const SMESH::double_array& Angles,
3295                                         CORBA::Boolean             LinearVariation,
3296                                         CORBA::Boolean             HasRefPoint,
3297                                         const SMESH::PointStruct&  RefPoint,
3298                                         bool                       MakeGroups,
3299                                         const SMDSAbs_ElementType  ElementType,
3300                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
3301   throw (SALOME::SALOME_Exception)
3302 {
3303   SMESH_TRY;
3304   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
3305
3306   initData();
3307
3308   list<double> angles;
3309   for (int i = 0; i < Angles.length(); i++) {
3310     angles.push_back( Angles[i] );
3311   }
3312   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
3313   int nbOldGroups = myMesh->NbGroup();
3314
3315   if ( Path->_is_nil() ) {
3316     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3317     return EmptyGr;
3318   }
3319
3320   TIDSortedElemSet elements, copyElements;
3321   arrayToSet(IDsOfElements, getMeshDS(), elements, ElementType);
3322
3323   TIDSortedElemSet* workElements = &elements;
3324
3325   if ( myIsPreviewMode )
3326   {
3327     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
3328     getPreviewMesh( SMDSAbs_Face )->Copy( elements, copyElements, select, avoid );
3329     workElements = & copyElements;
3330     MakeGroups = false;
3331   }
3332
3333   ::SMESH_MeshEditor::Extrusion_Error error;
3334
3335   if ( SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path ))
3336   {
3337     // path as mesh
3338     SMDS_MeshNode* aNodeStart =
3339       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
3340     if ( !aNodeStart ) {
3341       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3342       return EmptyGr;
3343     }
3344     error = getEditor().ExtrusionAlongTrack( *workElements, &(aMeshImp->GetImpl()), aNodeStart,
3345                                              HasAngles, angles, LinearVariation,
3346                                              HasRefPoint, refPnt, MakeGroups );
3347     declareMeshModified( /*isReComputeSafe=*/true );
3348   }
3349   else if ( SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path ))
3350   {
3351     // path as submesh
3352     SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
3353     aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
3354     SMDS_MeshNode* aNodeStart =
3355       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
3356     if ( !aNodeStart ) {
3357       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3358       return EmptyGr;
3359     }
3360     SMESH_subMesh* aSubMesh =
3361       aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
3362     error = getEditor().ExtrusionAlongTrack( *workElements, aSubMesh, aNodeStart,
3363                                              HasAngles, angles, LinearVariation,
3364                                              HasRefPoint, refPnt, MakeGroups );
3365     declareMeshModified( /*isReComputeSafe=*/true );
3366   }
3367   else if ( SMESH::DownCast<SMESH_Group_i*>( Path ))
3368   {
3369     // path as group of 1D elements
3370     // ????????
3371   }
3372   else
3373   {
3374     // invalid path
3375     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3376     return EmptyGr;
3377   }
3378
3379   Error = convExtrError( error );
3380
3381   if ( MakeGroups ) {
3382     list<int> groupIDs = myMesh->GetGroupIds();
3383     list<int>::iterator newBegin = groupIDs.begin();
3384     std::advance( newBegin, nbOldGroups ); // skip old groups
3385     groupIDs.erase( groupIDs.begin(), newBegin );
3386     return getGroups( & groupIDs );
3387   }
3388   return EmptyGr;
3389
3390   SMESH_CATCH( SMESH::throwCorbaException );
3391   return 0;
3392 }
3393
3394 //=======================================================================
3395 //function : ExtrusionAlongPath
3396 //purpose  :
3397 //=======================================================================
3398
3399 SMESH::SMESH_MeshEditor::Extrusion_Error
3400 SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
3401                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
3402                                        GEOM::GEOM_Object_ptr       thePathShape,
3403                                        CORBA::Long                 theNodeStart,
3404                                        CORBA::Boolean              theHasAngles,
3405                                        const SMESH::double_array & theAngles,
3406                                        CORBA::Boolean              theHasRefPoint,
3407                                        const SMESH::PointStruct &  theRefPoint)
3408   throw (SALOME::SALOME_Exception)
3409 {
3410   MESSAGE("ExtrusionAlongPath");
3411   if ( !myIsPreviewMode ) {
3412     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
3413                   << theIDsOfElements << ", "
3414                   << thePathMesh      << ", "
3415                   << thePathShape     << ", "
3416                   << theNodeStart     << ", "
3417                   << theHasAngles     << ", "
3418                   << theAngles        << ", "
3419                   << theHasRefPoint   << ", "
3420                   << "SMESH.PointStruct( "
3421                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3422                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3423                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3424   }
3425   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3426   extrusionAlongPath( theIDsOfElements,
3427                       thePathMesh,
3428                       thePathShape,
3429                       theNodeStart,
3430                       theHasAngles,
3431                       theAngles,
3432                       theHasRefPoint,
3433                       theRefPoint,
3434                       false,
3435                       anError);
3436   return anError;
3437 }
3438
3439 //=======================================================================
3440 //function : ExtrusionAlongPathObject
3441 //purpose  :
3442 //=======================================================================
3443
3444 SMESH::SMESH_MeshEditor::Extrusion_Error
3445 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
3446                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
3447                                              GEOM::GEOM_Object_ptr       thePathShape,
3448                                              CORBA::Long                 theNodeStart,
3449                                              CORBA::Boolean              theHasAngles,
3450                                              const SMESH::double_array & theAngles,
3451                                              CORBA::Boolean              theHasRefPoint,
3452                                              const SMESH::PointStruct &  theRefPoint)
3453   throw (SALOME::SALOME_Exception)
3454 {
3455   if ( !myIsPreviewMode ) {
3456     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
3457                   << theObject        << ", "
3458                   << thePathMesh      << ", "
3459                   << thePathShape     << ", "
3460                   << theNodeStart     << ", "
3461                   << theHasAngles     << ", "
3462                   << theAngles        << ", "
3463                   << theHasRefPoint   << ", "
3464                   << "SMESH.PointStruct( "
3465                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3466                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3467                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3468   }
3469   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3470   prepareIdSource( theObject );
3471   SMESH::long_array_var anElementsId = theObject->GetIDs();
3472   extrusionAlongPath( anElementsId,
3473                       thePathMesh,
3474                       thePathShape,
3475                       theNodeStart,
3476                       theHasAngles,
3477                       theAngles,
3478                       theHasRefPoint,
3479                       theRefPoint,
3480                       false,
3481                       anError);
3482   return anError;
3483 }
3484
3485 //=======================================================================
3486 //function : ExtrusionAlongPathObject1D
3487 //purpose  :
3488 //=======================================================================
3489
3490 SMESH::SMESH_MeshEditor::Extrusion_Error
3491 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
3492                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
3493                                                GEOM::GEOM_Object_ptr       thePathShape,
3494                                                CORBA::Long                 theNodeStart,
3495                                                CORBA::Boolean              theHasAngles,
3496                                                const SMESH::double_array & theAngles,
3497                                                CORBA::Boolean              theHasRefPoint,
3498                                                const SMESH::PointStruct &  theRefPoint)
3499   throw (SALOME::SALOME_Exception)
3500 {
3501   if ( !myIsPreviewMode ) {
3502     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
3503                   << theObject        << ", "
3504                   << thePathMesh      << ", "
3505                   << thePathShape     << ", "
3506                   << theNodeStart     << ", "
3507                   << theHasAngles     << ", "
3508                   << theAngles        << ", "
3509                   << theHasRefPoint   << ", "
3510                   << "SMESH.PointStruct( "
3511                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3512                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3513                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3514   }
3515   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3516   prepareIdSource( theObject );
3517   SMESH::long_array_var anElementsId = theObject->GetIDs();
3518   extrusionAlongPath( anElementsId,
3519                       thePathMesh,
3520                       thePathShape,
3521                       theNodeStart,
3522                       theHasAngles,
3523                       theAngles,
3524                       theHasRefPoint,
3525                       theRefPoint,
3526                       false,
3527                       anError,
3528                       SMDSAbs_Edge);
3529   return anError;
3530 }
3531
3532 //=======================================================================
3533 //function : ExtrusionAlongPathObject2D
3534 //purpose  :
3535 //=======================================================================
3536
3537 SMESH::SMESH_MeshEditor::Extrusion_Error
3538 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
3539                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
3540                                                GEOM::GEOM_Object_ptr       thePathShape,
3541                                                CORBA::Long                 theNodeStart,
3542                                                CORBA::Boolean              theHasAngles,
3543                                                const SMESH::double_array & theAngles,
3544                                                CORBA::Boolean              theHasRefPoint,
3545                                                const SMESH::PointStruct &  theRefPoint)
3546   throw (SALOME::SALOME_Exception)
3547 {
3548   if ( !myIsPreviewMode ) {
3549     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
3550                   << theObject        << ", "
3551                   << thePathMesh      << ", "
3552                   << thePathShape     << ", "
3553                   << theNodeStart     << ", "
3554                   << theHasAngles     << ", "
3555                   << theAngles        << ", "
3556                   << theHasRefPoint   << ", "
3557                   << "SMESH.PointStruct( "
3558                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3559                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3560                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3561   }
3562   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3563   prepareIdSource( theObject );
3564   SMESH::long_array_var anElementsId = theObject->GetIDs();
3565   extrusionAlongPath( anElementsId,
3566                       thePathMesh,
3567                       thePathShape,
3568                       theNodeStart,
3569                       theHasAngles,
3570                       theAngles,
3571                       theHasRefPoint,
3572                       theRefPoint,
3573                       false,
3574                       anError,
3575                       SMDSAbs_Face);
3576   return anError;
3577 }
3578
3579
3580 //=======================================================================
3581 //function : ExtrusionAlongPathMakeGroups
3582 //purpose  :
3583 //=======================================================================
3584
3585 SMESH::ListOfGroups*
3586 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
3587                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
3588                                                  GEOM::GEOM_Object_ptr      thePathShape,
3589                                                  CORBA::Long                theNodeStart,
3590                                                  CORBA::Boolean             theHasAngles,
3591                                                  const SMESH::double_array& theAngles,
3592                                                  CORBA::Boolean             theHasRefPoint,
3593                                                  const SMESH::PointStruct&  theRefPoint,
3594                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3595   throw (SALOME::SALOME_Exception)
3596 {
3597   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3598
3599   SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
3600                                                        thePathMesh,
3601                                                        thePathShape,
3602                                                        theNodeStart,
3603                                                        theHasAngles,
3604                                                        theAngles,
3605                                                        theHasRefPoint,
3606                                                        theRefPoint,
3607                                                        true,
3608                                                        Error);
3609   if (!myIsPreviewMode) {
3610     bool isDumpGroups = aGroups && aGroups->length() > 0;
3611     if (isDumpGroups)
3612       aPythonDump << "(" << aGroups << ", error)";
3613     else
3614       aPythonDump <<"error";
3615
3616     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
3617                << theIDsOfElements << ", "
3618                << thePathMesh      << ", "
3619                << thePathShape     << ", "
3620                << theNodeStart     << ", "
3621                << theHasAngles     << ", "
3622                << theAngles        << ", "
3623                << theHasRefPoint   << ", "
3624                << "SMESH.PointStruct( "
3625                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3626                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3627                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3628   }
3629   return aGroups;
3630 }
3631
3632 //=======================================================================
3633 //function : ExtrusionAlongPathObjectMakeGroups
3634 //purpose  :
3635 //=======================================================================
3636
3637 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3638 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3639                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
3640                                    GEOM::GEOM_Object_ptr      thePathShape,
3641                                    CORBA::Long                theNodeStart,
3642                                    CORBA::Boolean             theHasAngles,
3643                                    const SMESH::double_array& theAngles,
3644                                    CORBA::Boolean             theHasRefPoint,
3645                                    const SMESH::PointStruct&  theRefPoint,
3646                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3647   throw (SALOME::SALOME_Exception)
3648 {
3649   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3650
3651   prepareIdSource( theObject );
3652   SMESH::long_array_var anElementsId = theObject->GetIDs();
3653   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3654                                                       thePathMesh,
3655                                                       thePathShape,
3656                                                       theNodeStart,
3657                                                       theHasAngles,
3658                                                       theAngles,
3659                                                       theHasRefPoint,
3660                                                       theRefPoint,
3661                                                       true,
3662                                                       Error);
3663
3664   if (!myIsPreviewMode) {
3665     bool isDumpGroups = aGroups && aGroups->length() > 0;
3666     if (isDumpGroups)
3667       aPythonDump << "(" << aGroups << ", error)";
3668     else
3669       aPythonDump <<"error";
3670
3671     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
3672                 << theObject << ", "
3673                 << thePathMesh      << ", "
3674                 << thePathShape     << ", "
3675                 << theNodeStart     << ", "
3676                 << theHasAngles     << ", "
3677                 << theAngles        << ", "
3678                 << theHasRefPoint   << ", "
3679                 << "SMESH.PointStruct( "
3680                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3681                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3682                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3683   }
3684   return aGroups;
3685 }
3686
3687 //=======================================================================
3688 //function : ExtrusionAlongPathObject1DMakeGroups
3689 //purpose  :
3690 //=======================================================================
3691
3692 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3693 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3694                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
3695                                      GEOM::GEOM_Object_ptr      thePathShape,
3696                                      CORBA::Long                theNodeStart,
3697                                      CORBA::Boolean             theHasAngles,
3698                                      const SMESH::double_array& theAngles,
3699                                      CORBA::Boolean             theHasRefPoint,
3700                                      const SMESH::PointStruct&  theRefPoint,
3701                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3702   throw (SALOME::SALOME_Exception)
3703 {
3704   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3705
3706   prepareIdSource( theObject );
3707   SMESH::long_array_var anElementsId = theObject->GetIDs();
3708   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3709                                                       thePathMesh,
3710                                                       thePathShape,
3711                                                       theNodeStart,
3712                                                       theHasAngles,
3713                                                       theAngles,
3714                                                       theHasRefPoint,
3715                                                       theRefPoint,
3716                                                       true,
3717                                                       Error,
3718                                                       SMDSAbs_Edge);
3719
3720   if (!myIsPreviewMode) {
3721     bool isDumpGroups = aGroups && aGroups->length() > 0;
3722     if (isDumpGroups)
3723       aPythonDump << "(" << aGroups << ", error)";
3724     else
3725       aPythonDump << "error";
3726
3727     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
3728                 << theObject << ", "
3729                 << thePathMesh      << ", "
3730                 << thePathShape     << ", "
3731                 << theNodeStart     << ", "
3732                 << theHasAngles     << ", "
3733                 << theAngles        << ", "
3734                 << theHasRefPoint   << ", "
3735                 << "SMESH.PointStruct( "
3736                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3737                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3738                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3739   }
3740   return aGroups;
3741 }
3742
3743 //=======================================================================
3744 //function : ExtrusionAlongPathObject2DMakeGroups
3745 //purpose  :
3746 //=======================================================================
3747
3748 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3749 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3750                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
3751                                      GEOM::GEOM_Object_ptr      thePathShape,
3752                                      CORBA::Long                theNodeStart,
3753                                      CORBA::Boolean             theHasAngles,
3754                                      const SMESH::double_array& theAngles,
3755                                      CORBA::Boolean             theHasRefPoint,
3756                                      const SMESH::PointStruct&  theRefPoint,
3757                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3758   throw (SALOME::SALOME_Exception)
3759 {
3760   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3761
3762   prepareIdSource( theObject );
3763   SMESH::long_array_var anElementsId = theObject->GetIDs();
3764   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3765                                                       thePathMesh,
3766                                                       thePathShape,
3767                                                       theNodeStart,
3768                                                       theHasAngles,
3769                                                       theAngles,
3770                                                       theHasRefPoint,
3771                                                       theRefPoint,
3772                                                       true,
3773                                                       Error,
3774                                                       SMDSAbs_Face);
3775
3776   if (!myIsPreviewMode) {
3777     bool isDumpGroups = aGroups && aGroups->length() > 0;
3778     if (isDumpGroups)
3779       aPythonDump << "(" << aGroups << ", error)";
3780     else
3781       aPythonDump << "error";
3782
3783     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
3784                 << theObject << ", "
3785                 << thePathMesh      << ", "
3786                 << thePathShape     << ", "
3787                 << theNodeStart     << ", "
3788                 << theHasAngles     << ", "
3789                 << theAngles        << ", "
3790                 << theHasRefPoint   << ", "
3791                 << "SMESH.PointStruct( "
3792                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3793                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3794                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3795   }
3796   return aGroups;
3797 }
3798
3799 //=======================================================================
3800 //function : ExtrusionAlongPathObjX
3801 //purpose  :
3802 //=======================================================================
3803
3804 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3805 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
3806                        SMESH::SMESH_IDSource_ptr  Path,
3807                        CORBA::Long                NodeStart,
3808                        CORBA::Boolean             HasAngles,
3809                        const SMESH::double_array& Angles,
3810                        CORBA::Boolean             LinearVariation,
3811                        CORBA::Boolean             HasRefPoint,
3812                        const SMESH::PointStruct&  RefPoint,
3813                        CORBA::Boolean             MakeGroups,
3814                        SMESH::ElementType         ElemType,
3815                        SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3816   throw (SALOME::SALOME_Exception)
3817 {
3818   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3819
3820   prepareIdSource( Object );
3821   SMESH::long_array_var anElementsId = Object->GetIDs();
3822   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
3823                                                       Path,
3824                                                       NodeStart,
3825                                                       HasAngles,
3826                                                       Angles,
3827                                                       LinearVariation,
3828                                                       HasRefPoint,
3829                                                       RefPoint,
3830                                                       MakeGroups,
3831                                                       (SMDSAbs_ElementType)ElemType,
3832                                                       Error);
3833
3834   if (!myIsPreviewMode) {
3835     bool isDumpGroups = aGroups && aGroups->length() > 0;
3836     if (isDumpGroups)
3837       aPythonDump << "(" << *aGroups << ", error)";
3838     else
3839       aPythonDump << "error";
3840
3841     aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
3842                 << Object          << ", "
3843                 << Path            << ", "
3844                 << NodeStart       << ", "
3845                 << HasAngles       << ", "
3846                 << TVar( Angles )  << ", "
3847                 << LinearVariation << ", "
3848                 << HasRefPoint     << ", "
3849                 << "SMESH.PointStruct( "
3850                 << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
3851                 << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
3852                 << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
3853                 << MakeGroups << ", "
3854                 << ElemType << " )";
3855   }
3856   return aGroups;
3857 }
3858
3859 //=======================================================================
3860 //function : ExtrusionAlongPathX
3861 //purpose  :
3862 //=======================================================================
3863
3864 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3865 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
3866                     SMESH::SMESH_IDSource_ptr  Path,
3867                     CORBA::Long                NodeStart,
3868                     CORBA::Boolean             HasAngles,
3869                     const SMESH::double_array& Angles,
3870                     CORBA::Boolean             LinearVariation,
3871                     CORBA::Boolean             HasRefPoint,
3872                     const SMESH::PointStruct&  RefPoint,
3873                     CORBA::Boolean             MakeGroups,
3874                     SMESH::ElementType         ElemType,
3875                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3876   throw (SALOME::SALOME_Exception)
3877 {
3878   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3879
3880   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
3881                                                       Path,
3882                                                       NodeStart,
3883                                                       HasAngles,
3884                                                       Angles,
3885                                                       LinearVariation,
3886                                                       HasRefPoint,
3887                                                       RefPoint,
3888                                                       MakeGroups,
3889                                                       (SMDSAbs_ElementType)ElemType,
3890                                                       Error);
3891
3892   if (!myIsPreviewMode) {
3893     bool isDumpGroups = aGroups && aGroups->length() > 0;
3894     if (isDumpGroups)
3895       aPythonDump << "(" << *aGroups << ", error)";
3896     else
3897       aPythonDump <<"error";
3898
3899     aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
3900                 << IDsOfElements   << ", "
3901                 << Path            << ", "
3902                 << NodeStart       << ", "
3903                 << HasAngles       << ", "
3904                 << TVar( Angles )  << ", "
3905                 << LinearVariation << ", "
3906                 << HasRefPoint     << ", "
3907                 << "SMESH.PointStruct( "
3908                 << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
3909                 << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
3910                 << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
3911                 << MakeGroups << ", "
3912                 << ElemType << " )";
3913   }
3914   return aGroups;
3915 }
3916
3917 //================================================================================
3918 /*!
3919  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3920  * of given angles along path steps
3921  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3922  *                which proceeds the extrusion
3923  * \param PathShape is shape(edge); as the mesh can be complex, the edge
3924  *                 is used to define the sub-mesh for the path
3925  */
3926 //================================================================================
3927
3928 SMESH::double_array*
3929 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
3930                                           GEOM::GEOM_Object_ptr       thePathShape,
3931                                           const SMESH::double_array & theAngles)
3932 {
3933   SMESH::double_array_var aResult = new SMESH::double_array();
3934   int nbAngles = theAngles.length();
3935   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3936   {
3937     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3938     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3939     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3940     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3941       return aResult._retn();
3942     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3943     if ( nbSteps == nbAngles )
3944     {
3945       aResult.inout() = theAngles;
3946     }
3947     else
3948     {
3949       aResult->length( nbSteps );
3950       double rAn2St = double( nbAngles ) / double( nbSteps );
3951       double angPrev = 0, angle;
3952       for ( int iSt = 0; iSt < nbSteps; ++iSt )
3953       {
3954         double angCur = rAn2St * ( iSt+1 );
3955         double angCurFloor  = floor( angCur );
3956         double angPrevFloor = floor( angPrev );
3957         if ( angPrevFloor == angCurFloor )
3958           angle = rAn2St * theAngles[ int( angCurFloor ) ];
3959         else
3960         {
3961           int iP = int( angPrevFloor );
3962           double angPrevCeil = ceil(angPrev);
3963           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3964
3965           int iC = int( angCurFloor );
3966           if ( iC < nbAngles )
3967             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3968
3969           iP = int( angPrevCeil );
3970           while ( iC-- > iP )
3971             angle += theAngles[ iC ];
3972         }
3973         aResult[ iSt ] = angle;
3974         angPrev = angCur;
3975       }
3976     }
3977   }
3978   // Update Python script
3979   TPythonDump() << "rotAngles = " << theAngles;
3980   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3981                 << thePathMesh  << ", "
3982                 << thePathShape << ", "
3983                 << "rotAngles )";
3984
3985   return aResult._retn();
3986 }
3987
3988 //=======================================================================
3989 //function : mirror
3990 //purpose  :
3991 //=======================================================================
3992
3993 SMESH::ListOfGroups*
3994 SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
3995                            const SMESH::AxisStruct &           theAxis,
3996                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3997                            CORBA::Boolean                      theCopy,
3998                            bool                                theMakeGroups,
3999                            ::SMESH_Mesh*                       theTargetMesh)
4000   throw (SALOME::SALOME_Exception)
4001 {
4002   SMESH_TRY;
4003   initData();
4004
4005   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
4006   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
4007
4008   if ( theTargetMesh )
4009     theCopy = false;
4010
4011   gp_Trsf aTrsf;
4012   switch ( theMirrorType ) {
4013   case  SMESH::SMESH_MeshEditor::POINT:
4014     aTrsf.SetMirror( P );
4015     break;
4016   case  SMESH::SMESH_MeshEditor::AXIS:
4017     aTrsf.SetMirror( gp_Ax1( P, V ));
4018     break;
4019   default:
4020     aTrsf.SetMirror( gp_Ax2( P, V ));
4021   }
4022
4023   TIDSortedElemSet  copyElements;
4024   TIDSortedElemSet* workElements = & theElements;
4025
4026   if ( myIsPreviewMode )
4027   {
4028     TPreviewMesh * tmpMesh = getPreviewMesh();
4029     tmpMesh->Copy( theElements, copyElements);
4030     if ( !theCopy && !theTargetMesh )
4031     {
4032       TIDSortedElemSet elemsAround, elemsAroundCopy;
4033       getElementsAround( theElements, getMeshDS(), elemsAround );
4034       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4035     }
4036     workElements = & copyElements;
4037     theMakeGroups = false;
4038   }
4039
4040   ::SMESH_MeshEditor::PGroupIDs groupIds =
4041       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4042
4043   if ( theCopy && !myIsPreviewMode)
4044   {
4045     if ( theTargetMesh )
4046     {
4047       theTargetMesh->GetMeshDS()->Modified();
4048     }
4049     else
4050     {
4051       declareMeshModified( /*isReComputeSafe=*/false );
4052     }
4053   }
4054   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4055
4056   SMESH_CATCH( SMESH::throwCorbaException );
4057   return 0;
4058 }
4059
4060 //=======================================================================
4061 //function : Mirror
4062 //purpose  :
4063 //=======================================================================
4064
4065 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
4066                                 const SMESH::AxisStruct &           theAxis,
4067                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
4068                                 CORBA::Boolean                      theCopy)
4069   throw (SALOME::SALOME_Exception)
4070 {
4071   if ( !myIsPreviewMode ) {
4072     TPythonDump() << this << ".Mirror( "
4073                   << theIDsOfElements              << ", "
4074                   << theAxis                       << ", "
4075                   << mirrorTypeName(theMirrorType) << ", "
4076                   << theCopy                       << " )";
4077   }
4078   if ( theIDsOfElements.length() > 0 )
4079   {
4080     TIDSortedElemSet elements;
4081     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4082     mirror(elements, theAxis, theMirrorType, theCopy, false);
4083   }
4084 }
4085
4086
4087 //=======================================================================
4088 //function : MirrorObject
4089 //purpose  :
4090 //=======================================================================
4091
4092 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
4093                                       const SMESH::AxisStruct &           theAxis,
4094                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
4095                                       CORBA::Boolean                      theCopy)
4096   throw (SALOME::SALOME_Exception)
4097 {
4098   if ( !myIsPreviewMode ) {
4099     TPythonDump() << this << ".MirrorObject( "
4100                   << theObject                     << ", "
4101                   << theAxis                       << ", "
4102                   << mirrorTypeName(theMirrorType) << ", "
4103                   << theCopy                       << " )";
4104   }
4105   TIDSortedElemSet elements;
4106
4107   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4108
4109   prepareIdSource( theObject );
4110   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4111     mirror(elements, theAxis, theMirrorType, theCopy, false);
4112 }
4113
4114 //=======================================================================
4115 //function : MirrorMakeGroups
4116 //purpose  :
4117 //=======================================================================
4118
4119 SMESH::ListOfGroups*
4120 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
4121                                      const SMESH::AxisStruct&            theMirror,
4122                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
4123   throw (SALOME::SALOME_Exception)
4124 {
4125   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4126
4127   SMESH::ListOfGroups * aGroups = 0;
4128   if ( theIDsOfElements.length() > 0 )
4129   {
4130     TIDSortedElemSet elements;
4131     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4132     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
4133   }
4134   if (!myIsPreviewMode) {
4135     dumpGroupsList(aPythonDump, aGroups);
4136     aPythonDump << this << ".MirrorMakeGroups( "
4137                 << theIDsOfElements              << ", "
4138                 << theMirror                     << ", "
4139                 << mirrorTypeName(theMirrorType) << " )";
4140   }
4141   return aGroups;
4142 }
4143
4144 //=======================================================================
4145 //function : MirrorObjectMakeGroups
4146 //purpose  :
4147 //=======================================================================
4148
4149 SMESH::ListOfGroups*
4150 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
4151                                            const SMESH::AxisStruct&            theMirror,
4152                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
4153   throw (SALOME::SALOME_Exception)
4154 {
4155   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4156
4157   SMESH::ListOfGroups * aGroups = 0;
4158   TIDSortedElemSet elements;
4159   prepareIdSource( theObject );
4160   if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4161     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
4162
4163   if (!myIsPreviewMode)
4164   {
4165     dumpGroupsList(aPythonDump,aGroups);
4166     aPythonDump << this << ".MirrorObjectMakeGroups( "
4167                 << theObject                     << ", "
4168                 << theMirror                     << ", "
4169                 << mirrorTypeName(theMirrorType) << " )";
4170   }
4171   return aGroups;
4172 }
4173
4174 //=======================================================================
4175 //function : MirrorMakeMesh
4176 //purpose  :
4177 //=======================================================================
4178
4179 SMESH::SMESH_Mesh_ptr
4180 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
4181                                    const SMESH::AxisStruct&            theMirror,
4182                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
4183                                    CORBA::Boolean                      theCopyGroups,
4184                                    const char*                         theMeshName)
4185   throw (SALOME::SALOME_Exception)
4186 {
4187   SMESH_Mesh_i* mesh_i;
4188   SMESH::SMESH_Mesh_var mesh;
4189   { // open new scope to dump "MakeMesh" command
4190     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4191
4192     TPythonDump pydump; // to prevent dump at mesh creation
4193
4194     mesh = makeMesh( theMeshName );
4195     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4196     if (mesh_i && theIDsOfElements.length() > 0 )
4197     {
4198       TIDSortedElemSet elements;
4199       arrayToSet(theIDsOfElements, getMeshDS(), elements);
4200       mirror(elements, theMirror, theMirrorType,
4201              false, theCopyGroups, & mesh_i->GetImpl());
4202       mesh_i->CreateGroupServants();
4203     }
4204
4205     if (!myIsPreviewMode) {
4206       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
4207              << theIDsOfElements              << ", "
4208              << theMirror                     << ", "
4209              << mirrorTypeName(theMirrorType) << ", "
4210              << theCopyGroups                 << ", '"
4211              << theMeshName                   << "' )";
4212     }
4213   }
4214
4215   //dump "GetGroups"
4216   if (!myIsPreviewMode && mesh_i)
4217     mesh_i->GetGroups();
4218
4219   return mesh._retn();
4220 }
4221
4222 //=======================================================================
4223 //function : MirrorObjectMakeMesh
4224 //purpose  :
4225 //=======================================================================
4226
4227 SMESH::SMESH_Mesh_ptr
4228 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
4229                                          const SMESH::AxisStruct&            theMirror,
4230                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
4231                                          CORBA::Boolean                      theCopyGroups,
4232                                          const char*                         theMeshName)
4233   throw (SALOME::SALOME_Exception)
4234 {
4235   SMESH_Mesh_i* mesh_i;
4236   SMESH::SMESH_Mesh_var mesh;
4237   { // open new scope to dump "MakeMesh" command
4238     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4239
4240     TPythonDump pydump; // to prevent dump at mesh creation
4241
4242     mesh = makeMesh( theMeshName );
4243     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4244     TIDSortedElemSet elements;
4245     prepareIdSource( theObject );
4246     if ( mesh_i &&
4247          idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4248     {
4249       mirror(elements, theMirror, theMirrorType,
4250              false, theCopyGroups, & mesh_i->GetImpl());
4251       mesh_i->CreateGroupServants();
4252     }
4253     if (!myIsPreviewMode) {
4254       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
4255              << theObject                     << ", "
4256              << theMirror                     << ", "
4257              << mirrorTypeName(theMirrorType) << ", "
4258              << theCopyGroups                 << ", '"
4259              << theMeshName                   << "' )";
4260     }
4261   }
4262
4263   //dump "GetGroups"
4264   if (!myIsPreviewMode && mesh_i)
4265     mesh_i->GetGroups();
4266
4267   return mesh._retn();
4268 }
4269
4270 //=======================================================================
4271 //function : translate
4272 //purpose  :
4273 //=======================================================================
4274
4275 SMESH::ListOfGroups*
4276 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
4277                               const SMESH::DirStruct &  theVector,
4278                               CORBA::Boolean            theCopy,
4279                               bool                      theMakeGroups,
4280                               ::SMESH_Mesh*             theTargetMesh)
4281   throw (SALOME::SALOME_Exception)
4282 {
4283   SMESH_TRY;
4284   initData();
4285
4286   if ( theTargetMesh )
4287     theCopy = false;
4288
4289   gp_Trsf aTrsf;
4290   const SMESH::PointStruct * P = &theVector.PS;
4291   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
4292
4293   TIDSortedElemSet  copyElements;
4294   TIDSortedElemSet* workElements = &theElements;
4295
4296   if ( myIsPreviewMode )
4297   {
4298     TPreviewMesh * tmpMesh = getPreviewMesh();
4299     tmpMesh->Copy( theElements, copyElements);
4300     if ( !theCopy && !theTargetMesh )
4301     {
4302       TIDSortedElemSet elemsAround, elemsAroundCopy;
4303       getElementsAround( theElements, getMeshDS(), elemsAround );
4304       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4305     }
4306     workElements = & copyElements;
4307     theMakeGroups = false;
4308   }
4309
4310   ::SMESH_MeshEditor::PGroupIDs groupIds =
4311       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4312
4313   if ( theCopy && !myIsPreviewMode )
4314   {
4315     if ( theTargetMesh )
4316     {
4317       theTargetMesh->GetMeshDS()->Modified();
4318     }
4319     else
4320     {
4321       declareMeshModified( /*isReComputeSafe=*/false );
4322     }
4323   }
4324
4325   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4326
4327   SMESH_CATCH( SMESH::throwCorbaException );
4328   return 0;
4329 }
4330
4331 //=======================================================================
4332 //function : Translate
4333 //purpose  :
4334 //=======================================================================
4335
4336 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
4337                                    const SMESH::DirStruct &  theVector,
4338                                    CORBA::Boolean            theCopy)
4339   throw (SALOME::SALOME_Exception)
4340 {
4341   if (!myIsPreviewMode) {
4342     TPythonDump() << this << ".Translate( "
4343                   << theIDsOfElements << ", "
4344                   << theVector        << ", "
4345                   << theCopy          << " )";
4346   }
4347   if (theIDsOfElements.length()) {
4348     TIDSortedElemSet elements;
4349     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4350     translate(elements, theVector, theCopy, false);
4351   }
4352 }
4353
4354 //=======================================================================
4355 //function : TranslateObject
4356 //purpose  :
4357 //=======================================================================
4358
4359 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
4360                                          const SMESH::DirStruct &  theVector,
4361                                          CORBA::Boolean            theCopy)
4362   throw (SALOME::SALOME_Exception)
4363 {
4364   if (!myIsPreviewMode) {
4365     TPythonDump() << this << ".TranslateObject( "
4366                   << theObject << ", "
4367                   << theVector << ", "
4368                   << theCopy   << " )";
4369   }
4370   TIDSortedElemSet elements;
4371
4372   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4373   
4374   prepareIdSource( theObject );
4375   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4376     translate(elements, theVector, theCopy, false);
4377 }
4378
4379 //=======================================================================
4380 //function : TranslateMakeGroups
4381 //purpose  :
4382 //=======================================================================
4383
4384 SMESH::ListOfGroups*
4385 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
4386                                         const SMESH::DirStruct&  theVector)
4387   throw (SALOME::SALOME_Exception)
4388 {
4389   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4390
4391   SMESH::ListOfGroups * aGroups = 0;
4392   if (theIDsOfElements.length()) {
4393     TIDSortedElemSet elements;
4394     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4395     aGroups = translate(elements,theVector,true,true);
4396   }
4397   if (!myIsPreviewMode) {
4398     dumpGroupsList(aPythonDump, aGroups);
4399     aPythonDump << this << ".TranslateMakeGroups( "
4400                 << theIDsOfElements << ", "
4401                 << theVector        << " )";
4402   }
4403   return aGroups;
4404 }
4405
4406 //=======================================================================
4407 //function : TranslateObjectMakeGroups
4408 //purpose  :
4409 //=======================================================================
4410
4411 SMESH::ListOfGroups*
4412 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4413                                               const SMESH::DirStruct&   theVector)
4414   throw (SALOME::SALOME_Exception)
4415 {
4416   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4417
4418   SMESH::ListOfGroups * aGroups = 0;
4419   TIDSortedElemSet elements;
4420   prepareIdSource( theObject );
4421   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4422     aGroups = translate(elements, theVector, true, true);
4423
4424   if (!myIsPreviewMode) {
4425     dumpGroupsList(aPythonDump, aGroups);
4426     aPythonDump << this << ".TranslateObjectMakeGroups( "
4427                 << theObject << ", "
4428                 << theVector << " )";
4429   }
4430   return aGroups;
4431 }
4432
4433 //=======================================================================
4434 //function : TranslateMakeMesh
4435 //purpose  :
4436 //=======================================================================
4437
4438 SMESH::SMESH_Mesh_ptr
4439 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
4440                                       const SMESH::DirStruct&  theVector,
4441                                       CORBA::Boolean           theCopyGroups,
4442                                       const char*              theMeshName)
4443   throw (SALOME::SALOME_Exception)
4444 {
4445   SMESH_Mesh_i* mesh_i;
4446   SMESH::SMESH_Mesh_var mesh;
4447
4448   { // open new scope to dump "MakeMesh" command
4449     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4450
4451     TPythonDump pydump; // to prevent dump at mesh creation
4452
4453     mesh = makeMesh( theMeshName );
4454     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4455
4456     if ( mesh_i && theIDsOfElements.length() )
4457     {
4458       TIDSortedElemSet elements;
4459       arrayToSet(theIDsOfElements, getMeshDS(), elements);
4460       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
4461       mesh_i->CreateGroupServants();
4462     }
4463
4464     if ( !myIsPreviewMode ) {
4465       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
4466              << theIDsOfElements << ", "
4467              << theVector        << ", "
4468              << theCopyGroups    << ", '"
4469              << theMeshName      << "' )";
4470     }
4471   }
4472
4473   //dump "GetGroups"
4474   if (!myIsPreviewMode && mesh_i)
4475     mesh_i->GetGroups();
4476
4477   return mesh._retn();
4478 }
4479
4480 //=======================================================================
4481 //function : TranslateObjectMakeMesh
4482 //purpose  :
4483 //=======================================================================
4484
4485 SMESH::SMESH_Mesh_ptr
4486 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4487                                             const SMESH::DirStruct&   theVector,
4488                                             CORBA::Boolean            theCopyGroups,
4489                                             const char*               theMeshName)
4490   throw (SALOME::SALOME_Exception)
4491 {
4492   SMESH_TRY;
4493   SMESH_Mesh_i* mesh_i;
4494   SMESH::SMESH_Mesh_var mesh;
4495   { // open new scope to dump "MakeMesh" command
4496     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4497
4498     TPythonDump pydump; // to prevent dump at mesh creation
4499     mesh = makeMesh( theMeshName );
4500     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4501
4502     TIDSortedElemSet elements;
4503     prepareIdSource( theObject );
4504     if ( mesh_i &&
4505       idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4506     {
4507       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
4508       mesh_i->CreateGroupServants();
4509     }
4510     if ( !myIsPreviewMode ) {
4511       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
4512              << theObject     << ", "
4513              << theVector     << ", "
4514              << theCopyGroups << ", '"
4515              << theMeshName   << "' )";
4516     }
4517   }
4518
4519   // dump "GetGroups"
4520   if (!myIsPreviewMode && mesh_i)
4521     mesh_i->GetGroups();
4522
4523   return mesh._retn();
4524
4525   SMESH_CATCH( SMESH::throwCorbaException );
4526   return 0;
4527 }
4528
4529 //=======================================================================
4530 //function : rotate
4531 //purpose  :
4532 //=======================================================================
4533
4534 SMESH::ListOfGroups*
4535 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
4536                            const SMESH::AxisStruct & theAxis,
4537                            CORBA::Double             theAngle,
4538                            CORBA::Boolean            theCopy,
4539                            bool                      theMakeGroups,
4540                            ::SMESH_Mesh*             theTargetMesh)
4541   throw (SALOME::SALOME_Exception)
4542 {
4543   SMESH_TRY;
4544   initData();
4545
4546   if ( theTargetMesh )
4547     theCopy = false;
4548
4549   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
4550   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
4551
4552   gp_Trsf aTrsf;
4553   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
4554
4555   TIDSortedElemSet  copyElements;
4556   TIDSortedElemSet* workElements = &theElements;
4557   if ( myIsPreviewMode ) {
4558     TPreviewMesh * tmpMesh = getPreviewMesh();
4559     tmpMesh->Copy( theElements, copyElements );
4560     if ( !theCopy && !theTargetMesh )
4561     {
4562       TIDSortedElemSet elemsAround, elemsAroundCopy;
4563       getElementsAround( theElements, getMeshDS(), elemsAround );
4564       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4565     }
4566     workElements = &copyElements;
4567     theMakeGroups = false;
4568   }
4569
4570   ::SMESH_MeshEditor::PGroupIDs groupIds =
4571       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4572
4573   if ( theCopy && !myIsPreviewMode)
4574   {
4575     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
4576     else                 declareMeshModified( /*isReComputeSafe=*/false );
4577   }
4578
4579   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4580
4581   SMESH_CATCH( SMESH::throwCorbaException );
4582   return 0;
4583 }
4584
4585 //=======================================================================
4586 //function : Rotate
4587 //purpose  :
4588 //=======================================================================
4589
4590 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
4591                                 const SMESH::AxisStruct & theAxis,
4592                                 CORBA::Double             theAngle,
4593                                 CORBA::Boolean            theCopy)
4594   throw (SALOME::SALOME_Exception)
4595 {
4596   if (!myIsPreviewMode) {
4597     TPythonDump() << this << ".Rotate( "
4598                   << theIDsOfElements << ", "
4599                   << theAxis          << ", "
4600                   << TVar( theAngle ) << ", "
4601                   << theCopy          << " )";
4602   }
4603   if (theIDsOfElements.length() > 0)
4604   {
4605     TIDSortedElemSet elements;
4606     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4607     rotate(elements,theAxis,theAngle,theCopy,false);
4608   }
4609 }
4610
4611 //=======================================================================
4612 //function : RotateObject
4613 //purpose  :
4614 //=======================================================================
4615
4616 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
4617                                       const SMESH::AxisStruct & theAxis,
4618                                       CORBA::Double             theAngle,
4619                                       CORBA::Boolean            theCopy)
4620   throw (SALOME::SALOME_Exception)
4621 {
4622   if ( !myIsPreviewMode ) {
4623     TPythonDump() << this << ".RotateObject( "
4624                   << theObject        << ", "
4625                   << theAxis          << ", "
4626                   << TVar( theAngle ) << ", "
4627                   << theCopy          << " )";
4628   }
4629   TIDSortedElemSet elements;
4630   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4631   prepareIdSource( theObject );
4632   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4633     rotate(elements,theAxis,theAngle,theCopy,false);
4634 }
4635
4636 //=======================================================================
4637 //function : RotateMakeGroups
4638 //purpose  :
4639 //=======================================================================
4640
4641 SMESH::ListOfGroups*
4642 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
4643                                      const SMESH::AxisStruct& theAxis,
4644                                      CORBA::Double            theAngle)
4645   throw (SALOME::SALOME_Exception)
4646 {
4647   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4648
4649   SMESH::ListOfGroups * aGroups = 0;
4650   if (theIDsOfElements.length() > 0)
4651   {
4652     TIDSortedElemSet elements;
4653     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4654     aGroups = rotate(elements,theAxis,theAngle,true,true);
4655   }
4656   if (!myIsPreviewMode) {
4657     dumpGroupsList(aPythonDump, aGroups);
4658     aPythonDump << this << ".RotateMakeGroups( "
4659                 << theIDsOfElements << ", "
4660                 << theAxis          << ", "
4661                 << TVar( theAngle ) << " )";
4662   }
4663   return aGroups;
4664 }
4665
4666 //=======================================================================
4667 //function : RotateObjectMakeGroups
4668 //purpose  :
4669 //=======================================================================
4670
4671 SMESH::ListOfGroups*
4672 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4673                                            const SMESH::AxisStruct&  theAxis,
4674                                            CORBA::Double             theAngle)
4675   throw (SALOME::SALOME_Exception)
4676 {
4677   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4678
4679   SMESH::ListOfGroups * aGroups = 0;
4680   TIDSortedElemSet elements;
4681   prepareIdSource( theObject );
4682   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4683     aGroups = rotate(elements, theAxis, theAngle, true, true);
4684
4685   if (!myIsPreviewMode) {
4686     dumpGroupsList(aPythonDump, aGroups);
4687     aPythonDump << this << ".RotateObjectMakeGroups( "
4688                 << theObject        << ", "
4689                 << theAxis          << ", "
4690                 << TVar( theAngle ) << " )";
4691   }
4692   return aGroups;
4693 }
4694
4695 //=======================================================================
4696 //function : RotateMakeMesh
4697 //purpose  :
4698 //=======================================================================
4699
4700 SMESH::SMESH_Mesh_ptr
4701 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
4702                                    const SMESH::AxisStruct& theAxis,
4703                                    CORBA::Double            theAngleInRadians,
4704                                    CORBA::Boolean           theCopyGroups,
4705                                    const char*              theMeshName)
4706   throw (SALOME::SALOME_Exception)
4707 {
4708   SMESH_TRY;
4709   SMESH::SMESH_Mesh_var mesh;
4710   SMESH_Mesh_i* mesh_i;
4711
4712   { // open new scope to dump "MakeMesh" command
4713     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4714
4715     TPythonDump pydump; // to prevent dump at mesh creation
4716
4717     mesh = makeMesh( theMeshName );
4718     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4719
4720     if ( mesh_i && theIDsOfElements.length() > 0 )
4721     {
4722       TIDSortedElemSet elements;
4723       arrayToSet(theIDsOfElements, getMeshDS(), elements);
4724       rotate(elements, theAxis, theAngleInRadians,
4725              false, theCopyGroups, & mesh_i->GetImpl());
4726       mesh_i->CreateGroupServants();
4727     }
4728     if ( !myIsPreviewMode ) {
4729       pydump << mesh << " = " << this << ".RotateMakeMesh( "
4730              << theIDsOfElements          << ", "
4731              << theAxis                   << ", "
4732              << TVar( theAngleInRadians ) << ", "
4733              << theCopyGroups             << ", '"
4734              << theMeshName               << "' )";
4735     }
4736   }
4737
4738   // dump "GetGroups"
4739   if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
4740     mesh_i->GetGroups();
4741
4742   return mesh._retn();
4743
4744   SMESH_CATCH( SMESH::throwCorbaException );
4745   return 0;
4746 }
4747
4748 //=======================================================================
4749 //function : RotateObjectMakeMesh
4750 //purpose  :
4751 //=======================================================================
4752
4753 SMESH::SMESH_Mesh_ptr
4754 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4755                                          const SMESH::AxisStruct&  theAxis,
4756                                          CORBA::Double             theAngleInRadians,
4757                                          CORBA::Boolean            theCopyGroups,
4758                                          const char*               theMeshName)
4759   throw (SALOME::SALOME_Exception)
4760 {
4761   SMESH_TRY;
4762   SMESH::SMESH_Mesh_var mesh;
4763   SMESH_Mesh_i* mesh_i;
4764
4765   {// open new scope to dump "MakeMesh" command
4766    // and then "GetGroups" using SMESH_Mesh::GetGroups()
4767
4768     TPythonDump pydump; // to prevent dump at mesh creation
4769     mesh = makeMesh( theMeshName );
4770     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4771
4772     TIDSortedElemSet elements;
4773     prepareIdSource( theObject );
4774     if (mesh_i &&
4775         idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4776     {
4777       rotate(elements, theAxis, theAngleInRadians,
4778              false, theCopyGroups, & mesh_i->GetImpl());
4779       mesh_i->CreateGroupServants();
4780     }
4781     if ( !myIsPreviewMode ) {
4782       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
4783              << theObject                 << ", "
4784              << theAxis                   << ", "
4785              << TVar( theAngleInRadians ) << ", "
4786              << theCopyGroups             << ", '"
4787              << theMeshName               << "' )";
4788     }
4789   }
4790
4791   // dump "GetGroups"
4792   if (!myIsPreviewMode && mesh_i)
4793     mesh_i->GetGroups();
4794
4795   return mesh._retn();
4796
4797   SMESH_CATCH( SMESH::throwCorbaException );
4798   return 0;
4799 }
4800
4801 //=======================================================================
4802 //function : scale
4803 //purpose  :
4804 //=======================================================================
4805
4806 SMESH::ListOfGroups*
4807 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
4808                           const SMESH::PointStruct&  thePoint,
4809                           const SMESH::double_array& theScaleFact,
4810                           CORBA::Boolean             theCopy,
4811                           bool                       theMakeGroups,
4812                           ::SMESH_Mesh*              theTargetMesh)
4813   throw (SALOME::SALOME_Exception)
4814 {
4815   SMESH_TRY;
4816   initData();
4817   if ( theScaleFact.length() < 1 )
4818     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
4819   if ( theScaleFact.length() == 2 )
4820     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
4821
4822   if ( theTargetMesh )
4823     theCopy = false;
4824
4825   TIDSortedElemSet elements;
4826   prepareIdSource( theObject );
4827   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4828   if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4829     return 0;
4830
4831   double S[3] = {
4832     theScaleFact[0],
4833     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
4834     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
4835   };
4836   double tol = std::numeric_limits<double>::max();
4837   gp_Trsf aTrsf;
4838
4839 #if OCC_VERSION_LARGE > 0x06070100
4840   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
4841                    0,    S[1], 0,    thePoint.y * (1-S[1]),
4842                    0,    0,    S[2], thePoint.z * (1-S[2]) );
4843 #else
4844   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
4845                    0,    S[1], 0,    thePoint.y * (1-S[1]),
4846                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
4847 #endif
4848
4849   TIDSortedElemSet  copyElements;
4850   TIDSortedElemSet* workElements = &elements;
4851   if ( myIsPreviewMode )
4852   {
4853     TPreviewMesh * tmpMesh = getPreviewMesh();
4854     tmpMesh->Copy( elements, copyElements);
4855     if ( !theCopy && !theTargetMesh )
4856     {
4857       TIDSortedElemSet elemsAround, elemsAroundCopy;
4858       getElementsAround( elements, getMeshDS(), elemsAround );
4859       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4860     }
4861     workElements = & copyElements;
4862     theMakeGroups = false;
4863   }
4864
4865   ::SMESH_MeshEditor::PGroupIDs groupIds =
4866       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4867
4868   if ( theCopy && !myIsPreviewMode )
4869   {
4870     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
4871     else                 declareMeshModified( /*isReComputeSafe=*/false );
4872   }
4873   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4874
4875   SMESH_CATCH( SMESH::throwCorbaException );
4876   return 0;
4877 }
4878
4879 //=======================================================================
4880 //function : Scale
4881 //purpose  :
4882 //=======================================================================
4883
4884 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
4885                                const SMESH::PointStruct&  thePoint,
4886                                const SMESH::double_array& theScaleFact,
4887                                CORBA::Boolean             theCopy)
4888   throw (SALOME::SALOME_Exception)
4889 {
4890   if ( !myIsPreviewMode ) {
4891     TPythonDump() << this << ".Scale( "
4892                   << theObject            << ", "
4893                   << thePoint             << ", "
4894                   << TVar( theScaleFact ) << ", "
4895                   << theCopy              << " )";
4896   }
4897   scale(theObject, thePoint, theScaleFact, theCopy, false);
4898 }
4899
4900
4901 //=======================================================================
4902 //function : ScaleMakeGroups
4903 //purpose  :
4904 //=======================================================================
4905
4906 SMESH::ListOfGroups*
4907 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
4908                                     const SMESH::PointStruct&  thePoint,
4909                                     const SMESH::double_array& theScaleFact)
4910   throw (SALOME::SALOME_Exception)
4911 {
4912   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4913
4914   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
4915   if (!myIsPreviewMode) {
4916     dumpGroupsList(aPythonDump, aGroups);
4917     aPythonDump << this << ".Scale("
4918                 << theObject            << ","
4919                 << thePoint             << ","
4920                 << TVar( theScaleFact ) << ",True,True)";
4921   }
4922   return aGroups;
4923 }
4924
4925
4926 //=======================================================================
4927 //function : ScaleMakeMesh
4928 //purpose  :
4929 //=======================================================================
4930
4931 SMESH::SMESH_Mesh_ptr
4932 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
4933                                   const SMESH::PointStruct&  thePoint,
4934                                   const SMESH::double_array& theScaleFact,
4935                                   CORBA::Boolean             theCopyGroups,
4936                                   const char*                theMeshName)
4937   throw (SALOME::SALOME_Exception)
4938 {
4939   SMESH_Mesh_i* mesh_i;
4940   SMESH::SMESH_Mesh_var mesh;
4941   { // open new scope to dump "MakeMesh" command
4942     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4943
4944     TPythonDump pydump; // to prevent dump at mesh creation
4945     mesh = makeMesh( theMeshName );
4946     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4947
4948     if ( mesh_i )
4949     {
4950       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4951       mesh_i->CreateGroupServants();
4952     }
4953     if ( !myIsPreviewMode )
4954       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4955              << theObject            << ", "
4956              << thePoint             << ", "
4957              << TVar( theScaleFact ) << ", "
4958              << theCopyGroups        << ", '"
4959              << theMeshName          << "' )";
4960   }
4961
4962   // dump "GetGroups"
4963   if (!myIsPreviewMode && mesh_i)
4964     mesh_i->GetGroups();
4965
4966   return mesh._retn();
4967 }
4968
4969
4970 //=======================================================================
4971 //function : FindCoincidentNodes
4972 //purpose  :
4973 //=======================================================================
4974
4975 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
4976                                               SMESH::array_of_long_array_out GroupsOfNodes)
4977   throw (SALOME::SALOME_Exception)
4978 {
4979   SMESH_TRY;
4980   initData();
4981
4982   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4983   TIDSortedNodeSet nodes; // no input nodes
4984   getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4985
4986   GroupsOfNodes = new SMESH::array_of_long_array;
4987   GroupsOfNodes->length( aListOfListOfNodes.size() );
4988   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4989   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
4990     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4991     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4992     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4993     aGroup.length( aListOfNodes.size() );
4994     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4995       aGroup[ j ] = (*lIt)->GetID();
4996   }
4997   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4998                 << Tolerance << " )";
4999
5000   SMESH_CATCH( SMESH::throwCorbaException );
5001 }
5002
5003 //=======================================================================
5004 //function : FindCoincidentNodesOnPart
5005 //purpose  :
5006 //=======================================================================
5007
5008 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
5009                                                    CORBA::Double                  Tolerance,
5010                                                    SMESH::array_of_long_array_out GroupsOfNodes)
5011   throw (SALOME::SALOME_Exception)
5012 {
5013   SMESH_TRY;
5014   initData();
5015
5016   TIDSortedNodeSet nodes;
5017   prepareIdSource( theObject );
5018   idSourceToNodeSet( theObject, getMeshDS(), nodes );
5019
5020   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
5021   if(!nodes.empty())
5022     getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
5023
5024   GroupsOfNodes = new SMESH::array_of_long_array;
5025   GroupsOfNodes->length( aListOfListOfNodes.size() );
5026   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
5027   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
5028   {
5029     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
5030     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
5031     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
5032     aGroup.length( aListOfNodes.size() );
5033     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
5034       aGroup[ j ] = (*lIt)->GetID();
5035   }
5036   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
5037                 <<theObject<<", "
5038                 << Tolerance << " )";
5039
5040   SMESH_CATCH( SMESH::throwCorbaException );
5041 }
5042
5043 //================================================================================
5044 /*!
5045  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
5046  *        ExceptSubMeshOrGroups
5047  */
5048 //================================================================================
5049
5050 void SMESH_MeshEditor_i::
5051 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
5052                              CORBA::Double                  theTolerance,
5053                              SMESH::array_of_long_array_out theGroupsOfNodes,
5054                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
5055   throw (SALOME::SALOME_Exception)
5056 {
5057   SMESH_TRY;
5058   initData();
5059
5060   TIDSortedNodeSet nodes;
5061   prepareIdSource( theObject );
5062   idSourceToNodeSet( theObject, getMeshDS(), nodes );
5063
5064   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
5065   {
5066     TIDSortedNodeSet exceptNodes;
5067     idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
5068     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
5069     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
5070       nodes.erase( *avoidNode );
5071   }
5072   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
5073   if(!nodes.empty())
5074     getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
5075
5076   theGroupsOfNodes = new SMESH::array_of_long_array;
5077   theGroupsOfNodes->length( aListOfListOfNodes.size() );
5078   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
5079   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
5080   {
5081     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
5082     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
5083     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
5084     aGroup.length( aListOfNodes.size() );
5085     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
5086       aGroup[ j ] = (*lIt)->GetID();
5087   }
5088   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
5089                 << theObject<<", "
5090                 << theTolerance << ", "
5091                 << theExceptSubMeshOrGroups << " )";
5092
5093   SMESH_CATCH( SMESH::throwCorbaException );
5094 }
5095
5096 //=======================================================================
5097 //function : MergeNodes
5098 //purpose  :
5099 //=======================================================================
5100
5101 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
5102   throw (SALOME::SALOME_Exception)
5103 {
5104   SMESH_TRY;
5105   initData();
5106
5107   SMESHDS_Mesh* aMesh = getMeshDS();
5108
5109   TPythonDump aTPythonDump;
5110   aTPythonDump << this << ".MergeNodes([";
5111   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
5112   for (int i = 0; i < GroupsOfNodes.length(); i++)
5113   {
5114     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
5115     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
5116     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
5117     for ( int j = 0; j < aNodeGroup.length(); j++ )
5118     {
5119       CORBA::Long index = aNodeGroup[ j ];
5120       const SMDS_MeshNode * node = aMesh->FindNode(index);
5121       if ( node )
5122         aListOfNodes.push_back( node );
5123     }
5124     if ( aListOfNodes.size() < 2 )
5125       aListOfListOfNodes.pop_back();
5126
5127     if ( i > 0 ) aTPythonDump << ", ";
5128     aTPythonDump << aNodeGroup;
5129   }
5130   getEditor().MergeNodes( aListOfListOfNodes );
5131
5132   aTPythonDump <<  "])";
5133
5134   declareMeshModified( /*isReComputeSafe=*/false );
5135
5136   SMESH_CATCH( SMESH::throwCorbaException );
5137 }
5138
5139 //=======================================================================
5140 //function : FindEqualElements
5141 //purpose  :
5142 //=======================================================================
5143
5144 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
5145                                            SMESH::array_of_long_array_out GroupsOfElementsID)
5146   throw (SALOME::SALOME_Exception)
5147 {
5148   SMESH_TRY;
5149   initData();
5150
5151   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
5152   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
5153   {
5154     TIDSortedElemSet elems;
5155     prepareIdSource( theObject );
5156     idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
5157
5158     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
5159     getEditor().FindEqualElements( elems, aListOfListOfElementsID );
5160
5161     GroupsOfElementsID = new SMESH::array_of_long_array;
5162     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
5163
5164     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
5165         aListOfListOfElementsID.begin();
5166     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
5167     {
5168       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
5169       list<int>&      listOfIDs = *arraysIt;
5170       aGroup.length( listOfIDs.size() );
5171       list<int>::iterator idIt = listOfIDs.begin();
5172       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
5173         aGroup[ k ] = *idIt;
5174     }
5175
5176     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
5177                   <<theObject<<" )";
5178   }
5179
5180   SMESH_CATCH( SMESH::throwCorbaException );
5181 }
5182
5183 //=======================================================================
5184 //function : MergeElements
5185 //purpose  :
5186 //=======================================================================
5187
5188 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
5189   throw (SALOME::SALOME_Exception)
5190 {
5191   SMESH_TRY;
5192   initData();
5193
5194   TPythonDump aTPythonDump;
5195   aTPythonDump << this << ".MergeElements( [";
5196
5197   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
5198
5199   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
5200     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
5201     aListOfListOfElementsID.push_back( list< int >() );
5202     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
5203     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
5204       CORBA::Long id = anElemsIDGroup[ j ];
5205       aListOfElemsID.push_back( id );
5206     }
5207     if ( aListOfElemsID.size() < 2 )
5208       aListOfListOfElementsID.pop_back();
5209     if ( i > 0 ) aTPythonDump << ", ";
5210     aTPythonDump << anElemsIDGroup;
5211   }
5212
5213   getEditor().MergeElements(aListOfListOfElementsID);
5214
5215   declareMeshModified( /*isReComputeSafe=*/true );
5216
5217   aTPythonDump << "] )";
5218
5219   SMESH_CATCH( SMESH::throwCorbaException );
5220 }
5221
5222 //=======================================================================
5223 //function : MergeEqualElements
5224 //purpose  :
5225 //=======================================================================
5226
5227 void SMESH_MeshEditor_i::MergeEqualElements()
5228   throw (SALOME::SALOME_Exception)
5229 {
5230   SMESH_TRY;
5231   initData();
5232
5233   getEditor().MergeEqualElements();
5234
5235   declareMeshModified( /*isReComputeSafe=*/true );
5236
5237   TPythonDump() << this << ".MergeEqualElements()";
5238
5239   SMESH_CATCH( SMESH::throwCorbaException );
5240 }
5241
5242 //=============================================================================
5243 /*!
5244  * Move the node to a given point
5245  */
5246 //=============================================================================
5247
5248 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
5249                                             CORBA::Double x,
5250                                             CORBA::Double y,
5251                                             CORBA::Double z)
5252   throw (SALOME::SALOME_Exception)
5253 {
5254   SMESH_TRY;
5255   initData(/*deleteSearchers=*/false);
5256
5257   const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
5258   if ( !node )
5259     return false;
5260
5261   if ( theNodeSearcher )
5262     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5263
5264   if ( myIsPreviewMode ) // make preview data
5265   {
5266     // in a preview mesh, make edges linked to a node
5267     TPreviewMesh& tmpMesh = *getPreviewMesh();
5268     TIDSortedElemSet linkedNodes;
5269     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
5270     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
5271     SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
5272     for ( ; nIt != linkedNodes.end(); ++nIt )
5273     {
5274       SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
5275       tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
5276     }
5277     // move copied node
5278     if ( nodeCpy1 )
5279       tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
5280     // fill preview data
5281   }
5282   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
5283     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
5284   else
5285     getMeshDS()->MoveNode(node, x, y, z);
5286
5287   if ( !myIsPreviewMode )
5288   {
5289     // Update Python script
5290     TPythonDump() << "isDone = " << this << ".MoveNode( "
5291                   << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
5292     declareMeshModified( /*isReComputeSafe=*/false );
5293   }
5294
5295   SMESH_CATCH( SMESH::throwCorbaException );
5296
5297   return true;
5298 }
5299
5300 //================================================================================
5301 /*!
5302  * \brief Return ID of node closest to a given point
5303  */
5304 //================================================================================
5305
5306 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
5307                                                   CORBA::Double y,
5308                                                   CORBA::Double z)
5309   throw (SALOME::SALOME_Exception)
5310 {
5311   SMESH_TRY;
5312   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5313
5314   if ( !theNodeSearcher ) {
5315     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
5316   }
5317   gp_Pnt p( x,y,z );
5318   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
5319     return node->GetID();
5320
5321   SMESH_CATCH( SMESH::throwCorbaException );
5322   return 0;
5323 }
5324
5325 //================================================================================
5326 /*!
5327  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
5328  * move the node closest to the point to point's location and return ID of the node
5329  */
5330 //================================================================================
5331
5332 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
5333                                                        CORBA::Double y,
5334                                                        CORBA::Double z,
5335                                                        CORBA::Long   theNodeID)
5336   throw (SALOME::SALOME_Exception)
5337 {
5338   SMESH_TRY;
5339   // We keep theNodeSearcher until any mesh modification:
5340   // 1) initData() deletes theNodeSearcher at any edition,
5341   // 2) TSearchersDeleter - at any mesh compute event and mesh change
5342
5343   initData(/*deleteSearchers=*/false);
5344
5345   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5346
5347   int nodeID = theNodeID;
5348   const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
5349   if ( !node ) // preview moving node
5350   {
5351     if ( !theNodeSearcher ) {
5352       theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
5353     }
5354     gp_Pnt p( x,y,z );
5355     node = theNodeSearcher->FindClosestTo( p );
5356   }
5357   if ( node ) {
5358     nodeID = node->GetID();
5359     if ( myIsPreviewMode ) // make preview data
5360     {
5361       // in a preview mesh, make edges linked to a node
5362       TPreviewMesh tmpMesh = *getPreviewMesh();
5363       TIDSortedElemSet linkedNodes;
5364       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
5365       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
5366       for ( ; nIt != linkedNodes.end(); ++nIt )
5367       {
5368         SMDS_LinearEdge edge( node, cast2Node( *nIt ));
5369         tmpMesh.Copy( &edge );
5370       }
5371       // move copied node
5372       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
5373       if ( node )
5374         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
5375       // fill preview data
5376     }
5377     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
5378     {
5379       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
5380     }
5381     else
5382     {
5383       getMeshDS()->MoveNode(node, x, y, z);
5384     }
5385   }
5386
5387   if ( !myIsPreviewMode )
5388   {
5389     TPythonDump() << "nodeID = " << this
5390                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
5391                   << ", " << nodeID << " )";
5392
5393     declareMeshModified( /*isReComputeSafe=*/false );
5394   }
5395
5396   return nodeID;
5397
5398   SMESH_CATCH( SMESH::throwCorbaException );
5399   return 0;
5400 }
5401
5402 //=======================================================================
5403 /*!
5404  * Return elements of given type where the given point is IN or ON.
5405  *
5406  * 'ALL' type means elements of any type excluding nodes
5407  */
5408 //=======================================================================
5409
5410 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
5411                                                            CORBA::Double      y,
5412                                                            CORBA::Double      z,
5413                                                            SMESH::ElementType type)
5414   throw (SALOME::SALOME_Exception)
5415 {
5416   SMESH_TRY;
5417   SMESH::long_array_var res = new SMESH::long_array;
5418   vector< const SMDS_MeshElement* > foundElems;
5419
5420   theSearchersDeleter.Set( myMesh );
5421   if ( !theElementSearcher ) {
5422     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
5423   }
5424   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
5425                                            SMDSAbs_ElementType( type ),
5426                                            foundElems);
5427   res->length( foundElems.size() );
5428   for ( int i = 0; i < foundElems.size(); ++i )
5429     res[i] = foundElems[i]->GetID();
5430
5431   return res._retn();
5432
5433   SMESH_CATCH( SMESH::throwCorbaException );
5434   return 0;
5435 }
5436
5437 //=======================================================================
5438 //function : FindAmongElementsByPoint
5439 //purpose  : Searching among the given elements, return elements of given type 
5440 //           where the given point is IN or ON.
5441 //           'ALL' type means elements of any type excluding nodes
5442 //=======================================================================
5443
5444 SMESH::long_array*
5445 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
5446                                              CORBA::Double             x,
5447                                              CORBA::Double             y,
5448                                              CORBA::Double             z,
5449                                              SMESH::ElementType        type)
5450   throw (SALOME::SALOME_Exception)
5451 {
5452   SMESH_TRY;
5453   SMESH::long_array_var res = new SMESH::long_array;
5454   
5455   SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
5456   if ( types->length() == 1 && // a part contains only nodes or 0D elements
5457        ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
5458        type != types[0] ) // but search of elements of dim > 0
5459     return res._retn();
5460
5461   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
5462     return FindElementsByPoint( x,y,z, type );
5463
5464   TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
5465
5466   theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
5467   if ( !theElementSearcher )
5468   {
5469     // create a searcher from elementIDs
5470     SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
5471     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
5472
5473     if ( !idSourceToSet( elementIDs, meshDS, elements,
5474                          SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
5475       return res._retn();
5476
5477     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5478     SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
5479
5480     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
5481   }
5482
5483   vector< const SMDS_MeshElement* > foundElems;
5484
5485   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
5486                                            SMDSAbs_ElementType( type ),
5487                                            foundElems);
5488   res->length( foundElems.size() );
5489   for ( int i = 0; i < foundElems.size(); ++i )
5490     res[i] = foundElems[i]->GetID();
5491
5492   return res._retn();
5493
5494   SMESH_CATCH( SMESH::throwCorbaException );
5495   return 0;
5496 }
5497
5498 //=======================================================================
5499 //function : GetPointState
5500 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
5501 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
5502 //=======================================================================
5503
5504 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
5505                                                CORBA::Double y,
5506                                                CORBA::Double z)
5507   throw (SALOME::SALOME_Exception)
5508 {
5509   SMESH_TRY;
5510   theSearchersDeleter.Set( myMesh );
5511   if ( !theElementSearcher ) {
5512     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
5513   }
5514   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
5515
5516   SMESH_CATCH( SMESH::throwCorbaException );
5517   return 0;
5518 }
5519
5520 //=======================================================================
5521 //function : convError
5522 //purpose  :
5523 //=======================================================================
5524
5525 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5526
5527 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5528 {
5529   switch ( e ) {
5530     RETCASE( SEW_OK );
5531     RETCASE( SEW_BORDER1_NOT_FOUND );
5532     RETCASE( SEW_BORDER2_NOT_FOUND );
5533     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5534     RETCASE( SEW_BAD_SIDE_NODES );
5535     RETCASE( SEW_VOLUMES_TO_SPLIT );
5536     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5537     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5538     RETCASE( SEW_BAD_SIDE1_NODES );
5539     RETCASE( SEW_BAD_SIDE2_NODES );
5540   }
5541   return SMESH::SMESH_MeshEditor::SEW_OK;
5542 }
5543
5544 //=======================================================================
5545 //function : SewFreeBorders
5546 //purpose  :
5547 //=======================================================================
5548
5549 SMESH::SMESH_MeshEditor::Sew_Error
5550 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5551                                    CORBA::Long SecondNodeID1,
5552                                    CORBA::Long LastNodeID1,
5553                                    CORBA::Long FirstNodeID2,
5554                                    CORBA::Long SecondNodeID2,
5555                                    CORBA::Long LastNodeID2,
5556                                    CORBA::Boolean CreatePolygons,
5557                                    CORBA::Boolean CreatePolyedrs)
5558   throw (SALOME::SALOME_Exception)
5559 {
5560   SMESH_TRY;
5561   initData();
5562
5563   SMESHDS_Mesh* aMesh = getMeshDS();
5564
5565   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5566   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5567   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5568   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5569   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5570   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
5571
5572   if (!aBorderFirstNode ||
5573       !aBorderSecondNode||
5574       !aBorderLastNode)
5575     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5576   if (!aSide2FirstNode  ||
5577       !aSide2SecondNode ||
5578       !aSide2ThirdNode)
5579     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5580
5581   TPythonDump() << "error = " << this << ".SewFreeBorders( "
5582                 << FirstNodeID1  << ", "
5583                 << SecondNodeID1 << ", "
5584                 << LastNodeID1   << ", "
5585                 << FirstNodeID2  << ", "
5586                 << SecondNodeID2 << ", "
5587                 << LastNodeID2   << ", "
5588                 << CreatePolygons<< ", "
5589                 << CreatePolyedrs<< " )";
5590
5591   SMESH::SMESH_MeshEditor::Sew_Error error =
5592     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5593                                        aBorderSecondNode,
5594                                        aBorderLastNode,
5595                                        aSide2FirstNode,
5596                                        aSide2SecondNode,
5597                                        aSide2ThirdNode,
5598                                        true,
5599                                        CreatePolygons,
5600                                        CreatePolyedrs) );
5601
5602
5603   declareMeshModified( /*isReComputeSafe=*/false );
5604   return error;
5605
5606   SMESH_CATCH( SMESH::throwCorbaException );
5607   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5608 }
5609
5610
5611 //=======================================================================
5612 //function : SewConformFreeBorders
5613 //purpose  :
5614 //=======================================================================
5615
5616 SMESH::SMESH_MeshEditor::Sew_Error
5617 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5618                                           CORBA::Long SecondNodeID1,
5619                                           CORBA::Long LastNodeID1,
5620                                           CORBA::Long FirstNodeID2,
5621                                           CORBA::Long SecondNodeID2)
5622   throw (SALOME::SALOME_Exception)
5623 {
5624   SMESH_TRY;
5625   initData();
5626
5627   SMESHDS_Mesh* aMesh = getMeshDS();
5628
5629   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5630   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5631   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5632   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5633   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5634   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5635
5636   if (!aBorderFirstNode ||
5637       !aBorderSecondNode||
5638       !aBorderLastNode )
5639     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5640   if (!aSide2FirstNode  ||
5641       !aSide2SecondNode)
5642     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5643
5644   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5645                 << FirstNodeID1  << ", "
5646                 << SecondNodeID1 << ", "
5647                 << LastNodeID1   << ", "
5648                 << FirstNodeID2  << ", "
5649                 << SecondNodeID2 << " )";
5650
5651   SMESH::SMESH_MeshEditor::Sew_Error error =
5652     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5653                                        aBorderSecondNode,
5654                                        aBorderLastNode,
5655                                        aSide2FirstNode,
5656                                        aSide2SecondNode,
5657                                        aSide2ThirdNode,
5658                                        true,
5659                                        false, false) );
5660
5661   declareMeshModified( /*isReComputeSafe=*/false );
5662   return error;
5663
5664   SMESH_CATCH( SMESH::throwCorbaException );
5665   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5666 }
5667
5668
5669 //=======================================================================
5670 //function : SewBorderToSide
5671 //purpose  :
5672 //=======================================================================
5673
5674 SMESH::SMESH_MeshEditor::Sew_Error
5675 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5676                                     CORBA::Long SecondNodeIDOnFreeBorder,
5677                                     CORBA::Long LastNodeIDOnFreeBorder,
5678                                     CORBA::Long FirstNodeIDOnSide,
5679                                     CORBA::Long LastNodeIDOnSide,
5680                                     CORBA::Boolean CreatePolygons,
5681                                     CORBA::Boolean CreatePolyedrs)
5682   throw (SALOME::SALOME_Exception)
5683 {
5684   SMESH_TRY;
5685   initData();
5686
5687   SMESHDS_Mesh* aMesh = getMeshDS();
5688
5689   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
5690   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5691   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
5692   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
5693   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
5694   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5695
5696   if (!aBorderFirstNode ||
5697       !aBorderSecondNode||
5698       !aBorderLastNode  )
5699     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5700   if (!aSide2FirstNode  ||
5701       !aSide2SecondNode)
5702     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5703
5704   TPythonDump() << "error = " << this << ".SewBorderToSide( "
5705                 << FirstNodeIDOnFreeBorder  << ", "
5706                 << SecondNodeIDOnFreeBorder << ", "
5707                 << LastNodeIDOnFreeBorder   << ", "
5708                 << FirstNodeIDOnSide        << ", "
5709                 << LastNodeIDOnSide         << ", "
5710                 << CreatePolygons           << ", "
5711                 << CreatePolyedrs           << ") ";
5712
5713   SMESH::SMESH_MeshEditor::Sew_Error error =
5714     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5715                                        aBorderSecondNode,
5716                                        aBorderLastNode,
5717                                        aSide2FirstNode,
5718                                        aSide2SecondNode,
5719                                        aSide2ThirdNode,
5720                                        false,
5721                                        CreatePolygons,
5722                                        CreatePolyedrs) );
5723
5724   declareMeshModified( /*isReComputeSafe=*/false );
5725   return error;
5726
5727   SMESH_CATCH( SMESH::throwCorbaException );
5728   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5729 }
5730
5731
5732 //=======================================================================
5733 //function : SewSideElements
5734 //purpose  :
5735 //=======================================================================
5736
5737 SMESH::SMESH_MeshEditor::Sew_Error
5738 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5739                                     const SMESH::long_array& IDsOfSide2Elements,
5740                                     CORBA::Long NodeID1OfSide1ToMerge,
5741                                     CORBA::Long NodeID1OfSide2ToMerge,
5742                                     CORBA::Long NodeID2OfSide1ToMerge,
5743                                     CORBA::Long NodeID2OfSide2ToMerge)
5744   throw (SALOME::SALOME_Exception)
5745 {
5746   SMESH_TRY;
5747   initData();
5748
5749   SMESHDS_Mesh* aMesh = getMeshDS();
5750
5751   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
5752   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
5753   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5754   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5755
5756   if (!aFirstNode1ToMerge ||
5757       !aFirstNode2ToMerge )
5758     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5759   if (!aSecondNode1ToMerge||
5760       !aSecondNode2ToMerge)
5761     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5762
5763   TIDSortedElemSet aSide1Elems, aSide2Elems;
5764   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5765   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5766
5767   TPythonDump() << "error = " << this << ".SewSideElements( "
5768                 << IDsOfSide1Elements << ", "
5769                 << IDsOfSide2Elements << ", "
5770                 << NodeID1OfSide1ToMerge << ", "
5771                 << NodeID1OfSide2ToMerge << ", "
5772                 << NodeID2OfSide1ToMerge << ", "
5773                 << NodeID2OfSide2ToMerge << ")";
5774
5775   SMESH::SMESH_MeshEditor::Sew_Error error =
5776     convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5777                                          aFirstNode1ToMerge,
5778                                          aFirstNode2ToMerge,
5779                                          aSecondNode1ToMerge,
5780                                          aSecondNode2ToMerge));
5781
5782   declareMeshModified( /*isReComputeSafe=*/false );
5783   return error;
5784
5785   SMESH_CATCH( SMESH::throwCorbaException );
5786   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5787 }
5788
5789 //================================================================================
5790 /*!
5791  * \brief Set new nodes for given element
5792  * \param ide - element id
5793  * \param newIDs - new node ids
5794  * \retval CORBA::Boolean - true if result is OK
5795  */
5796 //================================================================================
5797
5798 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5799                                                    const SMESH::long_array& newIDs)
5800   throw (SALOME::SALOME_Exception)
5801 {
5802   SMESH_TRY;
5803   initData();
5804
5805   const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5806   if(!elem) return false;
5807
5808   int nbn = newIDs.length();
5809   int i=0;
5810   vector<const SMDS_MeshNode*> aNodes(nbn);
5811   int nbn1=-1;
5812   for(; i<nbn; i++) {
5813     const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5814     if(aNode) {
5815       nbn1++;
5816       aNodes[nbn1] = aNode;
5817     }
5818   }
5819   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5820                 << ide << ", " << newIDs << " )";
5821
5822   MESSAGE("ChangeElementNodes");
5823   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5824
5825   declareMeshModified( /*isReComputeSafe=*/ !res );
5826
5827   return res;
5828
5829   SMESH_CATCH( SMESH::throwCorbaException );
5830   return 0;
5831 }
5832
5833 //=======================================================================
5834 /*!
5835  * \brief Makes a part of the mesh quadratic or bi-quadratic
5836  */
5837 //=======================================================================
5838
5839 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean            theForce3d,
5840                                             CORBA::Boolean            theToBiQuad,
5841                                             SMESH::SMESH_IDSource_ptr theObject)
5842   throw (SALOME::SALOME_Exception)
5843 {
5844   SMESH_TRY;
5845   TIDSortedElemSet elems;
5846   bool elemsOK;
5847   if ( !( elemsOK = CORBA::is_nil( theObject )))
5848   {
5849     prepareIdSource( theObject );
5850     elemsOK =  idSourceToSet( theObject, getMeshDS(), elems,
5851                               SMDSAbs_All, /*emptyIfIsMesh=*/true );
5852   }
5853   if ( elemsOK )
5854   {
5855     if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5856       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5857
5858     if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5859     else                 getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5860
5861     declareMeshModified( /*isReComputeSafe=*/false );
5862   }
5863
5864   SMESH_CATCH( SMESH::throwCorbaException );
5865 }
5866
5867 //=======================================================================
5868 //function : ConvertFromQuadratic
5869 //purpose  :
5870 //=======================================================================
5871
5872 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5873   throw (SALOME::SALOME_Exception)
5874 {
5875   CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5876   TPythonDump() << this << ".ConvertFromQuadratic()";
5877   declareMeshModified( /*isReComputeSafe=*/!isDone );
5878   return isDone;
5879 }
5880
5881 //=======================================================================
5882 //function : ConvertToQuadratic
5883 //purpose  :
5884 //=======================================================================
5885
5886 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5887   throw (SALOME::SALOME_Exception)
5888 {
5889   convertToQuadratic( theForce3d, false );
5890   TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5891 }
5892
5893 //================================================================================
5894 /*!
5895  * \brief Makes a part of the mesh quadratic
5896  */
5897 //================================================================================
5898
5899 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theForce3d,
5900                                                   SMESH::SMESH_IDSource_ptr theObject)
5901   throw (SALOME::SALOME_Exception)
5902 {
5903   convertToQuadratic( theForce3d, false, theObject );
5904   TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5905 }
5906
5907 //================================================================================
5908 /*!
5909  * \brief Makes a part of the mesh bi-quadratic
5910  */
5911 //================================================================================
5912
5913 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean            theForce3d,
5914                                               SMESH::SMESH_IDSource_ptr theObject)
5915   throw (SALOME::SALOME_Exception)
5916 {
5917   convertToQuadratic( theForce3d, true, theObject );
5918   TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5919 }
5920
5921 //================================================================================
5922 /*!
5923  * \brief Makes a part of the mesh linear
5924  */
5925 //================================================================================
5926
5927 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5928   throw (SALOME::SALOME_Exception)
5929 {
5930   SMESH_TRY;
5931
5932   TPythonDump pyDump;
5933
5934   TIDSortedElemSet elems;
5935   prepareIdSource( theObject );
5936   if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5937   {
5938     if ( elems.empty() )
5939     {
5940       ConvertFromQuadratic();
5941     }
5942     else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5943     {
5944       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5945     }
5946     else
5947     {
5948       getEditor().ConvertFromQuadratic(elems);
5949     }
5950   }
5951   declareMeshModified( /*isReComputeSafe=*/false );
5952
5953   pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5954
5955   SMESH_CATCH( SMESH::throwCorbaException );
5956 }
5957
5958 //=======================================================================
5959 //function : makeMesh
5960 //purpose  : create a named imported mesh
5961 //=======================================================================
5962
5963 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5964 {
5965   SMESH_Gen_i*              gen = SMESH_Gen_i::GetSMESHGen();
5966   SMESH::SMESH_Mesh_var    mesh = gen->CreateEmptyMesh();
5967   SALOMEDS::Study_var     study = gen->GetCurrentStudy();
5968   SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5969   gen->SetName( meshSO, theMeshName, "Mesh" );
5970   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5971
5972   return mesh._retn();
5973 }
5974
5975 //=======================================================================
5976 //function : dumpGroupsList
5977 //purpose  :
5978 //=======================================================================
5979
5980 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPython,
5981                                         const SMESH::ListOfGroups * theGroupList)
5982 {
5983   bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5984   if ( isDumpGroupList )
5985     theDumpPython << theGroupList << " = ";
5986 }
5987
5988 //================================================================================
5989 /*!
5990   \brief Generates the unique group name.
5991   \param thePrefix name prefix
5992   \return unique name
5993 */
5994 //================================================================================
5995
5996 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5997 {
5998   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5999   set<string> groupNames;
6000
6001   // Get existing group names
6002   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
6003     SMESH::SMESH_GroupBase_var aGroup = groups[i];
6004     if (CORBA::is_nil(aGroup))
6005       continue;
6006
6007     CORBA::String_var name = aGroup->GetName();
6008     groupNames.insert( name.in() );
6009   }
6010
6011   // Find new name
6012   string name = thePrefix;
6013   int index = 0;
6014
6015   while (!groupNames.insert(name).second)
6016     name = SMESH_Comment( thePrefix ) << "_" << index++;
6017
6018   return name;
6019 }
6020
6021 //================================================================================
6022 /*!
6023  * \brief Prepare SMESH_IDSource for work
6024  */
6025 //================================================================================
6026
6027 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
6028 {
6029   if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
6030   {
6031     SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
6032     filter->SetMesh( mesh );
6033   }
6034 }
6035
6036 //================================================================================
6037 /*!
6038  * \brief Duplicates given elements, i.e. creates new elements based on the 
6039  *        same nodes as the given ones.
6040  * \param theElements - container of elements to duplicate.
6041  * \param theGroupName - a name of group to contain the generated elements.
6042  *                    If a group with such a name already exists, the new elements
6043  *                    are added to the existng group, else a new group is created.
6044  *                    If \a theGroupName is empty, new elements are not added 
6045  *                    in any group.
6046  * \return a group where the new elements are added. NULL if theGroupName == "".
6047  * \sa DoubleNode()
6048  */
6049 //================================================================================
6050
6051 SMESH::SMESH_Group_ptr
6052 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
6053                                    const char*               theGroupName)
6054   throw (SALOME::SALOME_Exception)
6055 {
6056   SMESH::SMESH_Group_var newGroup;
6057
6058   SMESH_TRY;
6059   initData();
6060
6061   TPythonDump pyDump;
6062
6063   TIDSortedElemSet elems;
6064   prepareIdSource( theElements );
6065   if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
6066   {
6067     getEditor().DoubleElements( elems );
6068
6069     if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
6070     {
6071       // group type
6072       SMESH::ElementType type =
6073         SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
6074       // find existing group
6075       SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
6076       for ( size_t i = 0; i < groups->length(); ++i )
6077         if ( groups[i]->GetType() == type )
6078         {
6079           CORBA::String_var name = groups[i]->GetName();
6080           if ( strcmp( name, theGroupName ) == 0 ) {
6081             newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
6082             break;
6083           }
6084         }
6085       // create a new group
6086       if ( newGroup->_is_nil() )
6087         newGroup = myMesh_i->CreateGroup( type, theGroupName );
6088       // fill newGroup
6089       if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
6090       {
6091         SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
6092         const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
6093         for ( int i = 1; i <= aSeq.Length(); i++ )
6094           groupDS->SMDSGroup().Add( aSeq(i) );
6095       }
6096     }
6097   }
6098   // python dump
6099   if ( !newGroup->_is_nil() )
6100     pyDump << newGroup << " = ";
6101   pyDump << this << ".DoubleElements( "
6102          << theElements << ", " << "'" << theGroupName <<"')";
6103
6104   SMESH_CATCH( SMESH::throwCorbaException );
6105
6106   return newGroup._retn();
6107 }
6108
6109 //================================================================================
6110 /*!
6111   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6112   \param theNodes - identifiers of nodes to be doubled
6113   \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
6114          nodes. If list of element identifiers is empty then nodes are doubled but
6115          they not assigned to elements
6116   \return TRUE if operation has been completed successfully, FALSE otherwise
6117   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
6118 */
6119 //================================================================================
6120
6121 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
6122                                                 const SMESH::long_array& theModifiedElems )
6123   throw (SALOME::SALOME_Exception)
6124 {
6125   SMESH_TRY;
6126   initData();
6127
6128   list< int > aListOfNodes;
6129   int i, n;
6130   for ( i = 0, n = theNodes.length(); i < n; i++ )
6131     aListOfNodes.push_back( theNodes[ i ] );
6132
6133   list< int > aListOfElems;
6134   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6135     aListOfElems.push_back( theModifiedElems[ i ] );
6136
6137   bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
6138
6139   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6140
6141   // Update Python script
6142   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
6143
6144   return aResult;
6145
6146   SMESH_CATCH( SMESH::throwCorbaException );
6147   return 0;
6148 }
6149
6150 //================================================================================
6151 /*!
6152   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6153   This method provided for convenience works as DoubleNodes() described above.
6154   \param theNodeId - identifier of node to be doubled.
6155   \param theModifiedElems - identifiers of elements to be updated.
6156   \return TRUE if operation has been completed successfully, FALSE otherwise
6157   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
6158 */
6159 //================================================================================
6160
6161 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
6162                                                const SMESH::long_array& theModifiedElems )
6163   throw (SALOME::SALOME_Exception)
6164 {
6165   SMESH_TRY;
6166   SMESH::long_array_var aNodes = new SMESH::long_array;
6167   aNodes->length( 1 );
6168   aNodes[ 0 ] = theNodeId;
6169
6170   TPythonDump pyDump; // suppress dump by the next line
6171
6172   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
6173
6174   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6175
6176   return done;
6177
6178   SMESH_CATCH( SMESH::throwCorbaException );
6179   return 0;
6180 }
6181
6182 //================================================================================
6183 /*!
6184   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6185   This method provided for convenience works as DoubleNodes() described above.
6186   \param theNodes - group of nodes to be doubled.
6187   \param theModifiedElems - group of elements to be updated.
6188   \return TRUE if operation has been completed successfully, FALSE otherwise
6189   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6190 */
6191 //================================================================================
6192
6193 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6194                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
6195   throw (SALOME::SALOME_Exception)
6196 {
6197   SMESH_TRY;
6198   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6199     return false;
6200
6201   SMESH::long_array_var aNodes = theNodes->GetListOfID();
6202   SMESH::long_array_var aModifiedElems;
6203   if ( !CORBA::is_nil( theModifiedElems ) )
6204     aModifiedElems = theModifiedElems->GetListOfID();
6205   else
6206   {
6207     aModifiedElems = new SMESH::long_array;
6208     aModifiedElems->length( 0 );
6209   }
6210
6211   TPythonDump pyDump; // suppress dump by the next line
6212
6213   bool done = DoubleNodes( aNodes, aModifiedElems );
6214
6215   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6216
6217   return done;
6218
6219   SMESH_CATCH( SMESH::throwCorbaException );
6220   return 0;
6221 }
6222
6223 //================================================================================
6224 /*!
6225  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6226  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6227  * \param theNodes - group of nodes to be doubled.
6228  * \param theModifiedElems - group of elements to be updated.
6229  * \return a new group with newly created nodes
6230  * \sa DoubleNodeGroup()
6231  */
6232 //================================================================================
6233
6234 SMESH::SMESH_Group_ptr
6235 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6236                                         SMESH::SMESH_GroupBase_ptr theModifiedElems )
6237   throw (SALOME::SALOME_Exception)
6238 {
6239   SMESH_TRY;
6240   SMESH::SMESH_Group_var aNewGroup;
6241
6242   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6243     return aNewGroup._retn();
6244
6245   // Duplicate nodes
6246   SMESH::long_array_var aNodes = theNodes->GetListOfID();
6247   SMESH::long_array_var aModifiedElems;
6248   if ( !CORBA::is_nil( theModifiedElems ) )
6249     aModifiedElems = theModifiedElems->GetListOfID();
6250   else {
6251     aModifiedElems = new SMESH::long_array;
6252     aModifiedElems->length( 0 );
6253   }
6254
6255   TPythonDump pyDump; // suppress dump by the next line
6256
6257   bool aResult = DoubleNodes( aNodes, aModifiedElems );
6258   if ( aResult )
6259   {
6260     // Create group with newly created nodes
6261     SMESH::long_array_var anIds = GetLastCreatedNodes();
6262     if (anIds->length() > 0) {
6263       string anUnindexedName (theNodes->GetName());
6264       string aNewName = generateGroupName(anUnindexedName + "_double");
6265       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6266       aNewGroup->Add(anIds);
6267       pyDump << aNewGroup << " = ";
6268     }
6269   }
6270
6271   pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6272          << theModifiedElems << " )";
6273
6274   return aNewGroup._retn();
6275
6276   SMESH_CATCH( SMESH::throwCorbaException );
6277   return 0;
6278 }
6279
6280 //================================================================================
6281 /*!
6282   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6283   This method provided for convenience works as DoubleNodes() described above.
6284   \param theNodes - list of groups of nodes to be doubled
6285   \param theModifiedElems - list of groups of elements to be updated.
6286   \return TRUE if operation has been completed successfully, FALSE otherwise
6287   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6288 */
6289 //================================================================================
6290
6291 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6292                                                     const SMESH::ListOfGroups& theModifiedElems )
6293   throw (SALOME::SALOME_Exception)
6294 {
6295   SMESH_TRY;
6296   initData();
6297
6298   std::list< int > aNodes;
6299   int i, n, j, m;
6300   for ( i = 0, n = theNodes.length(); i < n; i++ )
6301   {
6302     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6303     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6304     {
6305       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6306       for ( j = 0, m = aCurr->length(); j < m; j++ )
6307         aNodes.push_back( aCurr[ j ] );
6308     }
6309   }
6310
6311   std::list< int > anElems;
6312   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6313   {
6314     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6315     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6316     {
6317       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6318       for ( j = 0, m = aCurr->length(); j < m; j++ )
6319         anElems.push_back( aCurr[ j ] );
6320     }
6321   }
6322
6323   bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6324
6325   declareMeshModified( /*isReComputeSafe=*/false );
6326
6327   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6328
6329   return aResult;
6330
6331   SMESH_CATCH( SMESH::throwCorbaException );
6332   return 0;
6333 }
6334
6335 //================================================================================
6336 /*!
6337  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6338  * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6339  * \param theNodes - group of nodes to be doubled.
6340  * \param theModifiedElems - group of elements to be updated.
6341  * \return a new group with newly created nodes
6342  * \sa DoubleNodeGroups()
6343  */
6344 //================================================================================
6345
6346 SMESH::SMESH_Group_ptr
6347 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6348                                          const SMESH::ListOfGroups& theModifiedElems )
6349   throw (SALOME::SALOME_Exception)
6350 {
6351   SMESH::SMESH_Group_var aNewGroup;
6352
6353   TPythonDump pyDump; // suppress dump by the next line
6354
6355   bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6356
6357   if ( aResult )
6358   {
6359     // Create group with newly created nodes
6360     SMESH::long_array_var anIds = GetLastCreatedNodes();
6361     if (anIds->length() > 0) {
6362       string anUnindexedName (theNodes[0]->GetName());
6363       string aNewName = generateGroupName(anUnindexedName + "_double");
6364       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6365       aNewGroup->Add(anIds);
6366       pyDump << aNewGroup << " = ";
6367     }
6368   }
6369
6370   pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6371          << theModifiedElems << " )";
6372
6373   return aNewGroup._retn();
6374 }
6375
6376
6377 //================================================================================
6378 /*!
6379   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6380   \param theElems - the list of elements (edges or faces) to be replicated
6381   The nodes for duplication could be found from these elements
6382   \param theNodesNot - list of nodes to NOT replicate
6383   \param theAffectedElems - the list of elements (cells and edges) to which the
6384   replicated nodes should be associated to.
6385   \return TRUE if operation has been completed successfully, FALSE otherwise
6386   \sa DoubleNodeGroup(), DoubleNodeGroups()
6387 */
6388 //================================================================================
6389
6390 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6391                                                    const SMESH::long_array& theNodesNot,
6392                                                    const SMESH::long_array& theAffectedElems )
6393   throw (SALOME::SALOME_Exception)
6394 {
6395   SMESH_TRY;
6396   initData();
6397
6398   SMESHDS_Mesh* aMeshDS = getMeshDS();
6399   TIDSortedElemSet anElems, aNodes, anAffected;
6400   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6401   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6402   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6403
6404   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6405
6406   // Update Python script
6407   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6408                 << theNodesNot << ", " << theAffectedElems << " )";
6409
6410   declareMeshModified( /*isReComputeSafe=*/false );
6411   return aResult;
6412
6413   SMESH_CATCH( SMESH::throwCorbaException );
6414   return 0;
6415 }
6416
6417 //================================================================================
6418 /*!
6419   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6420   \param theElems - the list of elements (edges or faces) to be replicated
6421   The nodes for duplication could be found from these elements
6422   \param theNodesNot - list of nodes to NOT replicate
6423   \param theShape - shape to detect affected elements (element which geometric center
6424   located on or inside shape).
6425   The replicated nodes should be associated to affected elements.
6426   \return TRUE if operation has been completed successfully, FALSE otherwise
6427   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6428 */
6429 //================================================================================
6430
6431 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6432                                                             const SMESH::long_array& theNodesNot,
6433                                                             GEOM::GEOM_Object_ptr    theShape )
6434   throw (SALOME::SALOME_Exception)
6435 {
6436   SMESH_TRY;
6437   initData();
6438
6439
6440   SMESHDS_Mesh* aMeshDS = getMeshDS();
6441   TIDSortedElemSet anElems, aNodes;
6442   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6443   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6444
6445   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6446   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6447
6448   // Update Python script
6449   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6450                 << theNodesNot << ", " << theShape << " )";
6451
6452   declareMeshModified( /*isReComputeSafe=*/false );
6453   return aResult;
6454
6455   SMESH_CATCH( SMESH::throwCorbaException );
6456   return 0;
6457 }
6458
6459 //================================================================================
6460 /*!
6461   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6462   \param theElems - group of of elements (edges or faces) to be replicated
6463   \param theNodesNot - group of nodes not to replicated
6464   \param theAffectedElems - group of elements to which the replicated nodes
6465   should be associated to.
6466   \return TRUE if operation has been completed successfully, FALSE otherwise
6467   \sa DoubleNodes(), DoubleNodeGroups()
6468 */
6469 //================================================================================
6470
6471 CORBA::Boolean
6472 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6473                                         SMESH::SMESH_GroupBase_ptr theNodesNot,
6474                                         SMESH::SMESH_GroupBase_ptr theAffectedElems)
6475   throw (SALOME::SALOME_Exception)
6476 {
6477   SMESH_TRY;
6478   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6479     return false;
6480
6481   initData();
6482
6483
6484   SMESHDS_Mesh* aMeshDS = getMeshDS();
6485   TIDSortedElemSet anElems, aNodes, anAffected;
6486   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6487   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6488   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6489
6490   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6491
6492   // Update Python script
6493   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6494                 << theNodesNot << ", " << theAffectedElems << " )";
6495
6496   declareMeshModified( /*isReComputeSafe=*/false );
6497   return aResult;
6498
6499   SMESH_CATCH( SMESH::throwCorbaException );
6500   return 0;
6501 }
6502
6503 //================================================================================
6504 /*!
6505  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6506  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6507  * \param theElems - group of of elements (edges or faces) to be replicated
6508  * \param theNodesNot - group of nodes not to replicated
6509  * \param theAffectedElems - group of elements to which the replicated nodes
6510  *        should be associated to.
6511  * \return a new group with newly created elements
6512  * \sa DoubleNodeElemGroup()
6513  */
6514 //================================================================================
6515
6516 SMESH::SMESH_Group_ptr
6517 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6518                                            SMESH::SMESH_GroupBase_ptr theNodesNot,
6519                                            SMESH::SMESH_GroupBase_ptr theAffectedElems)
6520   throw (SALOME::SALOME_Exception)
6521 {
6522   TPythonDump pyDump;
6523   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6524                                                                theNodesNot,
6525                                                                theAffectedElems,
6526                                                                true, false );
6527   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6528   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6529
6530   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6531          << theElems         << ", "
6532          << theNodesNot      << ", "
6533          << theAffectedElems << " )";
6534
6535   return elemGroup._retn();
6536 }
6537
6538 //================================================================================
6539 /*!
6540  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6541  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6542  * \param theElems - group of of elements (edges or faces) to be replicated
6543  * \param theNodesNot - group of nodes not to replicated
6544  * \param theAffectedElems - group of elements to which the replicated nodes
6545  *        should be associated to.
6546  * \return a new group with newly created elements
6547  * \sa DoubleNodeElemGroup()
6548  */
6549 //================================================================================
6550
6551 SMESH::ListOfGroups*
6552 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6553                                             SMESH::SMESH_GroupBase_ptr theNodesNot,
6554                                             SMESH::SMESH_GroupBase_ptr theAffectedElems,
6555                                             CORBA::Boolean             theElemGroupNeeded,
6556                                             CORBA::Boolean             theNodeGroupNeeded)
6557   throw (SALOME::SALOME_Exception)
6558 {
6559   SMESH_TRY;
6560   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6561   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6562   aTwoGroups->length( 2 );
6563
6564   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6565     return aTwoGroups._retn();
6566
6567   initData();
6568
6569
6570   SMESHDS_Mesh* aMeshDS = getMeshDS();
6571   TIDSortedElemSet anElems, aNodes, anAffected;
6572   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6573   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6574   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6575
6576
6577   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6578
6579   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6580
6581   TPythonDump pyDump;
6582
6583   if ( aResult )
6584   {
6585     // Create group with newly created elements
6586     CORBA::String_var elemGroupName = theElems->GetName();
6587     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6588     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6589     {
6590       SMESH::long_array_var anIds = GetLastCreatedElems();
6591       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6592       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6593       aNewElemGroup->Add(anIds);
6594     }
6595     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6596     {
6597       SMESH::long_array_var anIds = GetLastCreatedNodes();
6598       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6599       aNewNodeGroup->Add(anIds);
6600     }
6601   }
6602
6603   // Update Python script
6604
6605   pyDump << "[ ";
6606   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6607   else                            pyDump << aNewElemGroup << ", ";
6608   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6609   else                            pyDump << aNewNodeGroup << " ] = ";
6610
6611   pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6612          << theNodesNot        << ", "
6613          << theAffectedElems   << ", "
6614          << theElemGroupNeeded << ", "
6615          << theNodeGroupNeeded <<" )";
6616
6617   aTwoGroups[0] = aNewElemGroup._retn();
6618   aTwoGroups[1] = aNewNodeGroup._retn();
6619   return aTwoGroups._retn();
6620
6621   SMESH_CATCH( SMESH::throwCorbaException );
6622   return 0;
6623 }
6624
6625 //================================================================================
6626 /*!
6627   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6628   \param theElems - group of of elements (edges or faces) to be replicated
6629   \param theNodesNot - group of nodes not to replicated
6630   \param theShape - shape to detect affected elements (element which geometric center
6631   located on or inside shape).
6632   The replicated nodes should be associated to affected elements.
6633   \return TRUE if operation has been completed successfully, FALSE otherwise
6634   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6635 */
6636 //================================================================================
6637
6638 CORBA::Boolean
6639 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6640                                                 SMESH::SMESH_GroupBase_ptr theNodesNot,
6641                                                 GEOM::GEOM_Object_ptr      theShape )
6642   throw (SALOME::SALOME_Exception)
6643 {
6644   SMESH_TRY;
6645   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6646     return false;
6647
6648   initData();
6649
6650
6651   SMESHDS_Mesh* aMeshDS = getMeshDS();
6652   TIDSortedElemSet anElems, aNodes, anAffected;
6653   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6654   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6655
6656   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6657   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6658
6659
6660   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6661
6662   // Update Python script
6663   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6664                 << theNodesNot << ", " << theShape << " )";
6665   return aResult;
6666
6667   SMESH_CATCH( SMESH::throwCorbaException );
6668   return 0;
6669 }
6670
6671 //================================================================================
6672 /*!
6673  * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6674  *  \param [in] theGrpList - groups
6675  *  \param [in] theMeshDS -  mesh
6676  *  \param [out] theElemSet - set of elements
6677  *  \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6678  */
6679 //================================================================================
6680
6681 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6682                              SMESHDS_Mesh*              theMeshDS,
6683                              TIDSortedElemSet&          theElemSet,
6684                              const bool                 theIsNodeGrp)
6685 {
6686   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6687   {
6688     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6689     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6690                                     : aGrp->GetType() != SMESH::NODE ) )
6691     {
6692       SMESH::long_array_var anIDs = aGrp->GetIDs();
6693       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6694     }
6695   }
6696 }
6697
6698 //================================================================================
6699 /*!
6700   \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6701   This method provided for convenience works as DoubleNodes() described above.
6702   \param theElems - list of groups of elements (edges or faces) to be replicated
6703   \param theNodesNot - list of groups of nodes not to replicated
6704   \param theAffectedElems - group of elements to which the replicated nodes
6705   should be associated to.
6706   \return TRUE if operation has been completed successfully, FALSE otherwise
6707   \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6708 */
6709 //================================================================================
6710
6711 CORBA::Boolean
6712 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6713                                          const SMESH::ListOfGroups& theNodesNot,
6714                                          const SMESH::ListOfGroups& theAffectedElems)
6715   throw (SALOME::SALOME_Exception)
6716 {
6717   SMESH_TRY;
6718   initData();
6719
6720
6721   SMESHDS_Mesh* aMeshDS = getMeshDS();
6722   TIDSortedElemSet anElems, aNodes, anAffected;
6723   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6724   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6725   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6726
6727   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6728
6729   // Update Python script
6730   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6731                 << &theNodesNot << ", " << &theAffectedElems << " )";
6732
6733   declareMeshModified( /*isReComputeSafe=*/false );
6734   return aResult;
6735
6736   SMESH_CATCH( SMESH::throwCorbaException );
6737   return 0;
6738 }
6739
6740 //================================================================================
6741 /*!
6742  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6743  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6744   \param theElems - list of groups of elements (edges or faces) to be replicated
6745   \param theNodesNot - list of groups of nodes not to replicated
6746   \param theAffectedElems - group of elements to which the replicated nodes
6747   should be associated to.
6748  * \return a new group with newly created elements
6749  * \sa DoubleNodeElemGroups()
6750  */
6751 //================================================================================
6752
6753 SMESH::SMESH_Group_ptr
6754 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6755                                             const SMESH::ListOfGroups& theNodesNot,
6756                                             const SMESH::ListOfGroups& theAffectedElems)
6757   throw (SALOME::SALOME_Exception)
6758 {
6759   TPythonDump pyDump;
6760   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6761                                                                 theNodesNot,
6762                                                                 theAffectedElems,
6763                                                                 true, false );
6764   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6765   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6766
6767   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6768          << theElems         << ", "
6769          << theNodesNot      << ", "
6770          << theAffectedElems << " )";
6771
6772   return elemGroup._retn();
6773 }
6774
6775 //================================================================================
6776 /*!
6777  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6778  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6779   \param theElems - list of groups of elements (edges or faces) to be replicated
6780   \param theNodesNot - list of groups of nodes not to replicated
6781   \param theAffectedElems - group of elements to which the replicated nodes
6782   should be associated to.
6783  * \return a new group with newly created elements
6784  * \sa DoubleNodeElemGroups()
6785  */
6786 //================================================================================
6787
6788 SMESH::ListOfGroups*
6789 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6790                                              const SMESH::ListOfGroups& theNodesNot,
6791                                              const SMESH::ListOfGroups& theAffectedElems,
6792                                              CORBA::Boolean             theElemGroupNeeded,
6793                                              CORBA::Boolean             theNodeGroupNeeded)
6794   throw (SALOME::SALOME_Exception)
6795 {
6796   SMESH_TRY;
6797   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6798   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6799   aTwoGroups->length( 2 );
6800   
6801   initData();
6802
6803
6804   SMESHDS_Mesh* aMeshDS = getMeshDS();
6805   TIDSortedElemSet anElems, aNodes, anAffected;
6806   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6807   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6808   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6809
6810   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6811
6812   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6813
6814   TPythonDump pyDump;
6815   if ( aResult )
6816   {
6817     // Create group with newly created elements
6818     CORBA::String_var elemGroupName = theElems[0]->GetName();
6819     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6820     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6821     {
6822       SMESH::long_array_var anIds = GetLastCreatedElems();
6823       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6824       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6825       aNewElemGroup->Add(anIds);
6826     }
6827     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6828     {
6829       SMESH::long_array_var anIds = GetLastCreatedNodes();
6830       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6831       aNewNodeGroup->Add(anIds);
6832     }
6833   }
6834
6835   // Update Python script
6836
6837   pyDump << "[ ";
6838   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6839   else                            pyDump << aNewElemGroup << ", ";
6840   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6841   else                            pyDump << aNewNodeGroup << " ] = ";
6842
6843   pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6844          << &theNodesNot       << ", "
6845          << &theAffectedElems  << ", "
6846          << theElemGroupNeeded << ", "
6847          << theNodeGroupNeeded << " )";
6848
6849   aTwoGroups[0] = aNewElemGroup._retn();
6850   aTwoGroups[1] = aNewNodeGroup._retn();
6851   return aTwoGroups._retn();
6852
6853   SMESH_CATCH( SMESH::throwCorbaException );
6854   return 0;
6855 }
6856
6857 //================================================================================
6858 /*!
6859   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6860   This method provided for convenience works as DoubleNodes() described above.
6861   \param theElems - list of groups of elements (edges or faces) to be replicated
6862   \param theNodesNot - list of groups of nodes not to replicated
6863   \param theShape - shape to detect affected elements (element which geometric center
6864   located on or inside shape).
6865   The replicated nodes should be associated to affected elements.
6866   \return TRUE if operation has been completed successfully, FALSE otherwise
6867   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6868 */
6869 //================================================================================
6870
6871 CORBA::Boolean
6872 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6873                                                  const SMESH::ListOfGroups& theNodesNot,
6874                                                  GEOM::GEOM_Object_ptr      theShape )
6875   throw (SALOME::SALOME_Exception)
6876 {
6877   SMESH_TRY;
6878   initData();
6879
6880
6881   SMESHDS_Mesh* aMeshDS = getMeshDS();
6882   TIDSortedElemSet anElems, aNodes;
6883   listOfGroupToSet(theElems, aMeshDS, anElems,false );
6884   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6885
6886   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6887   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6888
6889   // Update Python script
6890   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6891                 << &theNodesNot << ", " << theShape << " )";
6892
6893   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6894   return aResult;
6895
6896   SMESH_CATCH( SMESH::throwCorbaException );
6897   return 0;
6898 }
6899
6900 //================================================================================
6901 /*!
6902   \brief Identify the elements that will be affected by node duplication (actual
6903          duplication is not performed.
6904   This method is the first step of DoubleNodeElemGroupsInRegion.
6905   \param theElems - list of groups of elements (edges or faces) to be replicated
6906   \param theNodesNot - list of groups of nodes not to replicated
6907   \param theShape - shape to detect affected elements (element which geometric center
6908          located on or inside shape).
6909          The replicated nodes should be associated to affected elements.
6910   \return groups of affected elements
6911   \sa DoubleNodeElemGroupsInRegion()
6912 */
6913 //================================================================================
6914 SMESH::ListOfGroups*
6915 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6916                                                 const SMESH::ListOfGroups& theNodesNot,
6917                                                 GEOM::GEOM_Object_ptr      theShape )
6918   throw (SALOME::SALOME_Exception)
6919 {
6920   SMESH_TRY;
6921   MESSAGE("AffectedElemGroupsInRegion");
6922   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6923   bool isEdgeGroup = false;
6924   bool isFaceGroup = false;
6925   bool isVolumeGroup = false;
6926   SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6927   SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6928   SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6929
6930   initData();
6931
6932   ::SMESH_MeshEditor aMeshEditor(myMesh);
6933
6934   SMESHDS_Mesh* aMeshDS = getMeshDS();
6935   TIDSortedElemSet anElems, aNodes;
6936   listOfGroupToSet(theElems, aMeshDS, anElems, false);
6937   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6938
6939   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6940   TIDSortedElemSet anAffected;
6941   bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6942
6943
6944   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6945
6946   TPythonDump pyDump;
6947   if (aResult)
6948   {
6949     int lg = anAffected.size();
6950     MESSAGE("lg="<< lg);
6951     SMESH::long_array_var volumeIds = new SMESH::long_array;
6952     volumeIds->length(lg);
6953     SMESH::long_array_var faceIds = new SMESH::long_array;
6954     faceIds->length(lg);
6955     SMESH::long_array_var edgeIds = new SMESH::long_array;
6956     edgeIds->length(lg);
6957     int ivol = 0;
6958     int iface = 0;
6959     int iedge = 0;
6960
6961     TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6962     for (; eIt != anAffected.end(); ++eIt)
6963     {
6964       const SMDS_MeshElement* anElem = *eIt;
6965       if (!anElem)
6966         continue;
6967       int elemId = anElem->GetID();
6968       if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6969         volumeIds[ivol++] = elemId;
6970       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6971         faceIds[iface++] = elemId;
6972       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6973         edgeIds[iedge++] = elemId;
6974     }
6975     volumeIds->length(ivol);
6976     faceIds->length(iface);
6977     edgeIds->length(iedge);
6978
6979     aNewVolumeGroup->Add(volumeIds);
6980     aNewFaceGroup->Add(faceIds);
6981     aNewEdgeGroup->Add(edgeIds);
6982     isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6983     isFaceGroup = (aNewFaceGroup->Size() > 0);
6984     isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6985   }
6986
6987   int nbGroups = 0;
6988   if (isEdgeGroup)   nbGroups++;
6989   if (isFaceGroup)   nbGroups++;
6990   if (isVolumeGroup) nbGroups++;
6991   aListOfGroups->length(nbGroups);
6992
6993   int i = 0;
6994   if (isEdgeGroup)   aListOfGroups[i++] = aNewEdgeGroup._retn();
6995   if (isFaceGroup)   aListOfGroups[i++] = aNewFaceGroup._retn();
6996   if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6997
6998   // Update Python script
6999
7000   pyDump << "[ ";
7001   if (isEdgeGroup)   pyDump << aNewEdgeGroup << ", ";
7002   if (isFaceGroup)   pyDump << aNewFaceGroup << ", ";
7003   if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
7004   pyDump << "] = ";
7005   pyDump << this << ".AffectedElemGroupsInRegion( "
7006          << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
7007
7008   return aListOfGroups._retn();
7009
7010   SMESH_CATCH( SMESH::throwCorbaException );
7011   return 0;
7012 }
7013
7014 //================================================================================
7015 /*!
7016   \brief Generated skin mesh (containing 2D cells) from 3D mesh
7017    The created 2D mesh elements based on nodes of free faces of boundary volumes
7018   \return TRUE if operation has been completed successfully, FALSE otherwise
7019 */
7020 //================================================================================
7021
7022 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
7023   throw (SALOME::SALOME_Exception)
7024 {
7025   SMESH_TRY;
7026   initData();
7027
7028   bool aResult = getEditor().Make2DMeshFrom3D();
7029
7030   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
7031
7032   declareMeshModified( /*isReComputeSafe=*/ !aResult );
7033   return aResult;
7034
7035   SMESH_CATCH( SMESH::throwCorbaException );
7036   return false;
7037 }
7038
7039 //================================================================================
7040 /*!
7041  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
7042  * The list of groups must contain at least two groups. The groups have to be disjoint:
7043  * no common element into two different groups.
7044  * The nodes of the internal faces at the boundaries of the groups are doubled.
7045  * Optionally, the internal faces are replaced by flat elements.
7046  * Triangles are transformed into prisms, and quadrangles into hexahedrons.
7047  * The flat elements are stored in groups of volumes.
7048  * These groups are named according to the position of the group in the list:
7049  * the group j_n_p is the group of the flat elements that are built between the group #n and the group #p in the list.
7050  * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created.
7051  * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
7052  * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
7053  * \param theDomains - list of groups of volumes
7054  * \param createJointElems - if TRUE, create the elements
7055  * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
7056  *        the boundary between \a theDomains and the rest mesh
7057  * \return TRUE if operation has been completed successfully, FALSE otherwise
7058  */
7059 //================================================================================
7060
7061 CORBA::Boolean
7062 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
7063                                                   CORBA::Boolean             createJointElems,
7064                                                   CORBA::Boolean             onAllBoundaries )
7065   throw (SALOME::SALOME_Exception)
7066 {
7067   bool isOK = false;
7068
7069   SMESH_TRY;
7070   initData();
7071
7072   SMESHDS_Mesh* aMeshDS = getMeshDS();
7073
7074   // MESSAGE("theDomains.length = "<<theDomains.length());
7075   if ( theDomains.length() <= 1 && !onAllBoundaries )
7076     THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
7077
7078   vector<TIDSortedElemSet> domains;
7079   domains.resize( theDomains.length() );
7080
7081   for ( int i = 0, n = theDomains.length(); i < n; i++ )
7082   {
7083     SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
7084     if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
7085     {
7086 //      if ( aGrp->GetType() != SMESH::VOLUME )
7087 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
7088       SMESH::long_array_var anIDs = aGrp->GetIDs();
7089       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
7090     }
7091   }
7092
7093   isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
7094   // TODO publish the groups of flat elements in study
7095
7096   declareMeshModified( /*isReComputeSafe=*/ !isOK );
7097
7098   // Update Python script
7099   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
7100                 << ", " << createJointElems << ", " << onAllBoundaries << " )";
7101
7102   SMESH_CATCH( SMESH::throwCorbaException );
7103
7104   myMesh_i->CreateGroupServants(); // publish created groups if any
7105
7106   return isOK;
7107 }
7108
7109 //================================================================================
7110 /*!
7111  * \brief Double nodes on some external faces and create flat elements.
7112  * Flat elements are mainly used by some types of mechanic calculations.
7113  *
7114  * Each group of the list must be constituted of faces.
7115  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
7116  * @param theGroupsOfFaces - list of groups of faces
7117  * @return TRUE if operation has been completed successfully, FALSE otherwise
7118  */
7119 //================================================================================
7120
7121 CORBA::Boolean
7122 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
7123   throw (SALOME::SALOME_Exception)
7124 {
7125   SMESH_TRY;
7126   initData();
7127
7128   SMESHDS_Mesh* aMeshDS = getMeshDS();
7129
7130   vector<TIDSortedElemSet> faceGroups;
7131   faceGroups.clear();
7132
7133   for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
7134   {
7135     SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
7136     if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
7137     {
7138       TIDSortedElemSet faceGroup;
7139       faceGroup.clear();
7140       faceGroups.push_back(faceGroup);
7141       SMESH::long_array_var anIDs = aGrp->GetIDs();
7142       arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
7143     }
7144   }
7145
7146   bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
7147   // TODO publish the groups of flat elements in study
7148
7149   declareMeshModified( /*isReComputeSafe=*/ !aResult );
7150
7151   // Update Python script
7152   TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
7153   return aResult;
7154
7155   SMESH_CATCH( SMESH::throwCorbaException );
7156   return false;
7157 }
7158
7159 //================================================================================
7160 /*!
7161  *  \brief Identify all the elements around a geom shape, get the faces delimiting
7162  *         the hole.
7163  *
7164  *  Build groups of volume to remove, groups of faces to replace on the skin of the
7165  *  object, groups of faces to remove inside the object, (idem edges).
7166  *  Build ordered list of nodes at the border of each group of faces to replace
7167  *  (to be used to build a geom subshape).
7168  */
7169 //================================================================================
7170
7171 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double                  radius,
7172                                         GEOM::GEOM_Object_ptr          theShape,
7173                                         const char*                    groupName,
7174                                         const SMESH::double_array&     theNodesCoords,
7175                                         SMESH::array_of_long_array_out GroupsOfNodes)
7176   throw (SALOME::SALOME_Exception)
7177 {
7178   SMESH_TRY;
7179
7180   initData();
7181   std::vector<std::vector<int> > aListOfListOfNodes;
7182   ::SMESH_MeshEditor aMeshEditor( myMesh );
7183
7184   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7185   if ( !theNodeSearcher )
7186     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7187
7188   vector<double> nodesCoords;
7189   for (int i = 0; i < theNodesCoords.length(); i++)
7190   {
7191     nodesCoords.push_back( theNodesCoords[i] );
7192   }
7193
7194   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7195   aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7196                              nodesCoords, aListOfListOfNodes);
7197
7198   GroupsOfNodes = new SMESH::array_of_long_array;
7199   GroupsOfNodes->length( aListOfListOfNodes.size() );
7200   std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7201   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7202   {
7203     vector<int>& aListOfNodes = *llIt;
7204     vector<int>::iterator lIt = aListOfNodes.begin();;
7205     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7206     aGroup.length( aListOfNodes.size() );
7207     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7208       aGroup[ j ] = (*lIt);
7209   }
7210   TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7211                 << radius << ", "
7212                 << theShape
7213                 << ", '" << groupName << "', "
7214                 << theNodesCoords << " )";
7215
7216   SMESH_CATCH( SMESH::throwCorbaException );
7217 }
7218
7219 // issue 20749 ===================================================================
7220 /*!
7221  * \brief Creates missing boundary elements
7222  *  \param elements - elements whose boundary is to be checked
7223  *  \param dimension - defines type of boundary elements to create
7224  *  \param groupName - a name of group to store created boundary elements in,
7225  *                     "" means not to create the group
7226  *  \param meshName - a name of new mesh to store created boundary elements in,
7227  *                     "" means not to create the new mesh
7228  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
7229  *  \param toCopyExistingBondary - if true, not only new but also pre-existing
7230  *                                boundary elements will be copied into the new mesh
7231  *  \param group - returns the create group, if any
7232  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7233  */
7234 // ================================================================================
7235
7236 SMESH::SMESH_Mesh_ptr
7237 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7238                                      SMESH::Bnd_Dimension      dim,
7239                                      const char*               groupName,
7240                                      const char*               meshName,
7241                                      CORBA::Boolean            toCopyElements,
7242                                      CORBA::Boolean            toCopyExistingBondary,
7243                                      SMESH::SMESH_Group_out    group)
7244   throw (SALOME::SALOME_Exception)
7245 {
7246   SMESH_TRY;
7247   initData();
7248
7249   if ( dim > SMESH::BND_1DFROM2D )
7250     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7251
7252   SMESHDS_Mesh* aMeshDS = getMeshDS();
7253
7254   SMESH::SMESH_Mesh_var mesh_var;
7255   SMESH::SMESH_Group_var group_var;
7256
7257   TPythonDump pyDump;
7258
7259   TIDSortedElemSet elements;
7260   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7261   prepareIdSource( idSource );
7262   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7263   {
7264     // mesh to fill in
7265     mesh_var =
7266       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7267     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7268     // other mesh
7269     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7270
7271     // group of new boundary elements
7272     SMESH_Group* smesh_group = 0;
7273     if ( strlen(groupName) )
7274     {
7275       group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7276       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7277         smesh_group = group_i->GetSmeshGroup();
7278     }
7279
7280     // do it
7281     getEditor().MakeBoundaryMesh( elements,
7282                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
7283                                   smesh_group,
7284                                   smesh_mesh,
7285                                   toCopyElements,
7286                                   toCopyExistingBondary);
7287
7288     if ( smesh_mesh )
7289       smesh_mesh->GetMeshDS()->Modified();
7290   }
7291
7292   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7293
7294   // result of MakeBoundaryMesh() is a tuple (mesh, group)
7295   if ( mesh_var->_is_nil() )
7296     pyDump << myMesh_i->_this() << ", ";
7297   else
7298     pyDump << mesh_var << ", ";
7299   if ( group_var->_is_nil() )
7300     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7301   else
7302     pyDump << group_var << " = ";
7303   pyDump << this << ".MakeBoundaryMesh( "
7304          << idSource << ", "
7305          << "SMESH." << dimName[int(dim)] << ", "
7306          << "'" << groupName << "', "
7307          << "'" << meshName<< "', "
7308          << toCopyElements << ", "
7309          << toCopyExistingBondary << ")";
7310
7311   group = group_var._retn();
7312   return mesh_var._retn();
7313
7314   SMESH_CATCH( SMESH::throwCorbaException );
7315   return SMESH::SMESH_Mesh::_nil();
7316 }
7317
7318 //================================================================================
7319 /*!
7320  * \brief Creates missing boundary elements
7321  *  \param dimension - defines type of boundary elements to create
7322  *  \param groupName - a name of group to store all boundary elements in,
7323  *    "" means not to create the group
7324  *  \param meshName - a name of a new mesh, which is a copy of the initial 
7325  *    mesh + created boundary elements; "" means not to create the new mesh
7326  *  \param toCopyAll - if true, the whole initial mesh will be copied into
7327  *    the new mesh else only boundary elements will be copied into the new mesh
7328  *  \param groups - optional groups of elements to make boundary around
7329  *  \param mesh - returns the mesh where elements were added to
7330  *  \param group - returns the created group, if any
7331  *  \retval long - number of added boundary elements
7332  */
7333 //================================================================================
7334
7335 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7336                                                      const char* groupName,
7337                                                      const char* meshName,
7338                                                      CORBA::Boolean toCopyAll,
7339                                                      const SMESH::ListOfIDSources& groups,
7340                                                      SMESH::SMESH_Mesh_out mesh,
7341                                                      SMESH::SMESH_Group_out group)
7342   throw (SALOME::SALOME_Exception)
7343 {
7344   SMESH_TRY;
7345   initData();
7346
7347   if ( dim > SMESH::BND_1DFROM2D )
7348     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7349
7350   // separate groups belonging to this and other mesh
7351   SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7352   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7353   groupsOfThisMesh->length( groups.length() );
7354   groupsOfOtherMesh->length( groups.length() );
7355   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7356   for ( int i = 0; i < groups.length(); ++i )
7357   {
7358     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7359     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7360       groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7361     else
7362       groupsOfThisMesh[ nbGroups++ ] = groups[i];
7363     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7364       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
7365   }
7366   groupsOfThisMesh->length( nbGroups );
7367   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7368
7369   int nbAdded = 0;
7370   TPythonDump pyDump;
7371
7372   if ( nbGroupsOfOtherMesh > 0 )
7373   {
7374     // process groups belonging to another mesh
7375     SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
7376     SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7377     nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7378                                              groupsOfOtherMesh, mesh, group );
7379   }
7380
7381   SMESH::SMESH_Mesh_var mesh_var;
7382   SMESH::SMESH_Group_var group_var;
7383
7384   // get mesh to fill
7385   mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7386   const bool toCopyMesh = ( strlen( meshName ) > 0 );
7387   if ( toCopyMesh )
7388   {
7389     if ( toCopyAll )
7390       mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7391                                                       meshName,
7392                                                       /*toCopyGroups=*/false,
7393                                                       /*toKeepIDs=*/true);
7394     else
7395       mesh_var = makeMesh(meshName);
7396   }
7397   SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7398   SMESH_Mesh*  tgtMesh = &mesh_i->GetImpl();
7399
7400   // source mesh
7401   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7402   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7403
7404   // group of boundary elements
7405   SMESH_Group* smesh_group = 0;
7406   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7407   if ( strlen(groupName) )
7408   {
7409     SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7410     group_var = mesh_i->CreateGroup( groupType, groupName );
7411     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7412       smesh_group = group_i->GetSmeshGroup();
7413   }
7414
7415   TIDSortedElemSet elements;
7416
7417   if ( groups.length() > 0 )
7418   {
7419     for ( int i = 0; i < nbGroups; ++i )
7420     {
7421       elements.clear();
7422       if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7423       {
7424         SMESH::Bnd_Dimension bdim = 
7425           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7426         nbAdded += getEditor().MakeBoundaryMesh( elements,
7427                                                  ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7428                                                  smesh_group,
7429                                                  tgtMesh,
7430                                                  /*toCopyElements=*/false,
7431                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7432                                                  /*toAddExistingBondary=*/true,
7433                                                  /*aroundElements=*/true);
7434       }
7435     }
7436   }
7437   else
7438   {
7439     nbAdded += getEditor().MakeBoundaryMesh( elements,
7440                                              ::SMESH_MeshEditor::Bnd_Dimension(dim),
7441                                              smesh_group,
7442                                              tgtMesh,
7443                                              /*toCopyElements=*/false,
7444                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7445                                              /*toAddExistingBondary=*/true);
7446   }
7447   tgtMesh->GetMeshDS()->Modified();
7448
7449   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7450
7451   // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7452   pyDump << "nbAdded, ";
7453   if ( mesh_var->_is_nil() )
7454     pyDump << myMesh_i->_this() << ", ";
7455   else
7456     pyDump << mesh_var << ", ";
7457   if ( group_var->_is_nil() )
7458     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7459   else
7460     pyDump << group_var << " = ";
7461   pyDump << this << ".MakeBoundaryElements( "
7462          << "SMESH." << dimName[int(dim)] << ", "
7463          << "'" << groupName << "', "
7464          << "'" << meshName<< "', "
7465          << toCopyAll << ", "
7466          << groups << ")";
7467
7468   mesh  = mesh_var._retn();
7469   group = group_var._retn();
7470   return nbAdded;
7471
7472   SMESH_CATCH( SMESH::throwCorbaException );
7473   return 0;
7474 }