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