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