Salome HOME
f0f7c923bf1bcb50ab0768486b490a4d36f24d6d
[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                 << MakeGroups << ", "
2631                 << ElemType << " )";
2632   }
2633   return aGroups;
2634 }
2635
2636
2637 //================================================================================
2638 /*!
2639  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2640  * of given angles along path steps
2641  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
2642  *                which proceeds the extrusion
2643  * \param PathShape is shape(edge); as the mesh can be complex, the edge 
2644  *                 is used to define the sub-mesh for the path
2645  */
2646 //================================================================================
2647
2648 SMESH::double_array*
2649 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
2650                                           GEOM::GEOM_Object_ptr       thePathShape,
2651                                           const SMESH::double_array & theAngles)
2652 {
2653   SMESH::double_array_var aResult = new SMESH::double_array();
2654   int nbAngles = theAngles.length();
2655   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2656   {
2657     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2658     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2659     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2660     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2661       return aResult._retn();
2662     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2663     if ( nbSteps == nbAngles )
2664     {
2665       aResult.inout() = theAngles;
2666     }
2667     else
2668     {
2669       aResult->length( nbSteps );
2670       double rAn2St = double( nbAngles ) / double( nbSteps );
2671       double angPrev = 0, angle;
2672       for ( int iSt = 0; iSt < nbSteps; ++iSt )
2673       {
2674         double angCur = rAn2St * ( iSt+1 );
2675         double angCurFloor  = floor( angCur );
2676         double angPrevFloor = floor( angPrev );
2677         if ( angPrevFloor == angCurFloor )
2678           angle = rAn2St * theAngles[ int( angCurFloor ) ];
2679         else
2680         {
2681           int iP = int( angPrevFloor );
2682           double angPrevCeil = ceil(angPrev);
2683           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
2684
2685           int iC = int( angCurFloor );
2686           if ( iC < nbAngles )
2687             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
2688
2689           iP = int( angPrevCeil );
2690           while ( iC-- > iP )
2691             angle += theAngles[ iC ];
2692         }
2693         aResult[ iSt ] = angle;
2694         angPrev = angCur;
2695       }
2696     }
2697   }
2698   // Update Python script
2699   TPythonDump() << "rotAngles = " << theAngles;
2700   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
2701                 << thePathMesh  << ", "
2702                 << thePathShape << ", "
2703                 << "rotAngles )";
2704
2705   return aResult._retn();
2706 }
2707
2708
2709 //=======================================================================
2710 //function : mirror
2711 //purpose  : 
2712 //=======================================================================
2713
2714 SMESH::ListOfGroups*
2715 SMESH_MeshEditor_i::mirror(const SMESH::long_array &           theIDsOfElements,
2716                            const SMESH::AxisStruct &           theAxis,
2717                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2718                            CORBA::Boolean                      theCopy,
2719                            const bool                          theMakeGroups,
2720                            ::SMESH_Mesh*                       theTargetMesh)
2721 {
2722   initData();
2723
2724   TIDSortedElemSet elements;
2725   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2726
2727   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
2728   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
2729
2730   gp_Trsf aTrsf;
2731   switch ( theMirrorType ) {
2732   case  SMESH::SMESH_MeshEditor::POINT:
2733     aTrsf.SetMirror( P );
2734     break;
2735   case  SMESH::SMESH_MeshEditor::AXIS:
2736     aTrsf.SetMirror( gp_Ax1( P, V ));
2737     break;
2738   default:
2739     aTrsf.SetMirror( gp_Ax2( P, V ));
2740   }
2741
2742   ::SMESH_MeshEditor anEditor( myMesh );
2743   ::SMESH_MeshEditor::PGroupIDs groupIds =
2744       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2745
2746   if(theCopy) {
2747     storeResult(anEditor);
2748   }
2749   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2750 }
2751
2752 //=======================================================================
2753 //function : Mirror
2754 //purpose  :
2755 //=======================================================================
2756
2757 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
2758                                 const SMESH::AxisStruct &           theAxis,
2759                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2760                                 CORBA::Boolean                      theCopy)
2761 {
2762   if ( !myPreviewMode ) {
2763     TPythonDump() << this << ".Mirror( "
2764                   << theIDsOfElements << ", "
2765                   << theAxis          << ", "
2766                   << mirrorTypeName(theMirrorType) << ", "
2767                   << theCopy          << " )";
2768   }
2769   mirror(theIDsOfElements, theAxis, theMirrorType, theCopy, false);
2770 }
2771
2772
2773 //=======================================================================
2774 //function : MirrorObject
2775 //purpose  :
2776 //=======================================================================
2777
2778 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
2779                                       const SMESH::AxisStruct &           theAxis,
2780                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2781                                       CORBA::Boolean                      theCopy)
2782 {
2783   if ( !myPreviewMode ) {
2784     TPythonDump() << this << ".MirrorObject( "
2785                   << theObject << ", "
2786                   << theAxis   << ", "
2787                   << mirrorTypeName(theMirrorType) << ", "
2788                   << theCopy   << " )";
2789   }
2790   SMESH::long_array_var anElementsId = theObject->GetIDs();
2791   mirror(anElementsId, theAxis, theMirrorType, theCopy, false);
2792 }
2793
2794 //=======================================================================
2795 //function : MirrorMakeGroups
2796 //purpose  : 
2797 //=======================================================================
2798
2799 SMESH::ListOfGroups*
2800 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
2801                                      const SMESH::AxisStruct&            theMirror,
2802                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2803 {
2804   SMESH::ListOfGroups * aGroups = mirror(theIDsOfElements, theMirror, theMirrorType, true, true);
2805   if ( !myPreviewMode ) {
2806     TPythonDump aPythonDump;
2807     DumpGroupsList(aPythonDump,aGroups);
2808     aPythonDump << this << ".MirrorMakeGroups( "
2809                 << theIDsOfElements << ", "
2810                 << theMirror << ", "
2811                 << mirrorTypeName(theMirrorType) << " )";
2812   }
2813   return aGroups;
2814 }
2815
2816 //=======================================================================
2817 //function : MirrorObjectMakeGroups
2818 //purpose  : 
2819 //=======================================================================
2820
2821 SMESH::ListOfGroups*
2822 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
2823                                            const SMESH::AxisStruct&            theMirror,
2824                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
2825 {
2826   SMESH::long_array_var anElementsId = theObject->GetIDs();
2827   SMESH::ListOfGroups * aGroups = mirror(anElementsId, theMirror, theMirrorType, true, true);
2828   if ( !myPreviewMode ) {
2829     TPythonDump aPythonDump;
2830     DumpGroupsList(aPythonDump,aGroups);
2831     aPythonDump << this << ".MirrorObjectMakeGroups( "
2832                 << theObject << ", "
2833                 << theMirror << ", "
2834                 << mirrorTypeName(theMirrorType) << " )";
2835   }
2836   return aGroups;
2837 }
2838
2839 //=======================================================================
2840 //function : MirrorMakeMesh
2841 //purpose  : 
2842 //=======================================================================
2843
2844 SMESH::SMESH_Mesh_ptr
2845 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
2846                                    const SMESH::AxisStruct&            theMirror,
2847                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2848                                    CORBA::Boolean                      theCopyGroups,
2849                                    const char*                         theMeshName)
2850 {
2851   SMESH_Mesh_i* mesh_i;
2852   SMESH::SMESH_Mesh_var mesh;
2853   { // open new scope to dump "MakeMesh" command
2854     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2855
2856     TPythonDump pydump; // to prevent dump at mesh creation
2857
2858     mesh = makeMesh( theMeshName );
2859     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2860     if (mesh_i) {
2861       mirror(theIDsOfElements, theMirror, theMirrorType,
2862              false, theCopyGroups, & mesh_i->GetImpl());
2863       mesh_i->CreateGroupServants();
2864     }
2865
2866     if ( !myPreviewMode ) {
2867       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
2868              << theIDsOfElements << ", "
2869              << theMirror   << ", "
2870              << mirrorTypeName(theMirrorType) << ", "
2871              << theCopyGroups << ", '"
2872              << theMeshName << "' )";
2873     }
2874   }
2875
2876   //dump "GetGroups"
2877   if(!myPreviewMode && mesh_i)
2878     mesh_i->GetGroups();
2879
2880   return mesh._retn();
2881 }
2882
2883 //=======================================================================
2884 //function : MirrorObjectMakeMesh
2885 //purpose  : 
2886 //=======================================================================
2887
2888 SMESH::SMESH_Mesh_ptr
2889 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
2890                                          const SMESH::AxisStruct&            theMirror,
2891                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2892                                          CORBA::Boolean                      theCopyGroups,
2893                                          const char*                         theMeshName)
2894 {
2895   SMESH_Mesh_i* mesh_i;
2896   SMESH::SMESH_Mesh_var mesh;
2897   { // open new scope to dump "MakeMesh" command
2898     // and then "GetGroups" using SMESH_Mesh::GetGroups()
2899
2900     TPythonDump pydump; // to prevent dump at mesh creation
2901
2902     mesh = makeMesh( theMeshName );
2903     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
2904     if ( mesh_i ) {
2905       SMESH::long_array_var anElementsId = theObject->GetIDs();
2906       mirror(anElementsId, theMirror, theMirrorType,
2907              false, theCopyGroups, & mesh_i->GetImpl());
2908       mesh_i->CreateGroupServants();
2909     }
2910
2911     if ( !myPreviewMode ) {
2912       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
2913              << theObject << ", "
2914              << theMirror   << ", "
2915              << mirrorTypeName(theMirrorType) << ", "
2916              << theCopyGroups << ", '"
2917              << theMeshName << "' )";
2918     }
2919   } 
2920
2921   //dump "GetGroups"
2922   if(!myPreviewMode && mesh_i)
2923     mesh_i->GetGroups();
2924
2925   return mesh._retn();
2926 }
2927
2928 //=======================================================================
2929 //function : translate
2930 //purpose  : 
2931 //=======================================================================
2932
2933 SMESH::ListOfGroups*
2934 SMESH_MeshEditor_i::translate(const SMESH::long_array & theIDsOfElements,
2935                               const SMESH::DirStruct &  theVector,
2936                               CORBA::Boolean            theCopy,
2937                               const bool                theMakeGroups,
2938                               ::SMESH_Mesh*             theTargetMesh)
2939 {
2940   initData();
2941
2942   TIDSortedElemSet elements;
2943   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2944
2945   gp_Trsf aTrsf;
2946   const SMESH::PointStruct * P = &theVector.PS;
2947   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
2948
2949   ::SMESH_MeshEditor anEditor( myMesh );
2950   ::SMESH_MeshEditor::PGroupIDs groupIds =
2951       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2952
2953   if(theCopy)
2954     storeResult(anEditor);
2955
2956   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2957 }
2958
2959 //=======================================================================
2960 //function : Translate
2961 //purpose  :
2962 //=======================================================================
2963
2964 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
2965                                    const SMESH::DirStruct &  theVector,
2966                                    CORBA::Boolean            theCopy)
2967 {
2968   if ( !myPreviewMode ) {
2969     TPythonDump() << this << ".Translate( "
2970                   << theIDsOfElements << ", "
2971                   << theVector << ", "
2972                   << theCopy << " )";
2973   }
2974   translate(theIDsOfElements,
2975             theVector,
2976             theCopy,
2977             false);
2978 }
2979
2980 //=======================================================================
2981 //function : TranslateObject
2982 //purpose  :
2983 //=======================================================================
2984
2985 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
2986                                          const SMESH::DirStruct &  theVector,
2987                                          CORBA::Boolean            theCopy)
2988 {
2989   if ( !myPreviewMode ) {
2990     TPythonDump() << this << ".TranslateObject( "
2991                   << theObject << ", "
2992                   << theVector << ", "
2993                   << theCopy << " )";
2994   }
2995   SMESH::long_array_var anElementsId = theObject->GetIDs();
2996   translate(anElementsId,
2997             theVector,
2998             theCopy,
2999             false);
3000 }
3001
3002 //=======================================================================
3003 //function : TranslateMakeGroups
3004 //purpose  : 
3005 //=======================================================================
3006
3007 SMESH::ListOfGroups*
3008 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3009                                         const SMESH::DirStruct&  theVector)
3010 {
3011   SMESH::ListOfGroups * aGroups = translate(theIDsOfElements,theVector,true,true);
3012   if ( !myPreviewMode ) {
3013     TPythonDump aPythonDump;
3014     DumpGroupsList(aPythonDump,aGroups);
3015     aPythonDump << this << ".TranslateMakeGroups( "
3016                 << theIDsOfElements << ", "
3017                 << theVector << " )";
3018   }
3019   return aGroups;
3020 }
3021
3022 //=======================================================================
3023 //function : TranslateObjectMakeGroups
3024 //purpose  : 
3025 //=======================================================================
3026
3027 SMESH::ListOfGroups*
3028 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3029                                               const SMESH::DirStruct&   theVector)
3030 {
3031   SMESH::long_array_var anElementsId = theObject->GetIDs();
3032   SMESH::ListOfGroups * aGroups = translate(anElementsId, theVector, true, true);
3033
3034   if ( !myPreviewMode ) {
3035
3036     TPythonDump aPythonDump;
3037     DumpGroupsList(aPythonDump,aGroups);
3038     aPythonDump << this << ".TranslateObjectMakeGroups( "
3039                 << theObject << ", "
3040                 << theVector << " )";
3041   }
3042   return aGroups;
3043 }
3044
3045 //=======================================================================
3046 //function : TranslateMakeMesh
3047 //purpose  : 
3048 //=======================================================================
3049
3050 SMESH::SMESH_Mesh_ptr
3051 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3052                                       const SMESH::DirStruct&  theVector,
3053                                       CORBA::Boolean           theCopyGroups,
3054                                       const char*              theMeshName)
3055 {
3056   SMESH_Mesh_i* mesh_i;
3057   SMESH::SMESH_Mesh_var mesh;
3058
3059   { // open new scope to dump "MakeMesh" command
3060     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3061
3062     TPythonDump pydump; // to prevent dump at mesh creation
3063
3064     mesh = makeMesh( theMeshName );
3065     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3066
3067     if ( mesh_i ) {
3068       translate(theIDsOfElements, theVector,
3069                 false, theCopyGroups, & mesh_i->GetImpl());
3070       mesh_i->CreateGroupServants();
3071     }
3072
3073     if ( !myPreviewMode ) {
3074       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3075              << theIDsOfElements << ", "
3076              << theVector   << ", "
3077              << theCopyGroups << ", '"
3078              << theMeshName << "' )";
3079     }
3080   }
3081
3082   //dump "GetGroups"
3083   if(!myPreviewMode && mesh_i)
3084     mesh_i->GetGroups();
3085
3086   return mesh._retn();
3087 }
3088
3089 //=======================================================================
3090 //function : TranslateObjectMakeMesh
3091 //purpose  : 
3092 //=======================================================================
3093
3094 SMESH::SMESH_Mesh_ptr
3095 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3096                                             const SMESH::DirStruct&   theVector,
3097                                             CORBA::Boolean            theCopyGroups,
3098                                             const char*               theMeshName)
3099 {
3100   SMESH_Mesh_i* mesh_i;
3101   SMESH::SMESH_Mesh_var mesh;
3102   { // open new scope to dump "MakeMesh" command
3103     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3104
3105     TPythonDump pydump; // to prevent dump at mesh creation
3106     mesh = makeMesh( theMeshName );
3107     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3108
3109     if ( mesh_i ) {
3110       SMESH::long_array_var anElementsId = theObject->GetIDs();
3111       translate(anElementsId, theVector,
3112                 false, theCopyGroups, & mesh_i->GetImpl());
3113       mesh_i->CreateGroupServants();
3114     }
3115     if ( !myPreviewMode ) {
3116       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3117              << theObject << ", "
3118              << theVector   << ", "
3119              << theCopyGroups << ", '"
3120              << theMeshName << "' )";
3121     }
3122   }
3123
3124   //dump "GetGroups"
3125   if(!myPreviewMode && mesh_i)
3126     mesh_i->GetGroups();
3127
3128   return mesh._retn();
3129 }
3130
3131 //=======================================================================
3132 //function : rotate
3133 //purpose  : 
3134 //=======================================================================
3135
3136 SMESH::ListOfGroups*
3137 SMESH_MeshEditor_i::rotate(const SMESH::long_array & theIDsOfElements,
3138                            const SMESH::AxisStruct & theAxis,
3139                            CORBA::Double             theAngle,
3140                            CORBA::Boolean            theCopy,
3141                            const bool                theMakeGroups,
3142                            ::SMESH_Mesh*             theTargetMesh)
3143 {
3144   initData();
3145
3146   TIDSortedElemSet elements;
3147   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3148
3149   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3150   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3151
3152   gp_Trsf aTrsf;
3153   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3154
3155   ::SMESH_MeshEditor anEditor( myMesh );
3156   ::SMESH_MeshEditor::PGroupIDs groupIds =
3157       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3158
3159   if(theCopy) {
3160     storeResult(anEditor);
3161   }
3162   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3163 }
3164
3165 //=======================================================================
3166 //function : Rotate
3167 //purpose  :
3168 //=======================================================================
3169
3170 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3171                                 const SMESH::AxisStruct & theAxis,
3172                                 CORBA::Double             theAngle,
3173                                 CORBA::Boolean            theCopy)
3174 {
3175   if ( !myPreviewMode ) {
3176     TPythonDump() << this << ".Rotate( "
3177                   << theIDsOfElements << ", "
3178                   << theAxis << ", "
3179                   << theAngle << ", "
3180                   << theCopy << " )";
3181   }
3182   rotate(theIDsOfElements,
3183          theAxis,
3184          theAngle,
3185          theCopy,
3186          false);
3187 }
3188
3189 //=======================================================================
3190 //function : RotateObject
3191 //purpose  :
3192 //=======================================================================
3193
3194 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3195                                       const SMESH::AxisStruct & theAxis,
3196                                       CORBA::Double             theAngle,
3197                                       CORBA::Boolean            theCopy)
3198 {
3199   if ( !myPreviewMode ) {
3200     TPythonDump() << this << ".RotateObject( "
3201                   << theObject << ", "
3202                   << theAxis << ", "
3203                   << theAngle << ", "
3204                   << theCopy << " )";
3205   }
3206   SMESH::long_array_var anElementsId = theObject->GetIDs();
3207   rotate(anElementsId,
3208          theAxis,
3209          theAngle,
3210          theCopy,
3211          false);
3212 }
3213
3214 //=======================================================================
3215 //function : RotateMakeGroups
3216 //purpose  : 
3217 //=======================================================================
3218
3219 SMESH::ListOfGroups*
3220 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3221                                      const SMESH::AxisStruct& theAxis,
3222                                      CORBA::Double            theAngle)
3223 {
3224   SMESH::ListOfGroups * aGroups =  rotate(theIDsOfElements,theAxis,theAngle,true,true);
3225   if ( !myPreviewMode ) {
3226     TPythonDump aPythonDump;
3227     DumpGroupsList(aPythonDump,aGroups);
3228     aPythonDump << this << ".RotateMakeGroups( "
3229                 << theIDsOfElements << ", "
3230                 << theAxis << ", "
3231                 << theAngle << " )";
3232   }
3233   return aGroups;
3234 }
3235
3236 //=======================================================================
3237 //function : RotateObjectMakeGroups
3238 //purpose  : 
3239 //=======================================================================
3240
3241 SMESH::ListOfGroups*
3242 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3243                                            const SMESH::AxisStruct&  theAxis,
3244                                            CORBA::Double             theAngle)
3245 {
3246   SMESH::long_array_var anElementsId = theObject->GetIDs();
3247   SMESH::ListOfGroups * aGroups =  rotate(anElementsId,theAxis,theAngle,true,true);
3248
3249   if ( !myPreviewMode ) {
3250     TPythonDump aPythonDump;
3251     DumpGroupsList(aPythonDump,aGroups);
3252     aPythonDump << this << ".RotateObjectMakeGroups( "
3253                 << theObject << ", "
3254                 << theAxis << ", "
3255                 << theAngle << " )";
3256   }
3257   return aGroups;
3258 }
3259
3260 //=======================================================================
3261 //function : RotateMakeMesh
3262 //purpose  : 
3263 //=======================================================================
3264
3265 SMESH::SMESH_Mesh_ptr 
3266 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3267                                    const SMESH::AxisStruct& theAxis,
3268                                    CORBA::Double            theAngleInRadians,
3269                                    CORBA::Boolean           theCopyGroups,
3270                                    const char*              theMeshName)
3271 {
3272   SMESH::SMESH_Mesh_var mesh;
3273   SMESH_Mesh_i* mesh_i;
3274
3275   { // open new scope to dump "MakeMesh" command
3276     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3277
3278     TPythonDump pydump; // to prevent dump at mesh creation
3279
3280     mesh = makeMesh( theMeshName );
3281     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3282
3283     if ( mesh_i ) {
3284       rotate(theIDsOfElements, theAxis, theAngleInRadians,
3285              false, theCopyGroups, & mesh_i->GetImpl());
3286       mesh_i->CreateGroupServants();
3287     }
3288     if ( !myPreviewMode ) {
3289       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3290              << theIDsOfElements << ", "
3291              << theAxis << ", "
3292              << theAngleInRadians   << ", "
3293              << theCopyGroups << ", '"
3294              << theMeshName << "' )";
3295     }
3296   }
3297
3298   //dump "GetGroups"
3299   if(!myPreviewMode && mesh_i)
3300     mesh_i->GetGroups();
3301
3302   return mesh._retn();
3303 }
3304
3305 //=======================================================================
3306 //function : RotateObjectMakeMesh
3307 //purpose  : 
3308 //=======================================================================
3309
3310 SMESH::SMESH_Mesh_ptr 
3311 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3312                                          const SMESH::AxisStruct&  theAxis,
3313                                          CORBA::Double             theAngleInRadians,
3314                                          CORBA::Boolean            theCopyGroups,
3315                                          const char*               theMeshName)
3316 {
3317   SMESH::SMESH_Mesh_var mesh;
3318   SMESH_Mesh_i* mesh_i;
3319
3320   {// open new scope to dump "MakeMesh" command
3321    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3322
3323     TPythonDump pydump; // to prevent dump at mesh creation
3324     mesh = makeMesh( theMeshName );
3325     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3326
3327     if (mesh_i ) {
3328       SMESH::long_array_var anElementsId = theObject->GetIDs();
3329       rotate(anElementsId, theAxis, theAngleInRadians,
3330              false, theCopyGroups, & mesh_i->GetImpl());
3331       mesh_i->CreateGroupServants();
3332     }
3333     if ( !myPreviewMode ) {
3334       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3335              << theObject << ", "
3336              << theAxis << ", "
3337              << theAngleInRadians   << ", "
3338              << theCopyGroups << ", '"
3339              << theMeshName << "' )";
3340     }
3341   }
3342
3343   //dump "GetGroups"
3344   if(!myPreviewMode && mesh_i)
3345     mesh_i->GetGroups();
3346
3347   return mesh._retn();
3348 }
3349
3350 //=======================================================================
3351 //function : FindCoincidentNodes
3352 //purpose  :
3353 //=======================================================================
3354
3355 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
3356                                               SMESH::array_of_long_array_out GroupsOfNodes)
3357 {
3358   initData();
3359
3360   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3361   ::SMESH_MeshEditor anEditor( myMesh );
3362   set<const SMDS_MeshNode*> nodes; // no input nodes
3363   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3364
3365   GroupsOfNodes = new SMESH::array_of_long_array;
3366   GroupsOfNodes->length( aListOfListOfNodes.size() );
3367   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3368   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3369     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3370     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3371     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3372     aGroup.length( aListOfNodes.size() );
3373     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3374       aGroup[ j ] = (*lIt)->GetID();
3375   }
3376   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3377                 << Tolerance << " )";
3378 }
3379
3380 //=======================================================================
3381 //function : FindCoincidentNodesOnPart
3382 //purpose  :
3383 //=======================================================================
3384 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
3385                                                    CORBA::Double                  Tolerance,
3386                                                    SMESH::array_of_long_array_out GroupsOfNodes)
3387 {
3388   initData();
3389   SMESH::long_array_var aElementsId = theObject->GetIDs();
3390
3391   SMESHDS_Mesh* aMesh = GetMeshDS();
3392   set<const SMDS_MeshNode*> nodes;
3393
3394   if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
3395        SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) {
3396     for(int i = 0; i < aElementsId->length(); i++) {
3397       CORBA::Long ind = aElementsId[i];
3398       const SMDS_MeshNode * elem = aMesh->FindNode(ind);
3399       if(elem)
3400         nodes.insert(elem);
3401     }
3402   }
3403   else {
3404     for(int i = 0; i < aElementsId->length(); i++) {
3405       CORBA::Long ind = aElementsId[i];
3406       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
3407       if(elem) {
3408         SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
3409         while ( nIt->more() )
3410           nodes.insert( nodes.end(),static_cast<const SMDS_MeshNode*>(nIt->next()));
3411       }
3412     }
3413   }
3414
3415
3416   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3417   ::SMESH_MeshEditor anEditor( myMesh );
3418   if(!nodes.empty())
3419     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3420
3421   GroupsOfNodes = new SMESH::array_of_long_array;
3422   GroupsOfNodes->length( aListOfListOfNodes.size() );
3423   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3424   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3425     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3426     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3427     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3428     aGroup.length( aListOfNodes.size() );
3429     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3430       aGroup[ j ] = (*lIt)->GetID();
3431   }
3432   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3433                 <<theObject<<", "
3434                 << Tolerance << " )";
3435 }
3436
3437 //=======================================================================
3438 //function : MergeNodes
3439 //purpose  :
3440 //=======================================================================
3441
3442 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
3443 {
3444   initData();
3445
3446   SMESHDS_Mesh* aMesh = GetMeshDS();
3447
3448   TPythonDump aTPythonDump;
3449   aTPythonDump << this << ".MergeNodes([";
3450   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3451   for (int i = 0; i < GroupsOfNodes.length(); i++)
3452   {
3453     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
3454     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
3455     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
3456     for ( int j = 0; j < aNodeGroup.length(); j++ )
3457     {
3458       CORBA::Long index = aNodeGroup[ j ];
3459       const SMDS_MeshNode * node = aMesh->FindNode(index);
3460       if ( node )
3461         aListOfNodes.push_back( node );
3462     }
3463     if ( aListOfNodes.size() < 2 )
3464       aListOfListOfNodes.pop_back();
3465
3466     if ( i > 0 ) aTPythonDump << ", ";
3467     aTPythonDump << aNodeGroup;
3468   }
3469   ::SMESH_MeshEditor anEditor( myMesh );
3470   anEditor.MergeNodes( aListOfListOfNodes );
3471
3472   aTPythonDump <<  "])";
3473 }
3474
3475 //=======================================================================
3476 //function : FindEqualElements
3477 //purpose  :
3478 //=======================================================================
3479 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
3480                                            SMESH::array_of_long_array_out GroupsOfElementsID)
3481 {
3482   initData();
3483   if ( !(!CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
3484          SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) ) {
3485     typedef list<int> TListOfIDs;
3486     set<const SMDS_MeshElement*> elems;
3487     SMESH::long_array_var aElementsId = theObject->GetIDs();
3488     SMESHDS_Mesh* aMesh = GetMeshDS();
3489
3490     for(int i = 0; i < aElementsId->length(); i++) {
3491       CORBA::Long anID = aElementsId[i];
3492       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
3493       if (elem) {
3494         elems.insert(elem);
3495       }
3496     }
3497
3498     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3499     ::SMESH_MeshEditor anEditor( myMesh );
3500     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
3501
3502     GroupsOfElementsID = new SMESH::array_of_long_array;
3503     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
3504
3505     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
3506     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
3507       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
3508       TListOfIDs& listOfIDs = *arraysIt;
3509       aGroup.length( listOfIDs.size() );
3510       TListOfIDs::iterator idIt = listOfIDs.begin();
3511       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
3512         aGroup[ k ] = *idIt;
3513       }
3514     }
3515
3516     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
3517                   <<theObject<<" )";
3518   }
3519 }
3520
3521 //=======================================================================
3522 //function : MergeElements
3523 //purpose  :
3524 //=======================================================================
3525
3526 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
3527 {
3528   initData();
3529
3530   TPythonDump aTPythonDump;
3531   aTPythonDump << this << ".MergeElements( [";
3532
3533   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
3534
3535   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
3536     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
3537     aListOfListOfElementsID.push_back( list< int >() );
3538     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
3539     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
3540       CORBA::Long id = anElemsIDGroup[ j ];
3541       aListOfElemsID.push_back( id );
3542     }
3543     if ( aListOfElemsID.size() < 2 )
3544       aListOfListOfElementsID.pop_back();
3545     if ( i > 0 ) aTPythonDump << ", ";
3546     aTPythonDump << anElemsIDGroup;
3547   }
3548
3549   ::SMESH_MeshEditor anEditor( myMesh );
3550   anEditor.MergeElements(aListOfListOfElementsID);
3551
3552   aTPythonDump << "] )";
3553 }
3554
3555 //=======================================================================
3556 //function : MergeEqualElements
3557 //purpose  :
3558 //=======================================================================
3559
3560 void SMESH_MeshEditor_i::MergeEqualElements()
3561 {
3562   initData();
3563
3564   ::SMESH_MeshEditor anEditor( myMesh );
3565   anEditor.MergeEqualElements();
3566
3567   TPythonDump() << this << ".MergeEqualElements()";
3568 }
3569
3570 //=============================================================================
3571 /*!
3572  * Move the node to a given point
3573  */
3574 //=============================================================================
3575
3576 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
3577                                             CORBA::Double x,
3578                                             CORBA::Double y,
3579                                             CORBA::Double z)
3580 {
3581   initData(/*deleteSearchers=*/false);
3582
3583   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
3584   if ( !node )
3585     return false;
3586
3587   if ( theNodeSearcher )
3588     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3589
3590   if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3591     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3592   else
3593     GetMeshDS()->MoveNode(node, x, y, z);
3594
3595   // Update Python script
3596   TPythonDump() << "isDone = " << this << ".MoveNode( "
3597                 << NodeID << ", " << x << ", " << y << ", " << z << " )";
3598
3599   return true;
3600 }
3601
3602 //================================================================================
3603 /*!
3604  * \brief Return ID of node closest to a given point
3605  */
3606 //================================================================================
3607
3608 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
3609                                                   CORBA::Double y,
3610                                                   CORBA::Double z)
3611 {
3612   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3613
3614   if ( !theNodeSearcher ) {
3615     ::SMESH_MeshEditor anEditor( myMesh );
3616     theNodeSearcher = anEditor.GetNodeSearcher();
3617   }
3618   gp_Pnt p( x,y,z );
3619   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
3620     return node->GetID();
3621
3622   return 0;
3623 }
3624
3625 //================================================================================
3626 /*!
3627  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
3628  * move the node closest to the point to point's location and return ID of the node
3629  */
3630 //================================================================================
3631
3632 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
3633                                                        CORBA::Double y,
3634                                                        CORBA::Double z,
3635                                                        CORBA::Long   theNodeID)
3636 {
3637   // We keep theNodeSearcher until any mesh modification:
3638   // 1) initData() deletes theNodeSearcher at any edition,
3639   // 2) TSearchersDeleter - at any mesh compute event and mesh change
3640
3641   initData(/*deleteSearchers=*/false);
3642
3643   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
3644
3645   int nodeID = theNodeID;
3646   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
3647   if ( !node ) // preview moving node
3648   {
3649     if ( !theNodeSearcher ) {
3650       ::SMESH_MeshEditor anEditor( myMesh );
3651       theNodeSearcher = anEditor.GetNodeSearcher();
3652     }
3653     gp_Pnt p( x,y,z );
3654     node = theNodeSearcher->FindClosestTo( p );
3655   }
3656   if ( node ) {
3657     nodeID = node->GetID();
3658     if ( myPreviewMode ) // make preview data
3659     {
3660       // in a preview mesh, make edges linked to a node
3661       TPreviewMesh tmpMesh;
3662       TIDSortedElemSet linkedNodes;
3663       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
3664       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
3665       for ( ; nIt != linkedNodes.end(); ++nIt )
3666       {
3667         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
3668         tmpMesh.Copy( &edge );
3669       }
3670       // move copied node
3671       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
3672       if ( node )
3673         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
3674       // fill preview data
3675       ::SMESH_MeshEditor anEditor( & tmpMesh );
3676       storeResult( anEditor );
3677     }
3678     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
3679     {
3680       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
3681     }
3682     else
3683     {
3684       GetMeshDS()->MoveNode(node, x, y, z);
3685     }
3686   }
3687
3688   if ( !myPreviewMode ) {
3689     TPythonDump() << "nodeID = " << this
3690                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
3691                   << ", " << nodeID << " )";
3692   }
3693
3694   return nodeID;
3695 }
3696
3697 //=======================================================================
3698 /*!
3699  * Return elements of given type where the given point is IN or ON.
3700  *
3701  * 'ALL' type means elements of any type excluding nodes
3702  */
3703 //=======================================================================
3704
3705 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
3706                                                            CORBA::Double      y,
3707                                                            CORBA::Double      z,
3708                                                            SMESH::ElementType type)
3709 {
3710   SMESH::long_array_var res = new SMESH::long_array;
3711   vector< const SMDS_MeshElement* > foundElems;
3712
3713   theSearchersDeleter.Set( myMesh );
3714   if ( !theElementSearcher ) {
3715     ::SMESH_MeshEditor anEditor( myMesh );
3716     theElementSearcher = anEditor.GetElementSearcher();
3717   }
3718   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
3719                                            SMDSAbs_ElementType( type ),
3720                                            foundElems);
3721   res->length( foundElems.size() );
3722   for ( int i = 0; i < foundElems.size(); ++i )
3723     res[i] = foundElems[i]->GetID();
3724
3725   if ( !myPreviewMode ) // call from tui
3726     TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
3727                   << x << ", "
3728                   << y << ", "
3729                   << z << ", "
3730                   << type << " )";
3731
3732   return res._retn();
3733 }
3734
3735 //=======================================================================
3736 //function : convError
3737 //purpose  :
3738 //=======================================================================
3739
3740 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
3741
3742 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
3743 {
3744   switch ( e ) {
3745     RETCASE( SEW_OK );
3746     RETCASE( SEW_BORDER1_NOT_FOUND );
3747     RETCASE( SEW_BORDER2_NOT_FOUND );
3748     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
3749     RETCASE( SEW_BAD_SIDE_NODES );
3750     RETCASE( SEW_VOLUMES_TO_SPLIT );
3751     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
3752     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
3753     RETCASE( SEW_BAD_SIDE1_NODES );
3754     RETCASE( SEW_BAD_SIDE2_NODES );
3755   }
3756   return SMESH::SMESH_MeshEditor::SEW_OK;
3757 }
3758
3759 //=======================================================================
3760 //function : SewFreeBorders
3761 //purpose  :
3762 //=======================================================================
3763
3764 SMESH::SMESH_MeshEditor::Sew_Error
3765 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
3766                                    CORBA::Long SecondNodeID1,
3767                                    CORBA::Long LastNodeID1,
3768                                    CORBA::Long FirstNodeID2,
3769                                    CORBA::Long SecondNodeID2,
3770                                    CORBA::Long LastNodeID2,
3771                                    CORBA::Boolean CreatePolygons,
3772                                    CORBA::Boolean CreatePolyedrs)
3773 {
3774   initData();
3775
3776   SMESHDS_Mesh* aMesh = GetMeshDS();
3777
3778   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
3779   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
3780   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
3781   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
3782   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
3783   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
3784
3785   if (!aBorderFirstNode ||
3786       !aBorderSecondNode||
3787       !aBorderLastNode)
3788     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3789   if (!aSide2FirstNode  ||
3790       !aSide2SecondNode ||
3791       !aSide2ThirdNode)
3792     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
3793
3794   TPythonDump() << "error = " << this << ".SewFreeBorders( "
3795                 << FirstNodeID1  << ", "
3796                 << SecondNodeID1 << ", "
3797                 << LastNodeID1   << ", "
3798                 << FirstNodeID2  << ", "
3799                 << SecondNodeID2 << ", "
3800                 << LastNodeID2   << ", "
3801                 << CreatePolygons<< ", "
3802                 << CreatePolyedrs<< " )";
3803
3804   ::SMESH_MeshEditor anEditor( myMesh );
3805   SMESH::SMESH_MeshEditor::Sew_Error error =
3806     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3807                                        aBorderSecondNode,
3808                                        aBorderLastNode,
3809                                        aSide2FirstNode,
3810                                        aSide2SecondNode,
3811                                        aSide2ThirdNode,
3812                                        true,
3813                                        CreatePolygons,
3814                                        CreatePolyedrs) );
3815
3816   storeResult(anEditor);
3817
3818   return error;
3819 }
3820
3821
3822 //=======================================================================
3823 //function : SewConformFreeBorders
3824 //purpose  :
3825 //=======================================================================
3826
3827 SMESH::SMESH_MeshEditor::Sew_Error
3828 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
3829                                           CORBA::Long SecondNodeID1,
3830                                           CORBA::Long LastNodeID1,
3831                                           CORBA::Long FirstNodeID2,
3832                                           CORBA::Long SecondNodeID2)
3833 {
3834   initData();
3835
3836   SMESHDS_Mesh* aMesh = GetMeshDS();
3837
3838   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
3839   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
3840   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
3841   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
3842   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
3843   const SMDS_MeshNode* aSide2ThirdNode   = 0;
3844
3845   if (!aBorderFirstNode ||
3846       !aBorderSecondNode||
3847       !aBorderLastNode )
3848     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3849   if (!aSide2FirstNode  ||
3850       !aSide2SecondNode)
3851     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
3852
3853   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
3854                 << FirstNodeID1  << ", "
3855                 << SecondNodeID1 << ", "
3856                 << LastNodeID1   << ", "
3857                 << FirstNodeID2  << ", "
3858                 << SecondNodeID2 << " )";
3859
3860   ::SMESH_MeshEditor anEditor( myMesh );
3861   SMESH::SMESH_MeshEditor::Sew_Error error =
3862     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3863                                        aBorderSecondNode,
3864                                        aBorderLastNode,
3865                                        aSide2FirstNode,
3866                                        aSide2SecondNode,
3867                                        aSide2ThirdNode,
3868                                        true,
3869                                        false, false) );
3870
3871   storeResult(anEditor);
3872
3873   return error;
3874 }
3875
3876
3877 //=======================================================================
3878 //function : SewBorderToSide
3879 //purpose  :
3880 //=======================================================================
3881
3882 SMESH::SMESH_MeshEditor::Sew_Error
3883 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
3884                                     CORBA::Long SecondNodeIDOnFreeBorder,
3885                                     CORBA::Long LastNodeIDOnFreeBorder,
3886                                     CORBA::Long FirstNodeIDOnSide,
3887                                     CORBA::Long LastNodeIDOnSide,
3888                                     CORBA::Boolean CreatePolygons,
3889                                     CORBA::Boolean CreatePolyedrs)
3890 {
3891   initData();
3892
3893   SMESHDS_Mesh* aMesh = GetMeshDS();
3894
3895   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
3896   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
3897   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
3898   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
3899   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
3900   const SMDS_MeshNode* aSide2ThirdNode   = 0;
3901
3902   if (!aBorderFirstNode ||
3903       !aBorderSecondNode||
3904       !aBorderLastNode  )
3905     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
3906   if (!aSide2FirstNode  ||
3907       !aSide2SecondNode)
3908     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
3909
3910   TPythonDump() << "error = " << this << ".SewBorderToSide( "
3911                 << FirstNodeIDOnFreeBorder  << ", "
3912                 << SecondNodeIDOnFreeBorder << ", "
3913                 << LastNodeIDOnFreeBorder   << ", "
3914                 << FirstNodeIDOnSide        << ", "
3915                 << LastNodeIDOnSide         << ", "
3916                 << CreatePolygons           << ", "
3917                 << CreatePolyedrs           << ") ";
3918
3919   ::SMESH_MeshEditor anEditor( myMesh );
3920   SMESH::SMESH_MeshEditor::Sew_Error error =
3921     convError( anEditor.SewFreeBorder (aBorderFirstNode,
3922                                        aBorderSecondNode,
3923                                        aBorderLastNode,
3924                                        aSide2FirstNode,
3925                                        aSide2SecondNode,
3926                                        aSide2ThirdNode,
3927                                        false,
3928                                        CreatePolygons,
3929                                        CreatePolyedrs) );
3930
3931   storeResult(anEditor);
3932
3933   return error;
3934 }
3935
3936
3937 //=======================================================================
3938 //function : SewSideElements
3939 //purpose  :
3940 //=======================================================================
3941
3942 SMESH::SMESH_MeshEditor::Sew_Error
3943 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
3944                                     const SMESH::long_array& IDsOfSide2Elements,
3945                                     CORBA::Long NodeID1OfSide1ToMerge,
3946                                     CORBA::Long NodeID1OfSide2ToMerge,
3947                                     CORBA::Long NodeID2OfSide1ToMerge,
3948                                     CORBA::Long NodeID2OfSide2ToMerge)
3949 {
3950   initData();
3951
3952   SMESHDS_Mesh* aMesh = GetMeshDS();
3953
3954   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
3955   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
3956   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
3957   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
3958
3959   if (!aFirstNode1ToMerge ||
3960       !aFirstNode2ToMerge )
3961     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
3962   if (!aSecondNode1ToMerge||
3963       !aSecondNode2ToMerge)
3964     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
3965
3966   TIDSortedElemSet aSide1Elems, aSide2Elems;
3967   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
3968   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
3969
3970   TPythonDump() << "error = " << this << ".SewSideElements( "
3971                 << IDsOfSide1Elements << ", "
3972                 << IDsOfSide2Elements << ", "
3973                 << NodeID1OfSide1ToMerge << ", "
3974                 << NodeID1OfSide2ToMerge << ", "
3975                 << NodeID2OfSide1ToMerge << ", "
3976                 << NodeID2OfSide2ToMerge << ")";
3977
3978   ::SMESH_MeshEditor anEditor( myMesh );
3979   SMESH::SMESH_MeshEditor::Sew_Error error =
3980     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
3981                                          aFirstNode1ToMerge,
3982                                          aFirstNode2ToMerge,
3983                                          aSecondNode1ToMerge,
3984                                          aSecondNode2ToMerge));
3985
3986   storeResult(anEditor);
3987
3988   return error;
3989 }
3990
3991 //================================================================================
3992 /*!
3993  * \brief Set new nodes for given element
3994  * \param ide - element id
3995  * \param newIDs - new node ids
3996  * \retval CORBA::Boolean - true if result is OK
3997  */
3998 //================================================================================
3999
4000 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4001                                                    const SMESH::long_array& newIDs)
4002 {
4003   initData();
4004
4005   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4006   if(!elem) return false;
4007
4008   int nbn = newIDs.length();
4009   int i=0;
4010   vector<const SMDS_MeshNode*> aNodes(nbn);
4011   int nbn1=-1;
4012   for(; i<nbn; i++) {
4013     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4014     if(aNode) {
4015       nbn1++;
4016       aNodes[nbn1] = aNode;
4017     }
4018   }
4019   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4020                 << ide << ", " << newIDs << " )";
4021 #ifdef _DEBUG_
4022   TPythonDump() << "print 'ChangeElemNodes: ', isDone";
4023 #endif
4024
4025   return GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4026 }
4027
4028 //================================================================================
4029 /*!
4030  * \brief Update myLastCreated* or myPreviewData
4031  * \param anEditor - it contains last modification results
4032  */
4033 //================================================================================
4034
4035 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4036 {
4037   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
4038
4039     list<int> aNodesConnectivity;
4040     typedef map<int, int> TNodesMap;
4041     TNodesMap nodesMap;
4042
4043     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4044     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4045
4046     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4047     int nbEdges = aMeshDS->NbEdges();
4048     int nbFaces = aMeshDS->NbFaces();
4049     int nbVolum = aMeshDS->NbVolumes();
4050     switch ( previewType ) {
4051     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4052     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4053     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4054     default:;
4055     }
4056     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4057     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4058     int i = 0, j = 0;
4059     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4060
4061     while ( itMeshElems->more() ) {
4062       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4063       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4064         continue;
4065
4066       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4067       while ( itElemNodes->more() ) {
4068         const SMDS_MeshNode* aMeshNode = 
4069           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4070         int aNodeID = aMeshNode->GetID();
4071         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4072         if ( anIter == nodesMap.end() ) {
4073           // filling the nodes coordinates
4074           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4075           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4076           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4077           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4078           j++;
4079         }
4080         aNodesConnectivity.push_back(anIter->second);
4081       }
4082
4083       // filling the elements types
4084       SMDSAbs_ElementType aType;
4085       bool isPoly;
4086       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4087         aType = SMDSAbs_Node;
4088         isPoly = false;
4089         }
4090         else*/ {
4091         aType = aMeshElem->GetType();
4092         isPoly = aMeshElem->IsPoly();
4093       }
4094
4095       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4096       myPreviewData->elementTypes[i].isPoly = isPoly;
4097       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4098       i++;
4099
4100     }
4101     myPreviewData->nodesXYZ.length( j );
4102
4103     // filling the elements connectivities
4104     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4105     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4106     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4107       myPreviewData->elementConnectivities[i] = *aConnIter;
4108
4109     return;
4110   }
4111
4112   {
4113     // add new nodes into myLastCreatedNodes
4114     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4115     myLastCreatedNodes->length(aSeq.Length());
4116     for(int i=0; i<aSeq.Length(); i++)
4117       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
4118   }
4119   {
4120     // add new elements into myLastCreatedElems
4121     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4122     myLastCreatedElems->length(aSeq.Length());
4123     for(int i=0; i<aSeq.Length(); i++)
4124       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
4125   }
4126 }
4127
4128 //================================================================================
4129 /*!
4130  * Return data of mesh edition preview
4131  */
4132 //================================================================================
4133
4134 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4135 {
4136   return myPreviewData._retn();
4137 }
4138
4139 //================================================================================
4140 /*!
4141  * \brief Returns list of it's IDs of created nodes
4142  * \retval SMESH::long_array* - list of node ID
4143  */
4144 //================================================================================
4145
4146 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4147 {
4148   return myLastCreatedNodes._retn();
4149 }
4150
4151 //================================================================================
4152 /*!
4153  * \brief Returns list of it's IDs of created elements
4154  * \retval SMESH::long_array* - list of elements' ID
4155  */
4156 //================================================================================
4157
4158 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4159 {
4160   return myLastCreatedElems._retn();
4161 }
4162
4163 //=======================================================================
4164 //function : ConvertToQuadratic
4165 //purpose  :
4166 //=======================================================================
4167
4168 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4169 {
4170   ::SMESH_MeshEditor anEditor( myMesh );
4171   anEditor.ConvertToQuadratic(theForce3d);
4172   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4173 }
4174
4175 //=======================================================================
4176 //function : ConvertFromQuadratic
4177 //purpose  : 
4178 //=======================================================================
4179
4180 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4181 {
4182   ::SMESH_MeshEditor anEditor( myMesh );
4183   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
4184   TPythonDump() << this << ".ConvertFromQuadratic()";
4185   return isDone;
4186 }
4187
4188 //=======================================================================
4189 //function : makeMesh
4190 //purpose  : create a named imported mesh 
4191 //=======================================================================
4192
4193 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4194 {
4195   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4196   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4197   SALOMEDS::Study_var study = gen->GetCurrentStudy();
4198   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
4199   gen->SetName( meshSO, theMeshName, "Mesh" );
4200   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4201
4202   return mesh._retn();
4203 }
4204
4205 //=======================================================================
4206 //function : DumpGroupsList
4207 //purpose  :
4208 //=======================================================================
4209 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython, 
4210                                         const SMESH::ListOfGroups * theGroupList)
4211 {
4212   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
4213   if(isDumpGroupList) {
4214     theDumpPython << theGroupList << " = ";
4215   }
4216 }
4217
4218 //================================================================================
4219 /*!
4220   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4221   \param theNodes - identifiers of nodes to be doubled
4222   \param theModifiedElems - identifiers of elements to be updated by the new (doubled) 
4223          nodes. If list of element identifiers is empty then nodes are doubled but 
4224          they not assigned to elements
4225   \return TRUE if operation has been completed successfully, FALSE otherwise
4226   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
4227 */
4228 //================================================================================
4229
4230 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes, 
4231                                                 const SMESH::long_array& theModifiedElems )
4232 {
4233   initData();
4234
4235   ::SMESH_MeshEditor aMeshEditor( myMesh );
4236   list< int > aListOfNodes;
4237   int i, n;
4238   for ( i = 0, n = theNodes.length(); i < n; i++ )
4239     aListOfNodes.push_back( theNodes[ i ] );
4240
4241   list< int > aListOfElems;
4242   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4243     aListOfElems.push_back( theModifiedElems[ i ] );
4244
4245   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
4246
4247   storeResult( aMeshEditor) ;
4248
4249   return aResult;
4250 }
4251
4252 //================================================================================
4253 /*!
4254   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4255   This method provided for convenience works as DoubleNodes() described above.
4256   \param theNodeId - identifier of node to be doubled.
4257   \param theModifiedElems - identifiers of elements to be updated.
4258   \return TRUE if operation has been completed successfully, FALSE otherwise
4259   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
4260 */
4261 //================================================================================
4262
4263 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId, 
4264                                                const SMESH::long_array& theModifiedElems )
4265 {
4266   SMESH::long_array_var aNodes = new SMESH::long_array;
4267   aNodes->length( 1 );
4268   aNodes[ 0 ] = theNodeId;
4269   return DoubleNodes( aNodes, theModifiedElems );
4270 }
4271
4272 //================================================================================
4273 /*!
4274   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4275   This method provided for convenience works as DoubleNodes() described above.
4276   \param theNodes - group of nodes to be doubled.
4277   \param theModifiedElems - group of elements to be updated.
4278   \return TRUE if operation has been completed successfully, FALSE otherwise
4279   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
4280 */
4281 //================================================================================
4282
4283 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup( 
4284   SMESH::SMESH_GroupBase_ptr theNodes,
4285   SMESH::SMESH_GroupBase_ptr theModifiedElems )
4286 {
4287   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4288     return false;
4289
4290   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4291   SMESH::long_array_var aModifiedElems;
4292   if ( !CORBA::is_nil( theModifiedElems ) )
4293     aModifiedElems = theModifiedElems->GetListOfID();
4294   else 
4295   {
4296     aModifiedElems = new SMESH::long_array;
4297     aModifiedElems->length( 0 );
4298   }
4299
4300   return DoubleNodes( aNodes, aModifiedElems );
4301 }
4302
4303 //================================================================================
4304 /*!
4305   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4306   This method provided for convenience works as DoubleNodes() described above.
4307   \param theNodes - list of groups of nodes to be doubled
4308   \param theModifiedElems - list of groups of elements to be updated.
4309   \return TRUE if operation has been completed successfully, FALSE otherwise
4310   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
4311 */
4312 //================================================================================
4313
4314 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups( 
4315   const SMESH::ListOfGroups& theNodes,
4316   const SMESH::ListOfGroups& theModifiedElems )
4317 {
4318   initData();
4319
4320   ::SMESH_MeshEditor aMeshEditor( myMesh );
4321
4322   std::list< int > aNodes;
4323   int i, n, j, m;
4324   for ( i = 0, n = theNodes.length(); i < n; i++ )
4325   {
4326     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
4327     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
4328     {
4329       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4330       for ( j = 0, m = aCurr->length(); j < m; j++ )
4331         aNodes.push_back( aCurr[ j ] );
4332     }
4333   }
4334
4335   std::list< int > anElems;
4336   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4337   {
4338     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
4339     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
4340     {
4341       SMESH::long_array_var aCurr = aGrp->GetListOfID();
4342       for ( j = 0, m = aCurr->length(); j < m; j++ )
4343         anElems.push_back( aCurr[ j ] );
4344     }
4345   }
4346
4347   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
4348
4349   storeResult( aMeshEditor) ;
4350
4351   return aResult;
4352 }
4353
4354 //================================================================================
4355 /*!
4356   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4357   \param theElems - the list of elements (edges or faces) to be replicated
4358   The nodes for duplication could be found from these elements
4359   \param theNodesNot - list of nodes to NOT replicate
4360   \param theAffectedElems - the list of elements (cells and edges) to which the 
4361   replicated nodes should be associated to.
4362   \return TRUE if operation has been completed successfully, FALSE otherwise
4363   \sa DoubleNodeGroup(), DoubleNodeGroups()
4364 */
4365 //================================================================================
4366
4367 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems, 
4368                                                    const SMESH::long_array& theNodesNot,
4369                                                    const SMESH::long_array& theAffectedElems )
4370
4371 {
4372   initData();
4373
4374   ::SMESH_MeshEditor aMeshEditor( myMesh );
4375
4376   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4377   TIDSortedElemSet anElems, aNodes, anAffected;
4378   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4379   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4380   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
4381
4382   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4383
4384   storeResult( aMeshEditor) ;
4385
4386   // Update Python script
4387   TPythonDump() << "isDone = " << this << ".DoubleNodes( " << theElems << ", "
4388     << theNodesNot << ", " << theAffectedElems << " )";
4389   return aResult;
4390 }
4391
4392 //================================================================================
4393 /*!
4394   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4395   \param theElems - the list of elements (edges or faces) to be replicated
4396   The nodes for duplication could be found from these elements
4397   \param theNodesNot - list of nodes to NOT replicate
4398   \param theShape - shape to detect affected elements (element which geometric center
4399   located on or inside shape).
4400   The replicated nodes should be associated to affected elements.
4401   \return TRUE if operation has been completed successfully, FALSE otherwise
4402   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
4403 */
4404 //================================================================================
4405
4406 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion
4407 ( const SMESH::long_array& theElems, 
4408   const SMESH::long_array& theNodesNot,
4409   GEOM::GEOM_Object_ptr    theShape )
4410
4411 {
4412   initData();
4413
4414   ::SMESH_MeshEditor aMeshEditor( myMesh );
4415
4416   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4417   TIDSortedElemSet anElems, aNodes;
4418   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
4419   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
4420
4421   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4422   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4423
4424   storeResult( aMeshEditor) ;
4425
4426   // Update Python script
4427   TPythonDump() << "isDone = " << this << ".DoubleNodesInRegion( " << theElems << ", "
4428     << theNodesNot << ", " << theShape << " )";
4429   return aResult;
4430 }
4431
4432 //================================================================================
4433 /*!
4434   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4435   \param theElems - group of of elements (edges or faces) to be replicated
4436   \param theNodesNot - group of nodes not to replicated
4437   \param theAffectedElems - group of elements to which the replicated nodes
4438   should be associated to.
4439   \return TRUE if operation has been completed successfully, FALSE otherwise
4440   \sa DoubleNodes(), DoubleNodeGroups()
4441 */
4442 //================================================================================
4443
4444 static void groupToSet(SMESH::SMESH_GroupBase_ptr theGrp,
4445                        SMESHDS_Mesh*              theMeshDS,
4446                        TIDSortedElemSet&          theElemSet,
4447                        const SMDSAbs_ElementType  theType)
4448
4449 {
4450   if ( CORBA::is_nil( theGrp ) )
4451     return;
4452   SMESH::long_array_var anIDs = theGrp->GetIDs();
4453   arrayToSet( anIDs, theMeshDS, theElemSet, theType);
4454 }
4455
4456 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup( 
4457                                                        SMESH::SMESH_GroupBase_ptr theElems,
4458                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
4459                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems )
4460
4461 {
4462   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4463     return false;
4464
4465   initData();
4466
4467   ::SMESH_MeshEditor aMeshEditor( myMesh );
4468
4469   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4470   TIDSortedElemSet anElems, aNodes, anAffected;
4471   groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4472   groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4473   groupToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
4474
4475   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4476
4477   storeResult( aMeshEditor) ;
4478
4479   // Update Python script
4480   TPythonDump() << "isDone = " << this << ".DoubleNodeGroup( " << theElems << ", "
4481     << theNodesNot << ", " << theAffectedElems << " )";
4482   return aResult;
4483 }
4484
4485 //================================================================================
4486 /*!
4487   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4488   \param theElems - group of of elements (edges or faces) to be replicated
4489   \param theNodesNot - group of nodes not to replicated
4490   \param theShape - shape to detect affected elements (element which geometric center
4491   located on or inside shape).
4492   The replicated nodes should be associated to affected elements.
4493   \return TRUE if operation has been completed successfully, FALSE otherwise
4494   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
4495 */
4496 //================================================================================
4497
4498 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion( 
4499                                                                SMESH::SMESH_GroupBase_ptr theElems,
4500                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
4501                                                                GEOM::GEOM_Object_ptr      theShape )
4502
4503 {
4504   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
4505     return false;
4506
4507   initData();
4508
4509   ::SMESH_MeshEditor aMeshEditor( myMesh );
4510
4511   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4512   TIDSortedElemSet anElems, aNodes, anAffected;
4513   groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
4514   groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
4515
4516   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4517   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4518
4519   storeResult( aMeshEditor) ;
4520
4521   // Update Python script
4522   TPythonDump() << "isDone = " << this << ".DoubleNodeGroupInRegion( " << theElems << ", "
4523     << theNodesNot << ", " << theShape << " )";
4524   return aResult;
4525 }
4526
4527 //================================================================================
4528 /*!
4529   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4530   This method provided for convenience works as DoubleNodes() described above.
4531   \param theElems - list of groups of elements (edges or faces) to be replicated
4532   \param theNodesNot - list of groups of nodes not to replicated
4533   \param theAffectedElems - group of elements to which the replicated nodes
4534   should be associated to.
4535   \return TRUE if operation has been completed successfully, FALSE otherwise
4536   \sa DoubleNodeGroup(), DoubleNodes()
4537 */
4538 //================================================================================
4539
4540 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
4541                              SMESHDS_Mesh*              theMeshDS,
4542                              TIDSortedElemSet&          theElemSet,
4543                              const bool                 theIsNodeGrp)
4544 {
4545   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
4546   {
4547     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
4548     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE 
4549                                     : aGrp->GetType() != SMESH::NODE ) )
4550     {
4551       SMESH::long_array_var anIDs = aGrp->GetIDs();
4552       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
4553     }
4554   }
4555 }
4556
4557 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups( 
4558                                                         const SMESH::ListOfGroups& theElems,
4559                                                         const SMESH::ListOfGroups& theNodesNot,
4560                                                         const SMESH::ListOfGroups& theAffectedElems )
4561 {
4562   initData();
4563
4564   ::SMESH_MeshEditor aMeshEditor( myMesh );
4565
4566   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4567   TIDSortedElemSet anElems, aNodes, anAffected;
4568   listOfGroupToSet(theElems, aMeshDS, anElems, false );
4569   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
4570   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
4571
4572   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
4573
4574   storeResult( aMeshEditor) ;
4575
4576   // Update Python script
4577   TPythonDump() << "isDone = " << this << ".DoubleNodeGroups( " << &theElems << ", "
4578     << &theNodesNot << ", " << &theAffectedElems << " )";
4579   return aResult;
4580 }
4581
4582 //================================================================================
4583 /*!
4584   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4585   This method provided for convenience works as DoubleNodes() described above.
4586   \param theElems - list of groups of elements (edges or faces) to be replicated
4587   \param theNodesNot - list of groups of nodes not to replicated
4588   \param theShape - shape to detect affected elements (element which geometric center
4589   located on or inside shape).
4590   The replicated nodes should be associated to affected elements.
4591   \return TRUE if operation has been completed successfully, FALSE otherwise
4592   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
4593 */
4594 //================================================================================
4595
4596 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion( 
4597                                                                 const SMESH::ListOfGroups& theElems,
4598                                                                 const SMESH::ListOfGroups& theNodesNot,
4599                                                                 GEOM::GEOM_Object_ptr      theShape )
4600 {
4601   initData();
4602
4603   ::SMESH_MeshEditor aMeshEditor( myMesh );
4604
4605   SMESHDS_Mesh* aMeshDS = GetMeshDS();
4606   TIDSortedElemSet anElems, aNodes;
4607   listOfGroupToSet(theElems, aMeshDS, anElems,false );
4608   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
4609
4610   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
4611   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
4612
4613   storeResult( aMeshEditor) ;
4614
4615   // Update Python script
4616   TPythonDump() << "isDone = " << this << ".DoubleNodeGroupsInRegion( " << &theElems << ", "
4617     << &theNodesNot << ", " << theShape << " )";
4618   return aResult;
4619 }
4620
4621 //================================================================================
4622 /*!
4623   \brief Generated skin mesh (containing 2D cells) from 3D mesh
4624    The created 2D mesh elements based on nodes of free faces of boundary volumes
4625   \return TRUE if operation has been completed successfully, FALSE otherwise
4626 */
4627 //================================================================================
4628
4629 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
4630 {
4631   initData();
4632
4633   ::SMESH_MeshEditor aMeshEditor( myMesh );
4634   bool aResult = aMeshEditor.Make2DMeshFrom3D();
4635   storeResult( aMeshEditor) ;
4636   
4637   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
4638   return aResult;
4639 }