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