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