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