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