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