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