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