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