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