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