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