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