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