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