Salome HOME
PAL13312 (EDF262 SMESH mesh concatenation operation needed):
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  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 //
24 //  File   : SMESH_MeshEditor_i.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_MeshEditor_i.hxx"
30
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_PythonDump.hxx"
40
41 #include "utilities.h"
42
43 #include <gp_Ax1.hxx>
44 #include <gp_Ax2.hxx>
45 #include <gp_Vec.hxx>
46
47 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
48 #define NO_CAS_CATCH
49 #endif
50
51 #include <Standard_Failure.hxx>
52
53 #ifdef NO_CAS_CATCH
54 #include <Standard_ErrorHandler.hxx>
55 #else
56 #include "CASCatch.hxx"
57 #endif
58
59 #include <sstream>
60
61 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
62
63 using namespace std;
64 using SMESH::TPythonDump;
65
66 namespace {
67
68   //=============================================================================
69   /*!
70    * \brief Mesh to apply modifications for preview purposes
71    */
72   //=============================================================================
73
74   struct TPreviewMesh: public SMESH_Mesh
75   {
76     SMDSAbs_ElementType myPreviewType; // type to show
77     //!< Constructor
78     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
79       _isShapeToMesh = _id =_studyId =_idDoc = 0;
80       _myMeshDS  = new SMESHDS_Mesh( _id, true );
81       myPreviewType = previewElements;
82     }
83     //!< Destructor
84     virtual ~TPreviewMesh() { delete _myMeshDS; }
85     //!< Copy a set of elements
86     void Copy(const TIDSortedElemSet & theElements,
87               TIDSortedElemSet&        theCopyElements,
88               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
89               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
90     {
91       // loop on theIDsOfElements
92       TIDSortedElemSet::const_iterator eIt = theElements.begin();
93       for ( ; eIt != theElements.end(); ++eIt )
94       {
95         const SMDS_MeshElement* anElem = *eIt;
96         if ( !anElem ) continue;
97         SMDSAbs_ElementType type = anElem->GetType();
98         if ( type == theAvoidType ||
99              ( theSelectType != SMDSAbs_All && type != theSelectType ))
100           continue;
101
102         if ( const SMDS_MeshElement* anElemCopy = Copy( anElem ))
103           theCopyElements.insert( theCopyElements.end(), anElemCopy );
104       }
105     }
106     //!< Copy an element
107     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
108     {
109       // copy element nodes
110       int anElemNbNodes = anElem->NbNodes();
111       vector< int > anElemNodesID( anElemNbNodes ) ;
112       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
113       for ( int i = 0; itElemNodes->more(); i++)
114       {
115         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
116         Copy( anElemNode );
117         anElemNodesID[i] = anElemNode->GetID();
118       }
119
120       // creates a corresponding element on copied nodes
121       SMDS_MeshElement* anElemCopy = 0;
122       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
123       {
124         const SMDS_PolyhedralVolumeOfNodes* ph =
125           dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*> (anElem);
126         if ( ph )
127           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
128             (anElemNodesID, ph->GetQuanities(),anElem->GetID());
129       }
130       else {
131         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
132                                                           anElem->GetType(),
133                                                           anElem->IsPoly() );
134       }
135       return anElemCopy;
136     }
137     //!< Copy a node
138     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
139     {
140       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(), 
141                                       anElemNode->GetID());
142     }
143   };// struct TPreviewMesh
144
145   static SMESH_NodeSearcher * myNodeSearcher = 0;
146
147   //=============================================================================
148   /*!
149    * \brief Deleter of myNodeSearcher at any compute event occured
150    */
151   //=============================================================================
152
153   struct TNodeSearcherDeleter : public SMESH_subMeshEventListener
154   {
155     TNodeSearcherDeleter(): SMESH_subMeshEventListener( false ) // won't be deleted by submesh
156     {}
157     //!< Delete myNodeSearcher
158     static void Delete()
159     {
160       if ( myNodeSearcher ) { delete myNodeSearcher; myNodeSearcher = 0; }
161     }
162     typedef map < int, SMESH_subMesh * > TDependsOnMap;
163     //!< The meshod called by submesh: do my main job
164     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
165                       SMESH_subMeshEventListenerData*,SMESH_Hypothesis*)
166     {
167       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
168         Delete();
169         // delete self from all submeshes
170         if ( SMESH_subMesh* myMainSubMesh = sm->GetFather()->GetSubMeshContaining(1) ) {
171           const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
172           TDependsOnMap::const_iterator sm;
173           for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
174             sm->second->DeleteEventListener( this );
175         }
176       }
177     }
178     //!< set self on all submeshes
179     void Set(SMESH_Mesh* mesh)
180     {
181       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
182         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
183         TDependsOnMap::const_iterator sm;
184         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
185           sm->second->SetEventListener( this, 0, sm->second );
186       }
187     }
188   };
189 }
190
191 //=============================================================================
192 /*!
193  *
194  */
195 //=============================================================================
196
197 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh* theMesh, bool isPreview)
198 {
199   myMesh = theMesh;
200   myPreviewMode = isPreview;
201 }
202
203 //================================================================================
204 /*!
205  * \brief Destructor
206  */
207 //================================================================================
208
209 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
210 {
211 }
212
213 //================================================================================
214 /*!
215  * \brief Clear members
216  */
217 //================================================================================
218
219 void SMESH_MeshEditor_i::initData()
220 {
221   if ( myPreviewMode ) {
222     myPreviewData = new SMESH::MeshPreviewStruct();
223   }
224   else {
225     myLastCreatedElems = new SMESH::long_array();
226     myLastCreatedNodes = new SMESH::long_array();
227     TNodeSearcherDeleter::Delete();
228   }
229 }
230
231 //=============================================================================
232 /*!
233  *
234  */
235 //=============================================================================
236
237 CORBA::Boolean
238   SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
239 {
240   initData();
241
242   ::SMESH_MeshEditor anEditor( myMesh );
243   list< int > IdList;
244
245   for (int i = 0; i < IDsOfElements.length(); i++)
246     IdList.push_back( IDsOfElements[i] );
247
248   // Update Python script
249   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
250 #ifdef _DEBUG_
251   TPythonDump() << "print 'RemoveElements: ', isDone";
252 #endif
253   // Remove Elements
254   return anEditor.Remove( IdList, false );
255 }
256
257 //=============================================================================
258 /*!
259  *
260  */
261 //=============================================================================
262
263 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
264 {
265   initData();
266
267   ::SMESH_MeshEditor anEditor( myMesh );
268   list< int > IdList;
269   for (int i = 0; i < IDsOfNodes.length(); i++)
270     IdList.push_back( IDsOfNodes[i] );
271
272   // Update Python script
273   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
274 #ifdef _DEBUG_
275   TPythonDump() << "print 'RemoveNodes: ', isDone";
276 #endif
277
278   return anEditor.Remove( IdList, true );
279 }
280
281 //=============================================================================
282 /*!
283  *
284  */
285 //=============================================================================
286
287 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
288 {
289   initData();
290
291   int NbNodes = IDsOfNodes.length();
292   SMDS_MeshElement* elem = 0;
293   if (NbNodes == 2)
294   {
295     CORBA::Long index1 = IDsOfNodes[0];
296     CORBA::Long index2 = IDsOfNodes[1];
297     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(index1), GetMeshDS()->FindNode(index2));
298
299     // Update Python script
300     TPythonDump() << "edge = " << this << ".AddEdge([ "
301                   << index1 << ", " << index2 <<" ])";
302   }
303   if (NbNodes == 3) {
304     CORBA::Long n1 = IDsOfNodes[0];
305     CORBA::Long n2 = IDsOfNodes[1];
306     CORBA::Long n12 = IDsOfNodes[2];
307     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(n1),
308                                 GetMeshDS()->FindNode(n2),
309                                 GetMeshDS()->FindNode(n12));
310     // Update Python script
311     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
312                   <<n1<<", "<<n2<<", "<<n12<<" ])";
313   }
314
315   if(elem)
316     return elem->GetID();
317
318   return 0;
319 }
320
321 //=============================================================================
322 /*!
323  *
324  */
325 //=============================================================================
326
327 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
328                                         CORBA::Double y, CORBA::Double z)
329 {
330   initData();
331
332   const SMDS_MeshNode* N = GetMeshDS()->AddNode(x, y, z);
333
334   // Update Python script
335   TPythonDump() << "nodeID = " << this << ".AddNode( "
336                 << x << ", " << y << ", " << z << " )";
337
338   return N->GetID();
339 }
340
341 //=============================================================================
342 /*!
343  *  AddFace
344  */
345 //=============================================================================
346
347 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
348 {
349   initData();
350
351   int NbNodes = IDsOfNodes.length();
352   if (NbNodes < 3)
353   {
354     return false;
355   }
356
357   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
358   for (int i = 0; i < NbNodes; i++)
359     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
360
361   SMDS_MeshElement* elem = 0;
362   if (NbNodes == 3) {
363     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
364   }
365   else if (NbNodes == 4) {
366     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
367   }
368   else if (NbNodes == 6) {
369     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
370                                 nodes[4], nodes[5]);
371   }
372   else if (NbNodes == 8) {
373     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
374                                 nodes[4], nodes[5], nodes[6], nodes[7]);
375   }
376
377   // Update Python script
378   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
379
380   if(elem)
381     return elem->GetID();
382
383   return 0;
384 }
385
386 //=============================================================================
387 /*!
388  *  AddPolygonalFace
389  */
390 //=============================================================================
391 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace
392                                    (const SMESH::long_array & IDsOfNodes)
393 {
394   initData();
395
396   int NbNodes = IDsOfNodes.length();
397   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
398   for (int i = 0; i < NbNodes; i++)
399     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
400
401   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
402   
403   // Update Python script
404   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
405 #ifdef _DEBUG_
406   TPythonDump() << "print 'AddPolygonalFace: ', faceID";
407 #endif
408
409   if(elem)
410     return elem->GetID();
411
412   return 0;
413 }
414
415 //=============================================================================
416 /*!
417  *
418  */
419 //=============================================================================
420
421 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
422 {
423   initData();
424
425   int NbNodes = IDsOfNodes.length();
426   vector< const SMDS_MeshNode*> n(NbNodes);
427   for(int i=0;i<NbNodes;i++)
428     n[i]=GetMeshDS()->FindNode(IDsOfNodes[i]);
429
430   SMDS_MeshElement* elem = 0;
431   switch(NbNodes)
432   {
433   case 4 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
434   case 5 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
435   case 6 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
436   case 8 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
437   case 10:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
438                                         n[6],n[7],n[8],n[9]);
439     break;
440   case 13:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
441                                         n[7],n[8],n[9],n[10],n[11],n[12]);
442     break;
443   case 15:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
444                                         n[9],n[10],n[11],n[12],n[13],n[14]);
445     break;
446   case 20:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
447                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
448                                         n[15],n[16],n[17],n[18],n[19]);
449     break;
450   }
451
452   // Update Python script
453   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
454 #ifdef _DEBUG_
455   TPythonDump() << "print 'AddVolume: ', volID";
456 #endif
457
458   if(elem)
459     return elem->GetID();
460
461   return 0;
462 }
463
464 //=============================================================================
465 /*!
466  *  AddPolyhedralVolume
467  */
468 //=============================================================================
469 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
470                                    (const SMESH::long_array & IDsOfNodes,
471                                     const SMESH::long_array & Quantities)
472 {
473   initData();
474
475   int NbNodes = IDsOfNodes.length();
476   std::vector<const SMDS_MeshNode*> n (NbNodes);
477   for (int i = 0; i < NbNodes; i++)
478     n[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
479
480   int NbFaces = Quantities.length();
481   std::vector<int> q (NbFaces);
482   for (int j = 0; j < NbFaces; j++)
483     q[j] = Quantities[j];
484
485   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(n, q);
486
487   // Update Python script
488   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
489                 << IDsOfNodes << ", " << Quantities << " )";
490 #ifdef _DEBUG_
491   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
492 #endif
493
494   if(elem)
495     return elem->GetID();
496
497   return 0;
498 }
499
500 //=============================================================================
501 /*!
502  *  AddPolyhedralVolumeByFaces
503  */
504 //=============================================================================
505 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces
506                                    (const SMESH::long_array & IdsOfFaces)
507 {
508   initData();
509
510   int NbFaces = IdsOfFaces.length();
511   std::vector<const SMDS_MeshNode*> poly_nodes;
512   std::vector<int> quantities (NbFaces);
513
514   for (int i = 0; i < NbFaces; i++) {
515     const SMDS_MeshElement* aFace = GetMeshDS()->FindElement(IdsOfFaces[i]);
516     quantities[i] = aFace->NbNodes();
517
518     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
519     while (It->more()) {
520       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
521     }
522   }
523
524   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
525
526   // Update Python script
527   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
528                 << IdsOfFaces << " )";
529 #ifdef _DEBUG_
530   TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
531 #endif
532
533   if(elem)
534     return elem->GetID();
535
536   return 0;
537 }
538
539 //=============================================================================
540 /*!
541  *
542  */
543 //=============================================================================
544
545 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
546                                             CORBA::Double x,
547                                             CORBA::Double y,
548                                             CORBA::Double z)
549 {
550   initData();
551
552   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
553   if ( !node )
554     return false;
555
556   GetMeshDS()->MoveNode(node, x, y, z);
557
558   // Update Python script
559   TPythonDump() << "isDone = " << this << ".MoveNode( "
560                 << NodeID << ", " << x << ", " << y << ", " << z << " )";
561
562   return true;
563 }
564
565 //=============================================================================
566 /*!
567  *
568  */
569 //=============================================================================
570
571 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
572                                                CORBA::Long NodeID2)
573 {
574   initData();
575
576   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
577   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
578   if ( !n1 || !n2 )
579     return false;
580
581   // Update Python script
582   TPythonDump() << "isDone = " << this << ".InverseDiag( "
583                 << NodeID1 << ", " << NodeID2 << " )";
584
585   ::SMESH_MeshEditor aMeshEditor( myMesh );
586   return aMeshEditor.InverseDiag ( n1, n2 );
587 }
588
589 //=============================================================================
590 /*!
591  *
592  */
593 //=============================================================================
594
595 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
596                                               CORBA::Long NodeID2)
597 {
598   initData();
599
600   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
601   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
602   if ( !n1 || !n2 )
603     return false;
604
605   // Update Python script
606   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
607                 << NodeID1 << ", " << NodeID2 <<  " )";
608
609   ::SMESH_MeshEditor aMeshEditor( myMesh );
610
611   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
612
613   StoreResult(aMeshEditor);
614
615   return stat;
616 }
617
618 //=============================================================================
619 /*!
620  *
621  */
622 //=============================================================================
623
624 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
625 {
626   initData();
627
628   ::SMESH_MeshEditor anEditor( myMesh );
629   for (int i = 0; i < IDsOfElements.length(); i++)
630   {
631     CORBA::Long index = IDsOfElements[i];
632     const SMDS_MeshElement * elem = GetMeshDS()->FindElement(index);
633     if ( elem )
634       anEditor.Reorient( elem );
635   }
636   // Update Python script
637   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
638
639   return true;
640 }
641
642
643 //=============================================================================
644 /*!
645  *
646  */
647 //=============================================================================
648
649 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
650 {
651   initData();
652
653   SMESH::long_array_var anElementsId = theObject->GetIDs();
654   CORBA::Boolean isDone = Reorient(anElementsId);
655
656   // Clear python line, created by Reorient()
657   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
658   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
659
660   // Update Python script
661   TPythonDump() << "isDone = " << this << ".ReorientObject( " << theObject << " )";
662
663   return isDone;
664 }
665
666 namespace
667 {
668   //================================================================================
669   /*!
670    * \brief function for conversion long_array to TIDSortedElemSet
671     * \param IDs - array of IDs
672     * \param aMesh - mesh
673     * \param aMap - collection to fill
674     * \param aType - element type
675    */
676   //================================================================================
677
678   void ToMap(const SMESH::long_array & IDs,
679              const SMESHDS_Mesh*       aMesh,
680              TIDSortedElemSet&         aMap,
681              const SMDSAbs_ElementType aType = SMDSAbs_All )
682   { 
683     for (int i=0; i<IDs.length(); i++) {
684       CORBA::Long ind = IDs[i];
685       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
686       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
687         aMap.insert( elem );
688     }
689   }
690 }
691
692 //=============================================================================
693 /*!
694  *
695  */
696 //=============================================================================
697 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
698                                               SMESH::NumericalFunctor_ptr Criterion,
699                                               CORBA::Double               MaxAngle)
700 {
701   initData();
702
703   SMESHDS_Mesh* aMesh = GetMeshDS();
704   TIDSortedElemSet faces;
705   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
706
707   SMESH::NumericalFunctor_i* aNumericalFunctor =
708     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
709   SMESH::Controls::NumericalFunctorPtr aCrit;
710   if ( !aNumericalFunctor )
711     aCrit.reset( new SMESH::Controls::AspectRatio() );
712   else
713     aCrit = aNumericalFunctor->GetNumericalFunctor();
714
715   // Update Python script
716   TPythonDump() << "isDone = " << this << ".TriToQuad( "
717                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
718 #ifdef _DEBUG_
719   TPythonDump() << "print 'TriToQuad: ', isDone";
720 #endif
721
722   ::SMESH_MeshEditor anEditor( myMesh );
723
724   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
725
726   StoreResult(anEditor);
727
728   return stat;
729 }
730
731
732 //=============================================================================
733 /*!
734  *
735  */
736 //=============================================================================
737 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
738                                                     SMESH::NumericalFunctor_ptr Criterion,
739                                                     CORBA::Double               MaxAngle)
740 {
741   initData();
742
743   SMESH::long_array_var anElementsId = theObject->GetIDs();
744   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
745
746   // Clear python line(s), created by TriToQuad()
747   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
748   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
749 #ifdef _DEBUG_
750   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
751 #endif
752
753   SMESH::NumericalFunctor_i* aNumericalFunctor =
754     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
755
756   // Update Python script
757   TPythonDump() << "isDone = " << this << ".TriToQuadObject("
758                 << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
759 #ifdef _DEBUG_
760   TPythonDump() << "print 'TriToQuadObject: ', isDone";
761 #endif
762
763   return isDone;
764 }
765
766
767 //=============================================================================
768 /*!
769  *
770  */
771 //=============================================================================
772 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
773                                               SMESH::NumericalFunctor_ptr Criterion)
774 {
775   initData();
776
777   SMESHDS_Mesh* aMesh = GetMeshDS();
778   TIDSortedElemSet faces;
779   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
780
781   SMESH::NumericalFunctor_i* aNumericalFunctor =
782     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
783   SMESH::Controls::NumericalFunctorPtr aCrit;
784   if ( !aNumericalFunctor )
785     aCrit.reset( new SMESH::Controls::AspectRatio() );
786   else
787     aCrit = aNumericalFunctor->GetNumericalFunctor();
788
789
790   // Update Python script
791   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
792 #ifdef _DEBUG_
793   TPythonDump() << "print 'QuadToTri: ', isDone";
794 #endif
795
796   ::SMESH_MeshEditor anEditor( myMesh );
797   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
798
799   StoreResult(anEditor);
800
801   return stat;
802 }
803
804
805 //=============================================================================
806 /*!
807  *
808  */
809 //=============================================================================
810 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
811                                                     SMESH::NumericalFunctor_ptr Criterion)
812 {
813   initData();
814
815   SMESH::long_array_var anElementsId = theObject->GetIDs();
816   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
817
818   // Clear python line(s), created by QuadToTri()
819   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
820   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
821 #ifdef _DEBUG_
822   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
823 #endif
824
825   SMESH::NumericalFunctor_i* aNumericalFunctor =
826     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
827
828   // Update Python script
829   TPythonDump() << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
830 #ifdef _DEBUG_
831   TPythonDump() << "print 'QuadToTriObject: ', isDone";
832 #endif
833
834   return isDone;
835 }
836
837
838 //=============================================================================
839 /*!
840  *
841  */
842 //=============================================================================
843 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
844                                               CORBA::Boolean            Diag13)
845 {
846   initData();
847
848   SMESHDS_Mesh* aMesh = GetMeshDS();
849   TIDSortedElemSet faces;
850   ToMap(IDsOfElements, aMesh, faces, SMDSAbs_Face);
851
852   // Update Python script
853   TPythonDump() << "isDone = " << this << ".SplitQuad( "
854                 << IDsOfElements << ", " << Diag13 << " )";
855 #ifdef _DEBUG_
856   TPythonDump() << "print 'SplitQuad: ', isDone";
857 #endif
858
859   ::SMESH_MeshEditor anEditor( myMesh );
860   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
861
862   StoreResult(anEditor);
863
864   return stat;
865 }
866
867
868 //=============================================================================
869 /*!
870  *
871  */
872 //=============================================================================
873 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
874                                                     CORBA::Boolean            Diag13)
875 {
876   initData();
877
878   SMESH::long_array_var anElementsId = theObject->GetIDs();
879   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
880
881   // Clear python line(s), created by SplitQuad()
882   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
883   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
884 #ifdef _DEBUG_
885   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
886 #endif
887
888   // Update Python script
889   TPythonDump() << "isDone = " << this << ".SplitQuadObject( "
890                 << theObject << ", " << Diag13 << " )";
891 #ifdef _DEBUG_
892   TPythonDump() << "print 'SplitQuadObject: ', isDone";
893 #endif
894
895   return isDone;
896 }
897
898
899 //=============================================================================
900 /*!
901  *  BestSplit
902  */
903 //=============================================================================
904 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
905                                            SMESH::NumericalFunctor_ptr Criterion)
906 {
907   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
908   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
909   {
910     SMESH::NumericalFunctor_i* aNumericalFunctor =
911       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
912     SMESH::Controls::NumericalFunctorPtr aCrit;
913     if (aNumericalFunctor)
914       aCrit = aNumericalFunctor->GetNumericalFunctor();
915     else
916       aCrit.reset(new SMESH::Controls::AspectRatio());
917
918     ::SMESH_MeshEditor anEditor (myMesh);
919     return anEditor.BestSplit(quad, aCrit);
920   }
921   return -1;
922 }
923
924
925 //=======================================================================
926 //function : Smooth
927 //purpose  :
928 //=======================================================================
929
930 CORBA::Boolean
931   SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
932                              const SMESH::long_array &              IDsOfFixedNodes,
933                              CORBA::Long                            MaxNbOfIterations,
934                              CORBA::Double                          MaxAspectRatio,
935                              SMESH::SMESH_MeshEditor::Smooth_Method Method)
936 {
937   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
938                 MaxAspectRatio, Method, false );
939 }
940
941
942 //=======================================================================
943 //function : SmoothParametric
944 //purpose  :
945 //=======================================================================
946
947 CORBA::Boolean
948   SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
949                                        const SMESH::long_array &              IDsOfFixedNodes,
950                                        CORBA::Long                            MaxNbOfIterations,
951                                        CORBA::Double                          MaxAspectRatio,
952                                        SMESH::SMESH_MeshEditor::Smooth_Method Method)
953 {
954   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
955                 MaxAspectRatio, Method, true );
956 }
957
958
959 //=======================================================================
960 //function : SmoothObject
961 //purpose  :
962 //=======================================================================
963
964 CORBA::Boolean
965   SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
966                                    const SMESH::long_array &              IDsOfFixedNodes,
967                                    CORBA::Long                            MaxNbOfIterations,
968                                    CORBA::Double                          MaxAspectRatio,
969                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
970 {
971   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
972                        MaxAspectRatio, Method, false);
973 }
974
975
976 //=======================================================================
977 //function : SmoothParametricObject
978 //purpose  :
979 //=======================================================================
980
981 CORBA::Boolean
982   SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
983                                    const SMESH::long_array &              IDsOfFixedNodes,
984                                    CORBA::Long                            MaxNbOfIterations,
985                                    CORBA::Double                          MaxAspectRatio,
986                                    SMESH::SMESH_MeshEditor::Smooth_Method Method)
987 {
988   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
989                        MaxAspectRatio, Method, true);
990 }
991
992
993 //=============================================================================
994 /*!
995  *
996  */
997 //=============================================================================
998
999 CORBA::Boolean
1000   SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1001                              const SMESH::long_array &              IDsOfFixedNodes,
1002                              CORBA::Long                            MaxNbOfIterations,
1003                              CORBA::Double                          MaxAspectRatio,
1004                              SMESH::SMESH_MeshEditor::Smooth_Method Method,
1005                              bool                                   IsParametric)
1006 {
1007   initData();
1008
1009   SMESHDS_Mesh* aMesh = GetMeshDS();
1010
1011   TIDSortedElemSet elements;
1012   ToMap(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1013
1014   set<const SMDS_MeshNode*> fixedNodes;
1015   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1016     CORBA::Long index = IDsOfFixedNodes[i];
1017     const SMDS_MeshNode * node = aMesh->FindNode(index);
1018     if ( node )
1019       fixedNodes.insert( node );
1020   }
1021   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1022   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1023     method = ::SMESH_MeshEditor::CENTROIDAL;
1024
1025   ::SMESH_MeshEditor anEditor( myMesh );
1026   anEditor.Smooth(elements, fixedNodes, method,
1027                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1028
1029   StoreResult(anEditor);
1030
1031   // Update Python script
1032   TPythonDump() << "isDone = " << this << "."
1033                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1034                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1035                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1036                 << "SMESH.SMESH_MeshEditor."
1037                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1038                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1039 #ifdef _DEBUG_
1040   TPythonDump() << "print 'Smooth: ', isDone";
1041 #endif
1042
1043   return true;
1044 }
1045
1046
1047 //=============================================================================
1048 /*!
1049  *
1050  */
1051 //=============================================================================
1052
1053 CORBA::Boolean
1054 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1055                                  const SMESH::long_array &              IDsOfFixedNodes,
1056                                  CORBA::Long                            MaxNbOfIterations,
1057                                  CORBA::Double                          MaxAspectRatio,
1058                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1059                                  bool                                   IsParametric)
1060 {
1061   initData();
1062
1063   SMESH::long_array_var anElementsId = theObject->GetIDs();
1064   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1065                                   MaxAspectRatio, Method, IsParametric);
1066
1067   // Clear python line(s), created by Smooth()
1068   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1069   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1070 #ifdef _DEBUG_
1071   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1072 #endif
1073
1074   // Update Python script
1075   TPythonDump() << "isDone = " << this << "."
1076                 << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1077                 << theObject << ", " << IDsOfFixedNodes << ", "
1078                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1079                 << "SMESH.SMESH_MeshEditor."
1080                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1081                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1082 #ifdef _DEBUG_
1083   TPythonDump() << "print 'SmoothObject: ', isDone";
1084 #endif
1085
1086   return isDone;
1087 }
1088
1089
1090 //=============================================================================
1091 /*!
1092  *
1093  */
1094 //=============================================================================
1095
1096 void SMESH_MeshEditor_i::RenumberNodes()
1097 {
1098   // Update Python script
1099   TPythonDump() << this << ".RenumberNodes()";
1100
1101   GetMeshDS()->Renumber( true );
1102 }
1103
1104
1105 //=============================================================================
1106 /*!
1107  *
1108  */
1109 //=============================================================================
1110
1111 void SMESH_MeshEditor_i::RenumberElements()
1112 {
1113   // Update Python script
1114   TPythonDump() << this << ".RenumberElements()";
1115
1116   GetMeshDS()->Renumber( false );
1117 }
1118
1119
1120 //=======================================================================
1121 //function : RotationSweep
1122 //purpose  :
1123 //=======================================================================
1124
1125 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1126                                        const SMESH::AxisStruct & theAxis,
1127                                        CORBA::Double             theAngleInRadians,
1128                                        CORBA::Long               theNbOfSteps,
1129                                        CORBA::Double             theTolerance)
1130 {
1131   initData();
1132
1133   TIDSortedElemSet inElements, copyElements;
1134   ToMap(theIDsOfElements, GetMeshDS(), inElements);
1135
1136   TIDSortedElemSet* workElements = & inElements;
1137   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1138   SMESH_Mesh*       mesh = 0;
1139   bool              makeWalls=true;
1140   if ( myPreviewMode )
1141   {
1142     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1143     tmpMesh.Copy( inElements, copyElements, select, avoid );
1144     mesh = &tmpMesh;
1145     workElements = & copyElements;
1146     //makeWalls = false;
1147   }
1148   else
1149   {
1150     mesh = myMesh;
1151   }
1152
1153   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1154               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1155
1156   ::SMESH_MeshEditor anEditor( mesh );
1157   anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1158                           theNbOfSteps, theTolerance, makeWalls);
1159
1160   StoreResult(anEditor);
1161
1162   if ( !myPreviewMode ) {
1163     // Update Python script
1164     TPythonDump() << "axis = " << theAxis;
1165     TPythonDump() << this << ".RotationSweep( "
1166                   << theIDsOfElements
1167                   << ", axis, "
1168                   << theAngleInRadians << ", "
1169                   << theNbOfSteps << ", "
1170                   << theTolerance << " )";
1171   }
1172 }
1173
1174 //=======================================================================
1175 //function : RotationSweepObject
1176 //purpose  :
1177 //=======================================================================
1178
1179 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1180                                              const SMESH::AxisStruct & theAxis,
1181                                              CORBA::Double             theAngleInRadians,
1182                                              CORBA::Long               theNbOfSteps,
1183                                              CORBA::Double             theTolerance)
1184 {
1185   initData();
1186
1187   SMESH::long_array_var anElementsId = theObject->GetIDs();
1188   RotationSweep(anElementsId, theAxis, theAngleInRadians, theNbOfSteps, theTolerance);
1189
1190   // Clear python line, created by RotationSweep()
1191   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1192   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1193
1194   // Update Python script
1195   TPythonDump() << this << ".RotationSweepObject( "
1196                 << theObject
1197                 << ", axis, "
1198                 << theAngleInRadians << ", "
1199                 << theNbOfSteps << ", "
1200                 << theTolerance << " )";
1201 }
1202
1203 //=======================================================================
1204 //function : ExtrusionSweep
1205 //purpose  :
1206 //=======================================================================
1207
1208 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1209                                         const SMESH::DirStruct &  theStepVector,
1210                                         CORBA::Long               theNbOfSteps)
1211 {
1212   initData();
1213
1214 #ifdef NO_CAS_CATCH
1215   try {   
1216     OCC_CATCH_SIGNALS;
1217 #else
1218   CASCatch_TRY {
1219 #endif
1220     SMESHDS_Mesh* aMesh = GetMeshDS();
1221
1222     TIDSortedElemSet elements;
1223     ToMap(theIDsOfElements, aMesh, elements);
1224
1225     const SMESH::PointStruct * P = &theStepVector.PS;
1226     gp_Vec stepVec( P->x, P->y, P->z );
1227
1228     TElemOfElemListMap aHystory;
1229     ::SMESH_MeshEditor anEditor( myMesh );
1230     anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1231
1232     StoreResult(anEditor);
1233
1234     // Update Python script
1235     TPythonDump() << "stepVector = " << theStepVector;
1236     TPythonDump() << this << ".ExtrusionSweep( "
1237                   << theIDsOfElements << ", stepVector, " << theNbOfSteps << " )";
1238
1239 #ifdef NO_CAS_CATCH
1240   } catch(Standard_Failure) {
1241 #else
1242   } CASCatch_CATCH(Standard_Failure) {
1243 #endif
1244     Handle(Standard_Failure) aFail = Standard_Failure::Caught();          
1245     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1246   }
1247 }
1248
1249
1250 //=======================================================================
1251 //function : ExtrusionSweepObject
1252 //purpose  :
1253 //=======================================================================
1254
1255 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1256                                               const SMESH::DirStruct &  theStepVector,
1257                                               CORBA::Long               theNbOfSteps)
1258 {
1259   initData();
1260
1261   SMESH::long_array_var anElementsId = theObject->GetIDs();
1262   ExtrusionSweep(anElementsId, theStepVector, theNbOfSteps);
1263
1264   // Clear python line, created by ExtrusionSweep()
1265   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1266   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1267
1268   // Update Python script
1269   TPythonDump() << this << ".ExtrusionSweepObject( "
1270                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1271 }
1272
1273 //=======================================================================
1274 //function : ExtrusionSweepObject1D
1275 //purpose  :
1276 //=======================================================================
1277
1278 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1279                                                 const SMESH::DirStruct &  theStepVector,
1280                                                 CORBA::Long               theNbOfSteps)
1281 {
1282   initData();
1283
1284   SMESHDS_Mesh* aMesh = GetMeshDS();
1285
1286   SMESH::long_array_var allElementsId = theObject->GetIDs();
1287
1288   TIDSortedElemSet elements;
1289   ToMap(allElementsId, aMesh, elements);
1290
1291   const SMESH::PointStruct * P = &theStepVector.PS;
1292   gp_Vec stepVec( P->x, P->y, P->z );
1293
1294   ::SMESH_MeshEditor anEditor( myMesh );
1295   //anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps);
1296   TElemOfElemListMap aHystory;
1297   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1298
1299   StoreResult(anEditor);
1300
1301   // Update Python script
1302   TPythonDump() << "stepVector = " << theStepVector;
1303   TPythonDump() << this << ".ExtrusionSweepObject1D( "
1304                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1305 }
1306
1307 //=======================================================================
1308 //function : ExtrusionSweepObject2D
1309 //purpose  :
1310 //=======================================================================
1311
1312 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1313                                                 const SMESH::DirStruct &  theStepVector,
1314                                                 CORBA::Long               theNbOfSteps)
1315 {
1316   initData();
1317
1318   SMESHDS_Mesh* aMesh = GetMeshDS();
1319
1320   SMESH::long_array_var allElementsId = theObject->GetIDs();
1321
1322   TIDSortedElemSet elements;
1323   ToMap(allElementsId, aMesh, elements);
1324
1325   const SMESH::PointStruct * P = &theStepVector.PS;
1326   gp_Vec stepVec( P->x, P->y, P->z );
1327
1328   ::SMESH_MeshEditor anEditor( myMesh );
1329   //anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps);
1330   TElemOfElemListMap aHystory;
1331   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory);
1332
1333   StoreResult(anEditor);
1334
1335   // Update Python script
1336   TPythonDump() << "stepVector = " << theStepVector;
1337   TPythonDump() << this << ".ExtrusionSweepObject2D( "
1338                 << theObject << ", stepVector, " << theNbOfSteps << " )";
1339 }
1340
1341
1342 //=======================================================================
1343 //function : AdvancedExtrusion
1344 //purpose  :
1345 //=======================================================================
1346
1347 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
1348                                            const SMESH::DirStruct &  theStepVector,
1349                                            CORBA::Long               theNbOfSteps,
1350                                            CORBA::Long               theExtrFlags,
1351                                            CORBA::Double             theSewTolerance)
1352 {
1353   initData();
1354
1355   SMESHDS_Mesh* aMesh = GetMeshDS();
1356
1357   TIDSortedElemSet elements;
1358   ToMap(theIDsOfElements, aMesh, elements);
1359
1360   const SMESH::PointStruct * P = &theStepVector.PS;
1361   gp_Vec stepVec( P->x, P->y, P->z );
1362
1363   ::SMESH_MeshEditor anEditor( myMesh );
1364   TElemOfElemListMap aHystory;
1365   anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
1366                            theExtrFlags, theSewTolerance);
1367
1368   StoreResult(anEditor);
1369
1370   // Update Python script
1371   TPythonDump() << "stepVector = " << theStepVector;
1372   TPythonDump() << this << ".AdvancedExtrusion("
1373                 << theIDsOfElements
1374                 << ", stepVector, "
1375                 << theNbOfSteps << ","
1376                 << theExtrFlags << ", "
1377                 << theSewTolerance <<  " )";
1378 }
1379
1380
1381 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
1382
1383 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
1384 {
1385   switch ( e ) {
1386   RETCASE( EXTR_OK );
1387   RETCASE( EXTR_NO_ELEMENTS );
1388   RETCASE( EXTR_PATH_NOT_EDGE );
1389   RETCASE( EXTR_BAD_PATH_SHAPE );
1390   RETCASE( EXTR_BAD_STARTING_NODE );
1391   RETCASE( EXTR_BAD_ANGLES_NUMBER );
1392   RETCASE( EXTR_CANT_GET_TANGENT );
1393   }
1394   return SMESH::SMESH_MeshEditor::EXTR_OK;
1395 }
1396
1397 //=======================================================================
1398 //function : ExtrusionAlongPath
1399 //purpose  :
1400 //=======================================================================
1401
1402 SMESH::SMESH_MeshEditor::Extrusion_Error
1403   SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
1404                                          SMESH::SMESH_Mesh_ptr       thePathMesh,
1405                                          GEOM::GEOM_Object_ptr       thePathShape,
1406                                          CORBA::Long                 theNodeStart,
1407                                          CORBA::Boolean              theHasAngles,
1408                                          const SMESH::double_array & theAngles,
1409                                          CORBA::Boolean              theHasRefPoint,
1410                                          const SMESH::PointStruct &  theRefPoint)
1411 {
1412   initData();
1413
1414   SMESHDS_Mesh*  aMesh = GetMeshDS();
1415
1416   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() )
1417     return SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1418
1419   SMESH_Mesh_i* aMeshImp = dynamic_cast<SMESH_Mesh_i*>( SMESH_Gen_i::GetServant( thePathMesh ).in() );
1420   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
1421   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
1422
1423   if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
1424     return SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
1425
1426   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
1427   if ( !nodeStart )
1428     return SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
1429
1430   TIDSortedElemSet elements;
1431   ToMap(theIDsOfElements, aMesh, elements);
1432
1433   list<double> angles;
1434   for (int i = 0; i < theAngles.length(); i++) {
1435     angles.push_back( theAngles[i] );
1436   }
1437
1438   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
1439
1440   // Update Python script
1441   TPythonDump() << "rotAngles = " << theAngles;
1442
1443   if ( theHasRefPoint )
1444     TPythonDump() << "refPoint = SMESH.PointStruct( "
1445                   << refPnt.X() << ", "
1446                   << refPnt.Y() << ", "
1447                   << refPnt.Z() << " )";
1448   else
1449     TPythonDump() << "refPoint = SMESH.PointStruct( 0,0,0 )";
1450
1451   TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
1452                 << theIDsOfElements << ", "
1453                 << thePathMesh      << ", "
1454                 << thePathShape     << ", "
1455                 << theNodeStart     << ", "
1456                 << theHasAngles     << ", "
1457                 << "rotAngles"      << ", "
1458                 << theHasRefPoint   << ", refPoint )";
1459
1460   ::SMESH_MeshEditor anEditor( myMesh );
1461   SMESH::SMESH_MeshEditor::Extrusion_Error error = 
1462     convExtrError( anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
1463                                                 theHasAngles, angles,
1464                                                 theHasRefPoint, refPnt ) );
1465
1466   StoreResult(anEditor);
1467
1468   return error;
1469 }
1470
1471 //=======================================================================
1472 //function : ExtrusionAlongPathObject
1473 //purpose  :
1474 //=======================================================================
1475
1476 SMESH::SMESH_MeshEditor::Extrusion_Error
1477 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
1478                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
1479                                              GEOM::GEOM_Object_ptr       thePathShape,
1480                                              CORBA::Long                 theNodeStart,
1481                                              CORBA::Boolean              theHasAngles,
1482                                              const SMESH::double_array & theAngles,
1483                                              CORBA::Boolean              theHasRefPoint,
1484                                              const SMESH::PointStruct &  theRefPoint)
1485 {
1486   initData();
1487
1488   SMESH::long_array_var anElementsId = theObject->GetIDs();
1489   SMESH::SMESH_MeshEditor::Extrusion_Error error = ExtrusionAlongPath
1490     (anElementsId, thePathMesh, thePathShape, theNodeStart,
1491      theHasAngles, theAngles, theHasRefPoint, theRefPoint);
1492
1493   // Clear python line, created by ExtrusionAlongPath()
1494   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1495   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1496
1497   // Update Python script
1498   TPythonDump() << "rotAngles = " << theAngles;
1499   TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
1500                 << theObject    << ", "
1501                 << thePathMesh  << ", "
1502                 << thePathShape << ", "
1503                 << theNodeStart << ", "
1504                 << theHasAngles << ", "
1505                 << "rotAngles"     << ", "
1506                 << theHasRefPoint<<", refPoint )";
1507
1508   return error;
1509 }
1510
1511 //================================================================================
1512 /*!
1513  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
1514  * of given angles along path steps
1515   * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
1516   *                which proceeds the extrusion
1517   * \param PathShape is shape(edge); as the mesh can be complex, the edge 
1518   *                 is used to define the sub-mesh for the path
1519  */
1520 //================================================================================
1521
1522 SMESH::double_array*
1523 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
1524                                           GEOM::GEOM_Object_ptr       thePathShape,
1525                                           const SMESH::double_array & theAngles)
1526 {
1527   SMESH::double_array_var aResult = new SMESH::double_array();
1528   return aResult._retn();
1529 }
1530
1531 //=======================================================================
1532 //function : Mirror
1533 //purpose  :
1534 //=======================================================================
1535
1536 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
1537                                 const SMESH::AxisStruct &           theAxis,
1538                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
1539                                 CORBA::Boolean                      theCopy)
1540 {
1541   initData();
1542
1543   SMESHDS_Mesh* aMesh = GetMeshDS();
1544
1545   TIDSortedElemSet elements;
1546   ToMap(theIDsOfElements, aMesh, elements);
1547
1548   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
1549   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
1550
1551   gp_Trsf aTrsf;
1552   TCollection_AsciiString typeStr;
1553   switch ( theMirrorType ) {
1554   case  SMESH::SMESH_MeshEditor::POINT:
1555     aTrsf.SetMirror( P );
1556     typeStr = "SMESH.SMESH_MeshEditor.POINT";
1557     break;
1558   case  SMESH::SMESH_MeshEditor::AXIS:
1559     aTrsf.SetMirror( gp_Ax1( P, V ));
1560     typeStr = "SMESH.SMESH_MeshEditor.AXIS";
1561     break;
1562   default:
1563     aTrsf.SetMirror( gp_Ax2( P, V ));
1564     typeStr = "SMESH.SMESH_MeshEditor.PLANE";
1565   }
1566
1567   // Update Python script
1568   TPythonDump() << this << ".Mirror( "
1569                 << theIDsOfElements << ", "
1570                 << theAxis           << ", "
1571                 << typeStr           << ", "
1572                 << theCopy           << " )";
1573
1574   ::SMESH_MeshEditor anEditor( myMesh );
1575   anEditor.Transform (elements, aTrsf, theCopy);
1576
1577   if(theCopy) {
1578     StoreResult(anEditor);
1579   }
1580 }
1581
1582
1583 //=======================================================================
1584 //function : MirrorObject
1585 //purpose  :
1586 //=======================================================================
1587
1588 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
1589                                       const SMESH::AxisStruct &           theAxis,
1590                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
1591                                       CORBA::Boolean                      theCopy)
1592 {
1593   initData();
1594
1595   SMESH::long_array_var anElementsId = theObject->GetIDs();
1596   Mirror(anElementsId, theAxis, theMirrorType, theCopy);
1597
1598   // Clear python line, created by Mirror()
1599   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1600   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1601
1602   // Update Python script
1603   TCollection_AsciiString typeStr;
1604   switch ( theMirrorType ) {
1605   case  SMESH::SMESH_MeshEditor::POINT:
1606     typeStr = "SMESH.SMESH_MeshEditor.POINT";
1607     break;
1608   case  SMESH::SMESH_MeshEditor::AXIS:
1609     typeStr = "SMESH.SMESH_MeshEditor.AXIS";
1610     break;
1611   default:
1612     typeStr = "SMESH.SMESH_MeshEditor.PLANE";
1613   }
1614   TPythonDump() << "axis = " << theAxis;
1615   TPythonDump() << this << ".MirrorObject( "
1616                 << theObject << ", "
1617                 << "axis, "
1618                 << typeStr << ", "
1619                 << theCopy << " )";
1620 }
1621
1622 //=======================================================================
1623 //function : Translate
1624 //purpose  :
1625 //=======================================================================
1626
1627 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
1628                                    const SMESH::DirStruct &  theVector,
1629                                    CORBA::Boolean            theCopy)
1630 {
1631   initData();
1632
1633   SMESHDS_Mesh* aMesh = GetMeshDS();
1634
1635   TIDSortedElemSet elements;
1636   ToMap(theIDsOfElements, aMesh, elements);
1637
1638   gp_Trsf aTrsf;
1639   const SMESH::PointStruct * P = &theVector.PS;
1640   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
1641
1642   ::SMESH_MeshEditor anEditor( myMesh );
1643   anEditor.Transform (elements, aTrsf, theCopy);
1644
1645   if(theCopy) {
1646     StoreResult(anEditor);
1647   }
1648
1649   // Update Python script
1650   TPythonDump() << "vector = " << theVector;
1651   TPythonDump() << this << ".Translate( "
1652                 << theIDsOfElements
1653                 << ", vector, "
1654                 << theCopy << " )";
1655 }
1656
1657 //=======================================================================
1658 //function : TranslateObject
1659 //purpose  :
1660 //=======================================================================
1661
1662 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
1663                                          const SMESH::DirStruct &  theVector,
1664                                          CORBA::Boolean            theCopy)
1665 {
1666   initData();
1667
1668   SMESH::long_array_var anElementsId = theObject->GetIDs();
1669   Translate(anElementsId, theVector, theCopy);
1670
1671   // Clear python line, created by Translate()
1672   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1673   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1674
1675   // Update Python script
1676   TPythonDump() << this << ".TranslateObject( "
1677                 << theObject
1678                 << ", vector, "
1679                 << theCopy << " )";
1680 }
1681
1682 //=======================================================================
1683 //function : Rotate
1684 //purpose  :
1685 //=======================================================================
1686
1687 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
1688                                 const SMESH::AxisStruct & theAxis,
1689                                 CORBA::Double             theAngle,
1690                                 CORBA::Boolean            theCopy)
1691 {
1692   initData();
1693
1694   SMESHDS_Mesh* aMesh = GetMeshDS();
1695
1696   TIDSortedElemSet elements;
1697   ToMap(theIDsOfElements, aMesh, elements);
1698
1699   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
1700   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
1701
1702   gp_Trsf aTrsf;
1703   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
1704
1705   ::SMESH_MeshEditor anEditor( myMesh );
1706   anEditor.Transform (elements, aTrsf, theCopy);
1707
1708   if(theCopy) {
1709     StoreResult(anEditor);
1710   }
1711
1712   // Update Python script
1713   TPythonDump() << "axis = " << theAxis;
1714   TPythonDump() << this << ".Rotate( "
1715                 << theIDsOfElements
1716                 << ", axis, "
1717                 << theAngle << ", "
1718                 << theCopy << " )";
1719 }
1720
1721 //=======================================================================
1722 //function : RotateObject
1723 //purpose  :
1724 //=======================================================================
1725
1726 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
1727                                       const SMESH::AxisStruct & theAxis,
1728                                       CORBA::Double             theAngle,
1729                                       CORBA::Boolean            theCopy)
1730 {
1731   initData();
1732
1733   SMESH::long_array_var anElementsId = theObject->GetIDs();
1734   Rotate(anElementsId, theAxis, theAngle, theCopy);
1735
1736   // Clear python line, created by Rotate()
1737   SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
1738   aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
1739
1740   // Update Python script
1741   TPythonDump() << this << ".RotateObject( "
1742                 << theObject
1743                 << ", axis, "
1744                 << theAngle << ", "
1745                 << theCopy << " )";
1746 }
1747
1748 //=======================================================================
1749 //function : FindCoincidentNodes
1750 //purpose  :
1751 //=======================================================================
1752
1753 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
1754                                               SMESH::array_of_long_array_out GroupsOfNodes)
1755 {
1756   initData();
1757
1758   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1759   ::SMESH_MeshEditor anEditor( myMesh );
1760   set<const SMDS_MeshNode*> nodes; // no input nodes
1761   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
1762
1763   GroupsOfNodes = new SMESH::array_of_long_array;
1764   GroupsOfNodes->length( aListOfListOfNodes.size() );
1765   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
1766   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
1767     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
1768     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
1769     SMESH::long_array& aGroup = GroupsOfNodes[ i ];
1770     aGroup.length( aListOfNodes.size() );
1771     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
1772       aGroup[ j ] = (*lIt)->GetID();
1773   }
1774   // Update Python script
1775   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
1776                 << Tolerance << " )";
1777 }
1778
1779 //=======================================================================
1780 //function : FindCoincidentNodesOnPart
1781 //purpose  :
1782 //=======================================================================
1783 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
1784                                                    CORBA::Double                  Tolerance,
1785                                                    SMESH::array_of_long_array_out GroupsOfNodes)
1786 {
1787   initData();
1788   SMESH::long_array_var aElementsId = theObject->GetIDs();
1789
1790   SMESHDS_Mesh* aMesh = GetMeshDS();
1791   set<const SMDS_MeshNode*> nodes;
1792
1793   if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
1794       SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) {
1795     for(int i = 0; i < aElementsId->length(); i++) {
1796       CORBA::Long ind = aElementsId[i];
1797       const SMDS_MeshNode * elem = aMesh->FindNode(ind);
1798       if(elem)
1799         nodes.insert(elem);
1800     }
1801   }
1802   else {
1803     for(int i = 0; i < aElementsId->length(); i++) {
1804       CORBA::Long ind = aElementsId[i];
1805       const SMDS_MeshElement * elem = aMesh->FindElement(ind);
1806       if(elem) {
1807         SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
1808         while ( nIt->more() )
1809           nodes.insert( nodes.end(),static_cast<const SMDS_MeshNode*>(nIt->next()));
1810       }
1811     }
1812   }
1813     
1814   
1815   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1816   ::SMESH_MeshEditor anEditor( myMesh );
1817   if(!nodes.empty())
1818     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
1819   
1820   GroupsOfNodes = new SMESH::array_of_long_array;
1821   GroupsOfNodes->length( aListOfListOfNodes.size() );
1822   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
1823   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
1824     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
1825     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
1826     SMESH::long_array& aGroup = GroupsOfNodes[ i ];
1827     aGroup.length( aListOfNodes.size() );
1828     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
1829       aGroup[ j ] = (*lIt)->GetID();
1830   }
1831   // Update Python script
1832   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
1833                 <<theObject<<", "
1834                 << Tolerance << " )";
1835 }
1836
1837 //=======================================================================
1838 //function : MergeNodes
1839 //purpose  :
1840 //=======================================================================
1841
1842 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
1843 {
1844   initData();
1845
1846   SMESHDS_Mesh* aMesh = GetMeshDS();
1847
1848   TPythonDump aTPythonDump;
1849   aTPythonDump << this << ".MergeNodes([";
1850   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
1851   for (int i = 0; i < GroupsOfNodes.length(); i++)
1852   {
1853     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
1854     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
1855     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
1856     for ( int j = 0; j < aNodeGroup.length(); j++ )
1857     {
1858       CORBA::Long index = aNodeGroup[ j ];
1859       const SMDS_MeshNode * node = aMesh->FindNode(index);
1860       if ( node )
1861         aListOfNodes.push_back( node );
1862     }
1863     if ( aListOfNodes.size() < 2 )
1864       aListOfListOfNodes.pop_back();
1865
1866     if ( i > 0 ) aTPythonDump << ", ";
1867     aTPythonDump << aNodeGroup;
1868   }
1869   ::SMESH_MeshEditor anEditor( myMesh );
1870   anEditor.MergeNodes( aListOfListOfNodes );
1871
1872   // Update Python script
1873   aTPythonDump <<  "])";
1874 }
1875
1876 //=======================================================================
1877 //function : MergeEqualElements
1878 //purpose  :
1879 //=======================================================================
1880
1881 void SMESH_MeshEditor_i::MergeEqualElements()
1882 {
1883   initData();
1884
1885   ::SMESH_MeshEditor anEditor( myMesh );
1886   anEditor.MergeEqualElements();
1887
1888   // Update Python script
1889   TPythonDump() << this << ".MergeEqualElements()";
1890 }
1891
1892 //================================================================================
1893 /*!
1894  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
1895  * move the node closest to the point to point's location and return ID of the node
1896  */
1897 //================================================================================
1898
1899 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
1900                                                        CORBA::Double y,
1901                                                        CORBA::Double z,
1902                                                        CORBA::Long   theNodeID)
1903 {
1904   // We keep myNodeSearcher until any mesh modification:
1905   // 1) initData() deletes myNodeSearcher at any edition,
1906   // 2) TNodeSearcherDeleter - at any mesh compute event
1907
1908   initData();
1909
1910   int nodeID = theNodeID;
1911   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
1912   if ( !node )
1913   {
1914     if ( !myNodeSearcher ) {
1915       ::SMESH_MeshEditor anEditor( myMesh );
1916       myNodeSearcher = anEditor.GetNodeSearcher();
1917       static TNodeSearcherDeleter deleter;
1918       deleter.Set( myMesh );
1919     }
1920     gp_Pnt p( x,y,z );
1921     node = myNodeSearcher->FindClosestTo( p );
1922   }
1923   if ( node ) {
1924     nodeID = node->GetID();
1925     if ( myPreviewMode ) // make preview data
1926     {
1927       // in a preview mesh, make edges linked to a node
1928       TPreviewMesh tmpMesh;
1929       TIDSortedElemSet linkedNodes;
1930       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
1931       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
1932       for ( ; nIt != linkedNodes.end(); ++nIt )
1933       {
1934         SMDS_MeshEdge edge( node, cast2Node( *nIt ));
1935         tmpMesh.Copy( &edge );
1936       }
1937       // move copied node
1938       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
1939       if ( node )
1940         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
1941       // fill preview data
1942       ::SMESH_MeshEditor anEditor( & tmpMesh );
1943       StoreResult( anEditor );
1944     }
1945     else
1946     {
1947       GetMeshDS()->MoveNode(node, x, y, z);
1948     }
1949   }
1950
1951   if ( !myPreviewMode ) {
1952     // Update Python script
1953     TPythonDump() << "nodeID = " << this
1954                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z << " )";
1955   }
1956
1957   return nodeID;
1958 }
1959
1960 //=======================================================================
1961 //function : convError
1962 //purpose  :
1963 //=======================================================================
1964
1965 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
1966
1967 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
1968 {
1969   switch ( e ) {
1970   RETCASE( SEW_OK );
1971   RETCASE( SEW_BORDER1_NOT_FOUND );
1972   RETCASE( SEW_BORDER2_NOT_FOUND );
1973   RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
1974   RETCASE( SEW_BAD_SIDE_NODES );
1975   RETCASE( SEW_VOLUMES_TO_SPLIT );
1976   RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
1977   RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
1978   RETCASE( SEW_BAD_SIDE1_NODES );
1979   RETCASE( SEW_BAD_SIDE2_NODES );
1980   }
1981   return SMESH::SMESH_MeshEditor::SEW_OK;
1982 }
1983
1984 //=======================================================================
1985 //function : SewFreeBorders
1986 //purpose  :
1987 //=======================================================================
1988
1989 SMESH::SMESH_MeshEditor::Sew_Error
1990   SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
1991                                      CORBA::Long SecondNodeID1,
1992                                      CORBA::Long LastNodeID1,
1993                                      CORBA::Long FirstNodeID2,
1994                                      CORBA::Long SecondNodeID2,
1995                                      CORBA::Long LastNodeID2,
1996                                      CORBA::Boolean CreatePolygons,
1997                                      CORBA::Boolean CreatePolyedrs)
1998 {
1999   initData();
2000
2001   SMESHDS_Mesh* aMesh = GetMeshDS();
2002
2003   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
2004   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
2005   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
2006   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
2007   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
2008   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
2009
2010   if (!aBorderFirstNode ||
2011       !aBorderSecondNode||
2012       !aBorderLastNode)
2013     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2014   if (!aSide2FirstNode  ||
2015       !aSide2SecondNode ||
2016       !aSide2ThirdNode)
2017     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
2018
2019   // Update Python script
2020   TPythonDump() << "error = " << this << ".SewFreeBorders( "
2021                 << FirstNodeID1  << ", "
2022                 << SecondNodeID1 << ", "
2023                 << LastNodeID1   << ", "
2024                 << FirstNodeID2  << ", "
2025                 << SecondNodeID2 << ", "
2026                 << LastNodeID2   << ", "
2027                 << CreatePolygons<< ", "
2028                 << CreatePolyedrs<< " )";
2029
2030   ::SMESH_MeshEditor anEditor( myMesh );
2031   SMESH::SMESH_MeshEditor::Sew_Error error =
2032     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2033                                        aBorderSecondNode,
2034                                        aBorderLastNode,
2035                                        aSide2FirstNode,
2036                                        aSide2SecondNode,
2037                                        aSide2ThirdNode,
2038                                        true,
2039                                        CreatePolygons,
2040                                        CreatePolyedrs) );
2041
2042   StoreResult(anEditor);
2043
2044   return error;
2045 }
2046
2047
2048 //=======================================================================
2049 //function : SewConformFreeBorders
2050 //purpose  :
2051 //=======================================================================
2052
2053 SMESH::SMESH_MeshEditor::Sew_Error
2054 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
2055                                           CORBA::Long SecondNodeID1,
2056                                           CORBA::Long LastNodeID1,
2057                                           CORBA::Long FirstNodeID2,
2058                                           CORBA::Long SecondNodeID2)
2059 {
2060   initData();
2061
2062   SMESHDS_Mesh* aMesh = GetMeshDS();
2063
2064   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
2065   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
2066   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
2067   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
2068   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
2069   const SMDS_MeshNode* aSide2ThirdNode   = 0;
2070
2071   if (!aBorderFirstNode ||
2072       !aBorderSecondNode||
2073       !aBorderLastNode )
2074     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2075   if (!aSide2FirstNode  ||
2076       !aSide2SecondNode)
2077     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
2078
2079   // Update Python script
2080   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
2081                 << FirstNodeID1  << ", "
2082                 << SecondNodeID1 << ", "
2083                 << LastNodeID1   << ", "
2084                 << FirstNodeID2  << ", "
2085                 << SecondNodeID2 << " )";
2086
2087   ::SMESH_MeshEditor anEditor( myMesh );
2088   SMESH::SMESH_MeshEditor::Sew_Error error =
2089     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2090                                        aBorderSecondNode,
2091                                        aBorderLastNode,
2092                                        aSide2FirstNode,
2093                                        aSide2SecondNode,
2094                                        aSide2ThirdNode,
2095                                        true,
2096                                        false, false) );
2097
2098   StoreResult(anEditor);
2099
2100   return error;
2101 }
2102
2103
2104 //=======================================================================
2105 //function : SewBorderToSide
2106 //purpose  :
2107 //=======================================================================
2108
2109 SMESH::SMESH_MeshEditor::Sew_Error
2110 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
2111                                     CORBA::Long SecondNodeIDOnFreeBorder,
2112                                     CORBA::Long LastNodeIDOnFreeBorder,
2113                                     CORBA::Long FirstNodeIDOnSide,
2114                                     CORBA::Long LastNodeIDOnSide,
2115                                     CORBA::Boolean CreatePolygons,
2116                                     CORBA::Boolean CreatePolyedrs)
2117 {
2118   initData();
2119
2120   SMESHDS_Mesh* aMesh = GetMeshDS();
2121
2122   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
2123   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
2124   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
2125   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
2126   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
2127   const SMDS_MeshNode* aSide2ThirdNode   = 0;
2128
2129   if (!aBorderFirstNode ||
2130       !aBorderSecondNode||
2131       !aBorderLastNode  )
2132     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
2133   if (!aSide2FirstNode  ||
2134       !aSide2SecondNode)
2135     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
2136
2137   // Update Python script
2138   TPythonDump() << "error = " << this << ".SewBorderToSide( "
2139                 << FirstNodeIDOnFreeBorder  << ", "
2140                 << SecondNodeIDOnFreeBorder << ", "
2141                 << LastNodeIDOnFreeBorder   << ", "
2142                 << FirstNodeIDOnSide        << ", "
2143                 << LastNodeIDOnSide         << ", "
2144                 << CreatePolygons           << ", "
2145                 << CreatePolyedrs           << ") ";
2146
2147   ::SMESH_MeshEditor anEditor( myMesh );
2148   SMESH::SMESH_MeshEditor::Sew_Error error =
2149     convError( anEditor.SewFreeBorder (aBorderFirstNode,
2150                                        aBorderSecondNode,
2151                                        aBorderLastNode,
2152                                        aSide2FirstNode,
2153                                        aSide2SecondNode,
2154                                        aSide2ThirdNode,
2155                                        false,
2156                                        CreatePolygons,
2157                                        CreatePolyedrs) );
2158
2159   StoreResult(anEditor);
2160
2161   return error;
2162 }
2163
2164
2165 //=======================================================================
2166 //function : SewSideElements
2167 //purpose  :
2168 //=======================================================================
2169
2170 SMESH::SMESH_MeshEditor::Sew_Error
2171 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
2172                                     const SMESH::long_array& IDsOfSide2Elements,
2173                                     CORBA::Long NodeID1OfSide1ToMerge,
2174                                     CORBA::Long NodeID1OfSide2ToMerge,
2175                                     CORBA::Long NodeID2OfSide1ToMerge,
2176                                     CORBA::Long NodeID2OfSide2ToMerge)
2177 {
2178   initData();
2179
2180   SMESHDS_Mesh* aMesh = GetMeshDS();
2181
2182   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
2183   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
2184   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
2185   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
2186
2187   if (!aFirstNode1ToMerge ||
2188       !aFirstNode2ToMerge )
2189     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
2190   if (!aSecondNode1ToMerge||
2191       !aSecondNode2ToMerge)
2192     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
2193
2194   TIDSortedElemSet aSide1Elems, aSide2Elems;
2195   ToMap(IDsOfSide1Elements, aMesh, aSide1Elems);
2196   ToMap(IDsOfSide2Elements, aMesh, aSide2Elems);
2197
2198   // Update Python script
2199   TPythonDump() << "error = " << this << ".SewSideElements( "
2200                 << IDsOfSide1Elements << ", "
2201                 << IDsOfSide2Elements << ", "
2202                 << NodeID1OfSide1ToMerge << ", "
2203                 << NodeID1OfSide2ToMerge << ", "
2204                 << NodeID2OfSide1ToMerge << ", "
2205                 << NodeID2OfSide2ToMerge << ")";
2206
2207   ::SMESH_MeshEditor anEditor( myMesh );
2208   SMESH::SMESH_MeshEditor::Sew_Error error =
2209     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
2210                                          aFirstNode1ToMerge,
2211                                          aFirstNode2ToMerge,
2212                                          aSecondNode1ToMerge,
2213                                          aSecondNode2ToMerge));
2214
2215   StoreResult(anEditor);
2216
2217   return error;
2218 }
2219
2220 //================================================================================
2221 /*!
2222  * \brief Set new nodes for given element
2223   * \param ide - element id
2224   * \param newIDs - new node ids
2225   * \retval CORBA::Boolean - true if result is OK
2226  */
2227 //================================================================================
2228
2229 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
2230                                                    const SMESH::long_array& newIDs)
2231 {
2232   initData();
2233
2234   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
2235   if(!elem) return false;
2236
2237   int nbn = newIDs.length();
2238   int i=0;
2239   const SMDS_MeshNode* aNodes [nbn];
2240   int nbn1=-1;
2241   for(; i<nbn; i++) {
2242     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
2243     if(aNode) {
2244       nbn1++;
2245       aNodes[nbn1] = aNode;
2246     }
2247   }
2248   // Update Python script
2249   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
2250                 << ide << ", " << newIDs << " )";
2251 #ifdef _DEBUG_
2252   TPythonDump() << "print 'ChangeElemNodes: ', isDone";
2253 #endif
2254
2255   return GetMeshDS()->ChangeElementNodes( elem, aNodes, nbn1+1 );
2256 }
2257   
2258 //================================================================================
2259 /*!
2260  * \brief Update myLastCreated* or myPreviewData
2261   * \param anEditor - it contains last modification results
2262  */
2263 //================================================================================
2264
2265 void SMESH_MeshEditor_i::StoreResult(::SMESH_MeshEditor& anEditor)
2266 {
2267   if ( myPreviewMode ) { // --- MeshPreviewStruct filling --- 
2268
2269     list<int> aNodesConnectivity;
2270     typedef map<int, int> TNodesMap;
2271     TNodesMap nodesMap;
2272
2273     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
2274     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
2275
2276     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
2277     int nbEdges = aMeshDS->NbEdges();
2278     int nbFaces = aMeshDS->NbFaces();
2279     int nbVolum = aMeshDS->NbVolumes();
2280     switch ( previewType ) {
2281     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
2282     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
2283     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
2284     default:;
2285     }
2286     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
2287     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
2288     int i = 0, j = 0;
2289     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
2290
2291     while ( itMeshElems->more() ) {
2292       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
2293       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
2294         continue;
2295
2296       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
2297       while ( itElemNodes->more() ) {
2298         const SMDS_MeshNode* aMeshNode = 
2299           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
2300         int aNodeID = aMeshNode->GetID();
2301         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
2302         if ( anIter == nodesMap.end() ) {
2303           // filling the nodes coordinates
2304           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
2305           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
2306           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
2307           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
2308           j++;
2309         }
2310         aNodesConnectivity.push_back(anIter->second);
2311       }
2312
2313       // filling the elements types
2314       SMDSAbs_ElementType aType;
2315       bool isPoly;
2316       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
2317         aType = SMDSAbs_Node;
2318         isPoly = false;
2319       }
2320       else*/ {
2321         aType = aMeshElem->GetType();
2322         isPoly = aMeshElem->IsPoly();
2323       }
2324
2325       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
2326       myPreviewData->elementTypes[i].isPoly = isPoly;
2327       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
2328       i++;
2329
2330     }
2331     myPreviewData->nodesXYZ.length( j );
2332
2333     // filling the elements connectivities
2334     list<int>::iterator aConnIter = aNodesConnectivity.begin();
2335     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
2336     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
2337       myPreviewData->elementConnectivities[i] = *aConnIter;
2338     
2339     return;
2340   }
2341
2342   {
2343     // add new nodes into myLastCreatedNodes
2344     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
2345     myLastCreatedNodes->length(aSeq.Length());
2346     for(int i=0; i<aSeq.Length(); i++)
2347       myLastCreatedNodes[i] = aSeq.Value(i+1)->GetID();
2348   }
2349   {
2350     // add new elements into myLastCreatedElems
2351     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
2352     myLastCreatedElems->length(aSeq.Length());
2353     for(int i=0; i<aSeq.Length(); i++)
2354       myLastCreatedElems[i] = aSeq.Value(i+1)->GetID();
2355   }
2356 }
2357
2358 //================================================================================
2359 /*!
2360  * Return data of mesh edition preview
2361  */
2362 //================================================================================
2363
2364 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
2365 {
2366   return myPreviewData._retn();
2367 }
2368
2369 //================================================================================
2370 /*!
2371  * \brief Returns list of it's IDs of created nodes
2372   * \retval SMESH::long_array* - list of node ID
2373  */
2374 //================================================================================
2375
2376 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
2377 {
2378   return myLastCreatedNodes._retn();
2379 }
2380
2381 //================================================================================
2382 /*!
2383  * \brief Returns list of it's IDs of created elements
2384   * \retval SMESH::long_array* - list of elements' ID
2385  */
2386 //================================================================================
2387
2388 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
2389 {
2390   return myLastCreatedElems._retn();
2391 }
2392
2393 //=======================================================================
2394 //function : ConvertToQuadratic
2395 //purpose  :
2396 //=======================================================================
2397
2398 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
2399 {
2400   ::SMESH_MeshEditor anEditor( myMesh );
2401   anEditor.ConvertToQuadratic(theForce3d);
2402  // Update Python script
2403   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
2404 }
2405
2406 //=======================================================================
2407 //function : ConvertFromQuadratic
2408 //purpose  :
2409 //=======================================================================
2410
2411 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
2412 {
2413   ::SMESH_MeshEditor anEditor( myMesh );
2414   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
2415   // Update Python script
2416   TPythonDump() << this << ".ConvertFromQuadratic()";
2417   return isDone;
2418 }