Salome HOME
0021208: Performance issue when loading SMESH with an hdf file containing a big mesh
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_MeshEditor_i.cxx
23 //  Author : Nicolas REJNERI
24 //  Module : SMESH
25
26 #ifdef WNT
27 #define NOMINMAX
28 #endif
29
30 #include "SMESH_MeshEditor_i.hxx"
31
32 #include "SMDS_LinearEdge.hxx"
33 #include "SMDS_Mesh0DElement.hxx"
34 #include "SMDS_MeshFace.hxx"
35 #include "SMDS_MeshVolume.hxx"
36 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
37 #include "SMDS_SetIterator.hxx"
38 #include "SMESHDS_Group.hxx"
39 #include "SMESH_ControlsDef.hxx"
40 #include "SMESH_Filter_i.hxx"
41 #include "SMESH_Gen_i.hxx"
42 #include "SMESH_Group_i.hxx"
43 #include "SMESH_PythonDump.hxx"
44 #include "SMESH_subMeshEventListener.hxx"
45 #include "SMESH_subMesh_i.hxx"
46
47 #include "utilities.h"
48 #include "Utils_ExceptHandlers.hxx"
49 #include "Utils_CorbaException.hxx"
50
51 #include <BRepAdaptor_Surface.hxx>
52 #include <BRep_Tool.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Face.hxx>
57 #include <gp_Ax1.hxx>
58 #include <gp_Ax2.hxx>
59 #include <gp_Vec.hxx>
60
61 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
62 #define NO_CAS_CATCH
63 #endif
64
65 #include <Standard_Failure.hxx>
66
67 #ifdef NO_CAS_CATCH
68 #include <Standard_ErrorHandler.hxx>
69 #endif
70
71 #include <sstream>
72 #include <limits>
73
74 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
75
76 using namespace std;
77 using SMESH::TPythonDump;
78
79 namespace {
80
81   //=============================================================================
82   /*!
83    * \brief Mesh to apply modifications for preview purposes
84    */
85   //=============================================================================
86
87   struct TPreviewMesh: public SMESH_Mesh
88   {
89     SMDSAbs_ElementType myPreviewType; // type to show
90     //!< Constructor
91     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
92       _isShapeToMesh = (_id =_studyId =_idDoc = 0);
93       _myMeshDS  = new SMESHDS_Mesh( _id, true );
94       myPreviewType = previewElements;
95     }
96     //!< Destructor
97     virtual ~TPreviewMesh() { delete _myMeshDS; _myMeshDS = 0; }
98     //!< Copy a set of elements
99     void Copy(const TIDSortedElemSet & theElements,
100               TIDSortedElemSet&        theCopyElements,
101               SMDSAbs_ElementType      theSelectType = SMDSAbs_All,
102               SMDSAbs_ElementType      theAvoidType = SMDSAbs_All)
103     {
104       // loop on theIDsOfElements
105       TIDSortedElemSet::const_iterator eIt = theElements.begin();
106       for ( ; eIt != theElements.end(); ++eIt )
107       {
108         const SMDS_MeshElement* anElem = *eIt;
109         if ( !anElem ) continue;
110         SMDSAbs_ElementType type = anElem->GetType();
111         if ( type == theAvoidType ||
112              ( theSelectType != SMDSAbs_All && type != theSelectType ))
113           continue;
114         const SMDS_MeshElement* anElemCopy;
115         if ( type == SMDSAbs_Node)
116           anElemCopy = Copy( cast2Node(anElem) );
117         else
118           anElemCopy = Copy( anElem );
119         if ( anElemCopy )
120           theCopyElements.insert( theCopyElements.end(), anElemCopy );
121       }
122     }
123     //!< Copy an element
124     SMDS_MeshElement* Copy( const SMDS_MeshElement* anElem )
125     {
126       // copy element nodes
127       int anElemNbNodes = anElem->NbNodes();
128       vector< int > anElemNodesID( anElemNbNodes ) ;
129       SMDS_ElemIteratorPtr itElemNodes = anElem->nodesIterator();
130       for ( int i = 0; itElemNodes->more(); i++)
131       {
132         const SMDS_MeshNode* anElemNode = cast2Node( itElemNodes->next() );
133         Copy( anElemNode );
134         anElemNodesID[i] = anElemNode->GetID();
135       }
136
137       // creates a corresponding element on copied nodes
138       SMDS_MeshElement* anElemCopy = 0;
139       if ( anElem->IsPoly() && anElem->GetType() == SMDSAbs_Volume )
140       {
141         const SMDS_VtkVolume* ph =
142           dynamic_cast<const SMDS_VtkVolume*> (anElem);
143         if ( ph )
144           anElemCopy = _myMeshDS->AddPolyhedralVolumeWithID
145             (anElemNodesID, ph->GetQuantities(),anElem->GetID());
146       }
147       else {
148         anElemCopy = ::SMESH_MeshEditor(this).AddElement( anElemNodesID,
149                                                           anElem->GetType(),
150                                                           anElem->IsPoly() );
151       }
152       return anElemCopy;
153     }
154     //!< Copy a node
155     SMDS_MeshNode* Copy( const SMDS_MeshNode* anElemNode )
156     {
157       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
158                                       anElemNode->GetID());
159     }
160   };// struct TPreviewMesh
161
162   static SMESH_NodeSearcher *    theNodeSearcher    = 0;
163   static SMESH_ElementSearcher * theElementSearcher = 0;
164
165   //=============================================================================
166   /*!
167    * \brief Deleter of theNodeSearcher at any compute event occured
168    */
169   //=============================================================================
170
171   struct TSearchersDeleter : public SMESH_subMeshEventListener
172   {
173     SMESH_Mesh* myMesh;
174     string      myMeshPartIOR;
175     //!< Constructor
176     TSearchersDeleter(): SMESH_subMeshEventListener( false, // won't be deleted by submesh
177                                                      "SMESH_MeshEditor_i::TSearchersDeleter"),
178                          myMesh(0) {}
179     //!< Delete theNodeSearcher
180     static void Delete()
181     {
182       if ( theNodeSearcher )    delete theNodeSearcher;    theNodeSearcher    = 0;
183       if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
184     }
185     typedef map < int, SMESH_subMesh * > TDependsOnMap;
186     //!< The meshod called by submesh: do my main job
187     void ProcessEvent(const int, const int eventType, SMESH_subMesh* sm,
188                       SMESH_subMeshEventListenerData*,const SMESH_Hypothesis*)
189     {
190       if ( eventType == SMESH_subMesh::COMPUTE_EVENT ) {
191         Delete();
192         Unset( sm->GetFather() );
193       }
194     }
195     //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
196     void Set(SMESH_Mesh* mesh, const string& meshPartIOR = string())
197     {
198       if ( myMesh != mesh || myMeshPartIOR != meshPartIOR)
199       {
200         if ( myMesh ) {
201           Delete();
202           Unset( myMesh );
203         }
204         myMesh = mesh;
205         myMeshPartIOR = meshPartIOR;
206         if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
207           const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
208           TDependsOnMap::const_iterator sm;
209           for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
210             sm->second->SetEventListener( this, 0, sm->second );
211         }
212       }
213     }
214     //!<  delete self from all submeshes
215     void Unset(SMESH_Mesh* mesh)
216     {
217       if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
218         const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
219         TDependsOnMap::const_iterator sm;
220         for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
221           sm->second->DeleteEventListener( this );
222       }
223       myMesh = 0;
224     }
225
226   } theSearchersDeleter;
227
228   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
229   {
230     TCollection_AsciiString typeStr;
231     switch ( theMirrorType ) {
232     case  SMESH::SMESH_MeshEditor::POINT:
233       typeStr = "SMESH.SMESH_MeshEditor.POINT";
234       break;
235     case  SMESH::SMESH_MeshEditor::AXIS:
236       typeStr = "SMESH.SMESH_MeshEditor.AXIS";
237       break;
238     default:
239       typeStr = "SMESH.SMESH_MeshEditor.PLANE";
240     }
241     return typeStr;
242   }
243   //================================================================================
244   /*!
245    * \brief function for conversion of long_array to TIDSortedElemSet
246    * \param IDs - array of IDs
247    * \param aMesh - mesh
248    * \param aMap - collection to fill
249    * \param aType - element type
250    */
251   //================================================================================
252
253   void arrayToSet(const SMESH::long_array & IDs,
254                   const SMESHDS_Mesh*       aMesh,
255                   TIDSortedElemSet&         aMap,
256                   const SMDSAbs_ElementType aType = SMDSAbs_All )
257   {
258     for (int i=0; i<IDs.length(); i++) {
259       CORBA::Long ind = IDs[i];
260       const SMDS_MeshElement * elem =
261         (aType == SMDSAbs_Node ? aMesh->FindNode(ind) : aMesh->FindElement(ind));
262       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
263         aMap.insert( elem );
264     }
265   }
266   //================================================================================
267   /*!
268    * \brief Retrieve elements of given type from SMESH_IDSource
269    */
270   //================================================================================
271
272   bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
273                      const SMESHDS_Mesh*        theMeshDS,
274                      TIDSortedElemSet&          theElemSet,
275                      const SMDSAbs_ElementType  theType,
276                      const bool                 emptyIfIsMesh=false)
277
278   {
279     if ( CORBA::is_nil( theIDSource ) )
280       return false;
281     if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
282       return true;
283
284     SMESH::long_array_var anIDs = theIDSource->GetIDs();
285     if ( anIDs->length() == 0 )
286       return false;
287     SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
288     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
289     {
290       if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
291         arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
292       else
293         return false;
294     }
295     else
296     {
297       arrayToSet( anIDs, theMeshDS, theElemSet, theType);
298     }
299     return true;
300   }
301   //================================================================================
302   /*!
303    * \brief Retrieve nodes from SMESH_IDSource
304    */
305   //================================================================================
306
307   void idSourceToNodeSet(SMESH::SMESH_IDSource_ptr  theObject,
308                          const SMESHDS_Mesh*        theMeshDS,
309                          TIDSortedNodeSet&          theNodeSet)
310
311   {
312     if ( CORBA::is_nil( theObject ) )
313       return;
314     SMESH::array_of_ElementType_var types = theObject->GetTypes();
315     SMESH::long_array_var     aElementsId = theObject->GetIDs();
316     if ( types->length() == 1 && types[0] == SMESH::NODE)
317     {
318       for(int i = 0; i < aElementsId->length(); i++)
319         if ( const SMDS_MeshNode * n = theMeshDS->FindNode( aElementsId[i] ))
320           theNodeSet.insert( theNodeSet.end(), n);
321     }
322     else if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
323     {
324       SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
325       while ( nIt->more( ))
326         if( const SMDS_MeshElement * elem = nIt->next() )
327           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
328     }
329     else
330     {
331       for(int i = 0; i < aElementsId->length(); i++)
332         if( const SMDS_MeshElement * elem = theMeshDS->FindElement( aElementsId[i] ))
333           theNodeSet.insert( elem->begin_nodes(), elem->end_nodes());
334     }
335   }
336
337   //================================================================================
338   /*!
339    * \brief Returns elements connected to the given elements
340    */
341   //================================================================================
342
343   void getElementsAround(const TIDSortedElemSet& theElements,
344                          const SMESHDS_Mesh*     theMeshDS,
345                          TIDSortedElemSet&       theElementsAround)
346   {
347     if ( theElements.empty() ) return;
348
349     SMDSAbs_ElementType elemType    = (*theElements.begin())->GetType();
350     bool sameElemType = ( elemType == (*theElements.rbegin())->GetType() );
351     if ( sameElemType &&
352          theMeshDS->GetMeshInfo().NbElements( elemType ) == theElements.size() )
353       return; // all the elements are in theElements
354
355     if ( !sameElemType )
356       elemType = SMDSAbs_All;
357
358     TIDSortedElemSet visitedNodes;
359     TIDSortedElemSet::const_iterator elemIt = theElements.begin();
360     for ( ; elemIt != theElements.end(); ++elemIt )
361     {
362       const SMDS_MeshElement* e = *elemIt;
363       int i = e->NbCornerNodes();
364       while ( --i != -1 )
365       {
366         const SMDS_MeshNode* n = e->GetNode( i );
367         if ( visitedNodes.insert( n ).second )
368         {
369           SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
370           while ( invIt->more() )
371           {
372             const SMDS_MeshElement* elemAround = invIt->next();
373             if ( !theElements.count( elemAround ))
374               theElementsAround.insert( elemAround );
375           }
376         }
377       }
378     }
379   }
380 }
381
382 //=============================================================================
383 /*!
384  *
385  */
386 //=============================================================================
387
388 SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview)
389 {
390   myMesh_i = theMesh;
391   myMesh = & theMesh->GetImpl();
392   myPreviewMode = isPreview;
393 }
394
395 //================================================================================
396 /*!
397  * \brief Destructor
398  */
399 //================================================================================
400
401 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
402 {
403 }
404
405 //================================================================================
406 /*!
407  * \brief Clear members
408  */
409 //================================================================================
410
411 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
412 {
413   if ( myPreviewMode ) {
414     myPreviewData = new SMESH::MeshPreviewStruct();
415   }
416   else {
417     myLastCreatedElems = new SMESH::long_array();
418     myLastCreatedNodes = new SMESH::long_array();
419     if ( deleteSearchers )
420       TSearchersDeleter::Delete();
421   }
422 }
423
424 //=======================================================================
425 //function : MakeIDSource
426 //purpose  : Wrap a sequence of ids in a SMESH_IDSource
427 //=======================================================================
428
429 struct _IDSource : public POA_SMESH::SMESH_IDSource
430 {
431   SMESH::long_array     _ids;
432   SMESH::ElementType    _type;
433   SMESH::SMESH_Mesh_ptr _mesh;
434   SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
435   SMESH::long_array* GetMeshInfo() { return 0; }
436   SMESH::SMESH_Mesh_ptr GetMesh()  { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
437   bool IsMeshInfoCorrect()         { return true; }
438   SMESH::array_of_ElementType* GetTypes()
439   {
440     SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
441     if ( _ids.length() > 0 ) {
442       types->length( 1 );
443       types[0] = _type;
444     }
445     return types._retn();
446   }
447 };
448
449 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
450                                                            SMESH::ElementType       type)
451 {
452   _IDSource* anIDSource = new _IDSource;
453   anIDSource->_ids = ids;
454   anIDSource->_type = type;
455   anIDSource->_mesh = myMesh_i->_this();
456   SMESH::SMESH_IDSource_var anIDSourceVar = anIDSource->_this();
457
458   return anIDSourceVar._retn();
459 }
460
461 //=============================================================================
462 /*!
463  *
464  */
465 //=============================================================================
466
467 CORBA::Boolean
468 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
469 {
470   initData();
471
472   ::SMESH_MeshEditor anEditor( myMesh );
473   list< int > IdList;
474
475   for (int i = 0; i < IDsOfElements.length(); i++)
476     IdList.push_back( IDsOfElements[i] );
477
478   // Update Python script
479   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
480
481   // Remove Elements
482   bool ret = anEditor.Remove( IdList, false );
483   myMesh->GetMeshDS()->Modified();
484   if ( IDsOfElements.length() )
485     myMesh->SetIsModified( true ); // issue 0020693
486   return ret;
487 }
488
489 //=============================================================================
490 /*!
491  *
492  */
493 //=============================================================================
494
495 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
496 {
497   initData();
498
499   ::SMESH_MeshEditor anEditor( myMesh );
500   list< int > IdList;
501   for (int i = 0; i < IDsOfNodes.length(); i++)
502     IdList.push_back( IDsOfNodes[i] );
503
504   // Update Python script
505   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
506
507   bool ret = anEditor.Remove( IdList, true );
508   myMesh->GetMeshDS()->Modified();
509   if ( IDsOfNodes.length() )
510     myMesh->SetIsModified( true ); // issue 0020693
511   return ret;
512 }
513
514 //=============================================================================
515 /*!
516  *
517  */
518 //=============================================================================
519
520 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
521 {
522   initData();
523
524   ::SMESH_MeshEditor anEditor( myMesh );
525
526   // Update Python script
527   TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
528
529   // Create filter to find all orphan nodes
530   SMESH::Controls::Filter::TIdSequence seq;
531   SMESH::Controls::PredicatePtr predicate( new SMESH::Controls::FreeNodes() );
532   SMESH::Controls::Filter::GetElementsId( GetMeshDS(), predicate, seq );
533
534   // remove orphan nodes (if there are any)
535   list< int > IdList;
536   for ( int i = 0; i < seq.size(); i++ )
537     IdList.push_back( seq[i] );
538
539   int nbNodesBefore = myMesh->NbNodes();
540   anEditor.Remove( IdList, true );
541   myMesh->GetMeshDS()->Modified();
542   if ( IdList.size() )
543     myMesh->SetIsModified( true );
544   int nbNodesAfter = myMesh->NbNodes();
545
546   return nbNodesBefore - nbNodesAfter;
547 }
548
549 //=============================================================================
550 /*!
551  *
552  */
553 //=============================================================================
554
555 CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
556                                         CORBA::Double y, CORBA::Double z)
557 {
558   initData();
559
560   const SMDS_MeshNode* N = GetMeshDS()->AddNode(x, y, z);
561
562   // Update Python script
563   TPythonDump() << "nodeID = " << this << ".AddNode( "
564                 << x << ", " << y << ", " << z << " )";
565
566   myMesh->GetMeshDS()->Modified();
567   myMesh->SetIsModified( true ); // issue 0020693
568   return N->GetID();
569 }
570
571 //=============================================================================
572 /*!
573  *
574  */
575 //=============================================================================
576 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
577 {
578   initData();
579
580   const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(IDOfNode);
581   SMDS_MeshElement* elem = GetMeshDS()->Add0DElement(aNode);
582
583   // Update Python script
584   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
585
586   myMesh->GetMeshDS()->Modified();
587   myMesh->SetIsModified( true ); // issue 0020693
588
589   if (elem)
590     return elem->GetID();
591
592   return 0;
593 }
594
595 //=============================================================================
596 /*!
597  *
598  */
599 //=============================================================================
600
601 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
602 {
603   initData();
604
605   int NbNodes = IDsOfNodes.length();
606   SMDS_MeshElement* elem = 0;
607   if (NbNodes == 2)
608   {
609     CORBA::Long index1 = IDsOfNodes[0];
610     CORBA::Long index2 = IDsOfNodes[1];
611     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(index1), GetMeshDS()->FindNode(index2));
612
613     // Update Python script
614     TPythonDump() << "edge = " << this << ".AddEdge([ "
615                   << index1 << ", " << index2 <<" ])";
616   }
617   if (NbNodes == 3) {
618     CORBA::Long n1 = IDsOfNodes[0];
619     CORBA::Long n2 = IDsOfNodes[1];
620     CORBA::Long n12 = IDsOfNodes[2];
621     elem = GetMeshDS()->AddEdge(GetMeshDS()->FindNode(n1),
622                                 GetMeshDS()->FindNode(n2),
623                                 GetMeshDS()->FindNode(n12));
624     // Update Python script
625     TPythonDump() << "edgeID = " << this << ".AddEdge([ "
626                   <<n1<<", "<<n2<<", "<<n12<<" ])";
627   }
628
629   myMesh->GetMeshDS()->Modified();
630   if(elem)
631     return myMesh->SetIsModified( true ), elem->GetID();
632
633   return 0;
634 }
635
636 //=============================================================================
637 /*!
638  *  AddFace
639  */
640 //=============================================================================
641
642 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
643 {
644   initData();
645
646   int NbNodes = IDsOfNodes.length();
647   if (NbNodes < 3)
648   {
649     return 0;
650   }
651
652   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
653   for (int i = 0; i < NbNodes; i++)
654     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
655
656   SMDS_MeshElement* elem = 0;
657   if (NbNodes == 3) {
658     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
659   }
660   else if (NbNodes == 4) {
661     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
662   }
663   else if (NbNodes == 6) {
664     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
665                                 nodes[4], nodes[5]);
666   }
667   else if (NbNodes == 8) {
668     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
669                                 nodes[4], nodes[5], nodes[6], nodes[7]);
670   }
671   else if (NbNodes == 9) {
672     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
673                                 nodes[4], nodes[5], nodes[6], nodes[7], nodes[8] );
674   }
675   else if (NbNodes > 2) {
676     elem = GetMeshDS()->AddPolygonalFace(nodes);
677   }
678
679   // Update Python script
680   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
681
682   myMesh->GetMeshDS()->Modified();
683   if(elem)
684     return myMesh->SetIsModified( true ), elem->GetID();
685
686   return 0;
687 }
688
689 //=============================================================================
690 /*!
691  *  AddPolygonalFace
692  */
693 //=============================================================================
694 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
695 {
696   initData();
697
698   int NbNodes = IDsOfNodes.length();
699   std::vector<const SMDS_MeshNode*> nodes (NbNodes);
700   for (int i = 0; i < NbNodes; i++)
701     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
702
703   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
704
705   // Update Python script
706   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
707
708   myMesh->GetMeshDS()->Modified();
709   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
710 }
711
712 //=============================================================================
713 /*!
714  *
715  */
716 //=============================================================================
717
718 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
719 {
720   initData();
721
722   int NbNodes = IDsOfNodes.length();
723   vector< const SMDS_MeshNode*> n(NbNodes);
724   for(int i=0;i<NbNodes;i++)
725     n[i]=GetMeshDS()->FindNode(IDsOfNodes[i]);
726
727   SMDS_MeshElement* elem = 0;
728   switch(NbNodes)
729   {
730   case 4 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3]); break;
731   case 5 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4]); break;
732   case 6 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5]); break;
733   case 8 :elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7]); break;
734   case 10:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
735                                         n[6],n[7],n[8],n[9]);
736     break;
737   case 12:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],
738                                         n[6],n[7],n[8],n[9],n[10],n[11]);
739     break;
740   case 13:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],
741                                         n[7],n[8],n[9],n[10],n[11],n[12]);
742     break;
743   case 15:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],
744                                         n[9],n[10],n[11],n[12],n[13],n[14]);
745     break;
746   case 20:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
747                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
748                                         n[15],n[16],n[17],n[18],n[19]);
749     break;
750   case 27:elem = GetMeshDS()->AddVolume(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],
751                                         n[8],n[9],n[10],n[11],n[12],n[13],n[14],
752                                         n[15],n[16],n[17],n[18],n[19],
753                                         n[20],n[21],n[22],n[23],n[24],n[25],n[26]);
754     break;
755   }
756
757   // Update Python script
758   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
759
760   myMesh->GetMeshDS()->Modified();
761   if(elem)
762     return myMesh->SetIsModified( true ), elem->GetID();
763
764   return 0;
765 }
766
767 //=============================================================================
768 /*!
769  *  AddPolyhedralVolume
770  */
771 //=============================================================================
772 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
773                                                      const SMESH::long_array & Quantities)
774 {
775   initData();
776
777   int NbNodes = IDsOfNodes.length();
778   std::vector<const SMDS_MeshNode*> n (NbNodes);
779   for (int i = 0; i < NbNodes; i++)
780     {
781       const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(IDsOfNodes[i]);
782       if (!aNode) return 0;
783       n[i] = aNode;
784     }
785
786   int NbFaces = Quantities.length();
787   std::vector<int> q (NbFaces);
788   for (int j = 0; j < NbFaces; j++)
789     q[j] = Quantities[j];
790
791   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(n, q);
792
793   // Update Python script
794   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
795                 << IDsOfNodes << ", " << Quantities << " )";
796   myMesh->GetMeshDS()->Modified();
797
798   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
799 }
800
801 //=============================================================================
802 /*!
803  *  AddPolyhedralVolumeByFaces
804  */
805 //=============================================================================
806 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
807 {
808   initData();
809
810   int NbFaces = IdsOfFaces.length();
811   std::vector<const SMDS_MeshNode*> poly_nodes;
812   std::vector<int> quantities (NbFaces);
813
814   for (int i = 0; i < NbFaces; i++) {
815     const SMDS_MeshElement* aFace = GetMeshDS()->FindElement(IdsOfFaces[i]);
816     quantities[i] = aFace->NbNodes();
817
818     SMDS_ElemIteratorPtr It = aFace->nodesIterator();
819     while (It->more()) {
820       poly_nodes.push_back(static_cast<const SMDS_MeshNode *>(It->next()));
821     }
822   }
823
824   const SMDS_MeshElement* elem = GetMeshDS()->AddPolyhedralVolume(poly_nodes, quantities);
825
826   // Update Python script
827   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
828                 << IdsOfFaces << " )";
829   myMesh->GetMeshDS()->Modified();
830
831   return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
832 }
833
834 //=============================================================================
835 /*!
836  * \brief Bind a node to a vertex
837  * \param NodeID - node ID
838  * \param VertexID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
839  * \retval boolean - false if NodeID or VertexID is invalid
840  */
841 //=============================================================================
842
843 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
844   throw (SALOME::SALOME_Exception)
845 {
846   Unexpect aCatch(SALOME_SalomeException);
847
848   SMESHDS_Mesh * mesh = GetMeshDS();
849   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
850   if ( !node )
851     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
852
853   if ( mesh->MaxShapeIndex() < VertexID )
854     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
855
856   TopoDS_Shape shape = mesh->IndexToShape( VertexID );
857   if ( shape.ShapeType() != TopAbs_VERTEX )
858     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
859
860   mesh->SetNodeOnVertex( node, VertexID );
861
862   myMesh->SetIsModified( true );
863 }
864
865 //=============================================================================
866 /*!
867  * \brief Store node position on an edge
868  * \param NodeID - node ID
869  * \param EdgeID - edge ID available through GEOM_Object.GetSubShapeIndices()[0]
870  * \param paramOnEdge - parameter on edge where the node is located
871  * \retval boolean - false if any parameter is invalid
872  */
873 //=============================================================================
874
875 void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
876                                        CORBA::Double paramOnEdge)
877   throw (SALOME::SALOME_Exception)
878 {
879   Unexpect aCatch(SALOME_SalomeException);
880
881   SMESHDS_Mesh * mesh = GetMeshDS();
882   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
883   if ( !node )
884     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
885
886   if ( mesh->MaxShapeIndex() < EdgeID )
887     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
888
889   TopoDS_Shape shape = mesh->IndexToShape( EdgeID );
890   if ( shape.ShapeType() != TopAbs_EDGE )
891     THROW_SALOME_CORBA_EXCEPTION("Invalid EdgeID", SALOME::BAD_PARAM);
892
893   Standard_Real f,l;
894   BRep_Tool::Range( TopoDS::Edge( shape ), f,l);
895   if ( paramOnEdge < f || paramOnEdge > l )
896     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
897
898   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
899
900   myMesh->SetIsModified( true );
901 }
902
903 //=============================================================================
904 /*!
905  * \brief Store node position on a face
906  * \param NodeID - node ID
907  * \param FaceID - face ID available through GEOM_Object.GetSubShapeIndices()[0]
908  * \param u - U parameter on face where the node is located
909  * \param v - V parameter on face where the node is located
910  * \retval boolean - false if any parameter is invalid
911  */
912 //=============================================================================
913
914 void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
915                                        CORBA::Double u, CORBA::Double v)
916   throw (SALOME::SALOME_Exception)
917 {
918   Unexpect aCatch(SALOME_SalomeException);
919
920   SMESHDS_Mesh * mesh = GetMeshDS();
921   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
922   if ( !node )
923     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
924
925   if ( mesh->MaxShapeIndex() < FaceID )
926     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
927
928   TopoDS_Shape shape = mesh->IndexToShape( FaceID );
929   if ( shape.ShapeType() != TopAbs_FACE )
930     THROW_SALOME_CORBA_EXCEPTION("Invalid FaceID", SALOME::BAD_PARAM);
931
932   BRepAdaptor_Surface surf( TopoDS::Face( shape ));
933   bool isOut = ( u < surf.FirstUParameter() ||
934                  u > surf.LastUParameter()  ||
935                  v < surf.FirstVParameter() ||
936                  v > surf.LastVParameter() );
937
938   if ( isOut ) {
939 #ifdef _DEBUG_
940     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
941               << " u( " <<  surf.FirstUParameter()
942               << "," <<  surf.LastUParameter()
943               << ") v( " <<  surf.FirstVParameter()
944               << "," <<  surf.LastVParameter() << ")" );
945 #endif
946     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
947   }
948
949   mesh->SetNodeOnFace( node, FaceID, u, v );
950   myMesh->SetIsModified( true );
951 }
952
953 //=============================================================================
954 /*!
955  * \brief Bind a node to a solid
956  * \param NodeID - node ID
957  * \param SolidID - vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
958  * \retval boolean - false if NodeID or SolidID is invalid
959  */
960 //=============================================================================
961
962 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
963   throw (SALOME::SALOME_Exception)
964 {
965   Unexpect aCatch(SALOME_SalomeException);
966
967   SMESHDS_Mesh * mesh = GetMeshDS();
968   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
969   if ( !node )
970     THROW_SALOME_CORBA_EXCEPTION("Invalid NodeID", SALOME::BAD_PARAM);
971
972   if ( mesh->MaxShapeIndex() < SolidID )
973     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
974
975   TopoDS_Shape shape = mesh->IndexToShape( SolidID );
976   if ( shape.ShapeType() != TopAbs_SOLID &&
977        shape.ShapeType() != TopAbs_SHELL)
978     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
979
980   mesh->SetNodeInVolume( node, SolidID );
981
982   // myMesh->SetIsModified( true ); - SetNodeInVolume() can't prevent re-compute, I believe
983 }
984
985 //=============================================================================
986 /*!
987  * \brief Bind an element to a shape
988  * \param ElementID - element ID
989  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
990  * \retval boolean - false if ElementID or ShapeID is invalid
991  */
992 //=============================================================================
993
994 void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
995                                                CORBA::Long ShapeID)
996   throw (SALOME::SALOME_Exception)
997 {
998   Unexpect aCatch(SALOME_SalomeException);
999
1000   SMESHDS_Mesh * mesh = GetMeshDS();
1001   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
1002   if ( !elem )
1003     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
1004
1005   if ( mesh->MaxShapeIndex() < ShapeID )
1006     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
1007
1008   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
1009   if ( shape.ShapeType() != TopAbs_EDGE &&
1010        shape.ShapeType() != TopAbs_FACE &&
1011        shape.ShapeType() != TopAbs_SOLID &&
1012        shape.ShapeType() != TopAbs_SHELL )
1013     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
1014
1015   mesh->SetMeshElementOnShape( elem, ShapeID );
1016
1017   myMesh->SetIsModified( true );
1018 }
1019
1020 //=============================================================================
1021 /*!
1022  *
1023  */
1024 //=============================================================================
1025
1026 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
1027                                                CORBA::Long NodeID2)
1028 {
1029   initData();
1030
1031   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
1032   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
1033   if ( !n1 || !n2 )
1034     return false;
1035
1036   // Update Python script
1037   TPythonDump() << "isDone = " << this << ".InverseDiag( "
1038                 << NodeID1 << ", " << NodeID2 << " )";
1039
1040
1041   ::SMESH_MeshEditor aMeshEditor( myMesh );
1042   int ret =  aMeshEditor.InverseDiag ( n1, n2 );
1043   myMesh->GetMeshDS()->Modified();
1044   myMesh->SetIsModified( true );
1045   return ret;
1046 }
1047
1048 //=============================================================================
1049 /*!
1050  *
1051  */
1052 //=============================================================================
1053
1054 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
1055                                               CORBA::Long NodeID2)
1056 {
1057   initData();
1058
1059   const SMDS_MeshNode * n1 = GetMeshDS()->FindNode( NodeID1 );
1060   const SMDS_MeshNode * n2 = GetMeshDS()->FindNode( NodeID2 );
1061   if ( !n1 || !n2 )
1062     return false;
1063
1064   // Update Python script
1065   TPythonDump() << "isDone = " << this << ".DeleteDiag( "
1066                 << NodeID1 << ", " << NodeID2 <<  " )";
1067
1068   ::SMESH_MeshEditor aMeshEditor( myMesh );
1069
1070   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
1071
1072   myMesh->GetMeshDS()->Modified();
1073   if ( stat )
1074     myMesh->SetIsModified( true ); // issue 0020693
1075
1076   storeResult(aMeshEditor);
1077
1078   return stat;
1079 }
1080
1081 //=============================================================================
1082 /*!
1083  *
1084  */
1085 //=============================================================================
1086
1087 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
1088 {
1089   initData();
1090
1091   ::SMESH_MeshEditor anEditor( myMesh );
1092   for (int i = 0; i < IDsOfElements.length(); i++)
1093   {
1094     CORBA::Long index = IDsOfElements[i];
1095     const SMDS_MeshElement * elem = GetMeshDS()->FindElement(index);
1096     if ( elem )
1097       anEditor.Reorient( elem );
1098   }
1099   // Update Python script
1100   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
1101
1102   myMesh->GetMeshDS()->Modified();
1103   if ( IDsOfElements.length() )
1104     myMesh->SetIsModified( true ); // issue 0020693
1105
1106   return true;
1107 }
1108
1109
1110 //=============================================================================
1111 /*!
1112  *
1113  */
1114 //=============================================================================
1115
1116 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
1117 {
1118   initData();
1119
1120   TPythonDump aTPythonDump; // suppress dump in Reorient()
1121
1122   SMESH::long_array_var anElementsId = theObject->GetIDs();
1123   CORBA::Boolean isDone = Reorient(anElementsId);
1124
1125   // Update Python script
1126   aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
1127
1128   return isDone;
1129 }
1130
1131 //=============================================================================
1132 /*!
1133  *
1134  */
1135 //=============================================================================
1136 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
1137                                               SMESH::NumericalFunctor_ptr Criterion,
1138                                               CORBA::Double               MaxAngle)
1139 {
1140   initData();
1141
1142   SMESHDS_Mesh* aMesh = GetMeshDS();
1143   TIDSortedElemSet faces;
1144   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1145
1146   SMESH::NumericalFunctor_i* aNumericalFunctor =
1147     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1148   SMESH::Controls::NumericalFunctorPtr aCrit;
1149   if ( !aNumericalFunctor )
1150     aCrit.reset( new SMESH::Controls::AspectRatio() );
1151   else
1152     aCrit = aNumericalFunctor->GetNumericalFunctor();
1153
1154   // Update Python script
1155   TPythonDump() << "isDone = " << this << ".TriToQuad( "
1156                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
1157
1158   ::SMESH_MeshEditor anEditor( myMesh );
1159
1160   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
1161   myMesh->GetMeshDS()->Modified();
1162   if ( stat )
1163     myMesh->SetIsModified( true ); // issue 0020693
1164
1165   storeResult(anEditor);
1166
1167   return stat;
1168 }
1169
1170
1171 //=============================================================================
1172 /*!
1173  *
1174  */
1175 //=============================================================================
1176 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
1177                                                     SMESH::NumericalFunctor_ptr Criterion,
1178                                                     CORBA::Double               MaxAngle)
1179 {
1180   initData();
1181
1182   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
1183   SMESH::long_array_var anElementsId = theObject->GetIDs();
1184   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1185
1186   SMESH::NumericalFunctor_i* aNumericalFunctor =
1187     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1188
1189   // Update Python script
1190   aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1191                << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
1192
1193   return isDone;
1194 }
1195
1196
1197 //=============================================================================
1198 /*!
1199  *
1200  */
1201 //=============================================================================
1202 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
1203                                               SMESH::NumericalFunctor_ptr Criterion)
1204 {
1205   initData();
1206
1207   SMESHDS_Mesh* aMesh = GetMeshDS();
1208   TIDSortedElemSet faces;
1209   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1210
1211   SMESH::NumericalFunctor_i* aNumericalFunctor =
1212     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1213   SMESH::Controls::NumericalFunctorPtr aCrit;
1214   if ( !aNumericalFunctor )
1215     aCrit.reset( new SMESH::Controls::AspectRatio() );
1216   else
1217     aCrit = aNumericalFunctor->GetNumericalFunctor();
1218
1219
1220   // Update Python script
1221   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1222
1223   ::SMESH_MeshEditor anEditor( myMesh );
1224   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
1225   myMesh->GetMeshDS()->Modified();
1226   if ( stat )
1227     myMesh->SetIsModified( true ); // issue 0020693
1228
1229   storeResult(anEditor);
1230
1231   return stat;
1232 }
1233
1234
1235 //=============================================================================
1236 /*!
1237  *
1238  */
1239 //=============================================================================
1240 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1241                                                     SMESH::NumericalFunctor_ptr Criterion)
1242 {
1243   initData();
1244
1245   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
1246
1247   SMESH::long_array_var anElementsId = theObject->GetIDs();
1248   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1249
1250   SMESH::NumericalFunctor_i* aNumericalFunctor =
1251     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1252
1253   // Update Python script
1254   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1255
1256   return isDone;
1257 }
1258
1259
1260 //=============================================================================
1261 /*!
1262  *
1263  */
1264 //=============================================================================
1265 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1266                                               CORBA::Boolean            Diag13)
1267 {
1268   initData();
1269
1270   SMESHDS_Mesh* aMesh = GetMeshDS();
1271   TIDSortedElemSet faces;
1272   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1273
1274   // Update Python script
1275   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1276                 << IDsOfElements << ", " << Diag13 << " )";
1277
1278   ::SMESH_MeshEditor anEditor( myMesh );
1279   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
1280   myMesh->GetMeshDS()->Modified();
1281   if ( stat )
1282     myMesh->SetIsModified( true ); // issue 0020693
1283
1284
1285   storeResult(anEditor);
1286
1287   return stat;
1288 }
1289
1290
1291 //=============================================================================
1292 /*!
1293  *
1294  */
1295 //=============================================================================
1296 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1297                                                     CORBA::Boolean            Diag13)
1298 {
1299   initData();
1300
1301   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
1302
1303   SMESH::long_array_var anElementsId = theObject->GetIDs();
1304   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1305
1306   // Update Python script
1307   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1308                << theObject << ", " << Diag13 << " )";
1309
1310   return isDone;
1311 }
1312
1313
1314 //=============================================================================
1315 /*!
1316  *  BestSplit
1317  */
1318 //=============================================================================
1319 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
1320                                            SMESH::NumericalFunctor_ptr Criterion)
1321 {
1322   initData();
1323
1324   const SMDS_MeshElement* quad = GetMeshDS()->FindElement(IDOfQuad);
1325   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1326   {
1327     SMESH::NumericalFunctor_i* aNumericalFunctor =
1328       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1329     SMESH::Controls::NumericalFunctorPtr aCrit;
1330     if (aNumericalFunctor)
1331       aCrit = aNumericalFunctor->GetNumericalFunctor();
1332     else
1333       aCrit.reset(new SMESH::Controls::AspectRatio());
1334
1335     ::SMESH_MeshEditor anEditor (myMesh);
1336     return anEditor.BestSplit(quad, aCrit);
1337   }
1338   return -1;
1339 }
1340
1341 //================================================================================
1342 /*!
1343  * \brief Split volumic elements into tetrahedrons
1344  */
1345 //================================================================================
1346
1347 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
1348                                                 CORBA::Short              methodFlags)
1349   throw (SALOME::SALOME_Exception)
1350 {
1351   Unexpect aCatch(SALOME_SalomeException);
1352
1353   initData();
1354
1355   SMESH::long_array_var anElementsId = elems->GetIDs();
1356   TIDSortedElemSet elemSet;
1357   arrayToSet( anElementsId, GetMeshDS(), elemSet, SMDSAbs_Volume );
1358
1359   ::SMESH_MeshEditor anEditor (myMesh);
1360   anEditor.SplitVolumesIntoTetra( elemSet, int( methodFlags ));
1361   myMesh->GetMeshDS()->Modified();
1362
1363   storeResult(anEditor);
1364
1365 //   if ( myLastCreatedElems.length() ) - it does not influence Compute()
1366 //     myMesh->SetIsModified( true ); // issue 0020693
1367
1368   TPythonDump() << this << ".SplitVolumesIntoTetra( "
1369                 << elems << ", " << methodFlags << " )";
1370 }
1371
1372 //=======================================================================
1373 //function : Smooth
1374 //purpose  :
1375 //=======================================================================
1376
1377 CORBA::Boolean
1378 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
1379                            const SMESH::long_array &              IDsOfFixedNodes,
1380                            CORBA::Long                            MaxNbOfIterations,
1381                            CORBA::Double                          MaxAspectRatio,
1382                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1383 {
1384   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1385                  MaxAspectRatio, Method, false );
1386 }
1387
1388
1389 //=======================================================================
1390 //function : SmoothParametric
1391 //purpose  :
1392 //=======================================================================
1393
1394 CORBA::Boolean
1395 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
1396                                      const SMESH::long_array &              IDsOfFixedNodes,
1397                                      CORBA::Long                            MaxNbOfIterations,
1398                                      CORBA::Double                          MaxAspectRatio,
1399                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
1400 {
1401   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
1402                  MaxAspectRatio, Method, true );
1403 }
1404
1405
1406 //=======================================================================
1407 //function : SmoothObject
1408 //purpose  :
1409 //=======================================================================
1410
1411 CORBA::Boolean
1412 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1413                                  const SMESH::long_array &              IDsOfFixedNodes,
1414                                  CORBA::Long                            MaxNbOfIterations,
1415                                  CORBA::Double                          MaxAspectRatio,
1416                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
1417 {
1418   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1419                        MaxAspectRatio, Method, false);
1420 }
1421
1422
1423 //=======================================================================
1424 //function : SmoothParametricObject
1425 //purpose  :
1426 //=======================================================================
1427
1428 CORBA::Boolean
1429 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
1430                                            const SMESH::long_array &              IDsOfFixedNodes,
1431                                            CORBA::Long                            MaxNbOfIterations,
1432                                            CORBA::Double                          MaxAspectRatio,
1433                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
1434 {
1435   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
1436                        MaxAspectRatio, Method, true);
1437 }
1438
1439
1440 //=============================================================================
1441 /*!
1442  *
1443  */
1444 //=============================================================================
1445
1446 CORBA::Boolean
1447 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
1448                            const SMESH::long_array &              IDsOfFixedNodes,
1449                            CORBA::Long                            MaxNbOfIterations,
1450                            CORBA::Double                          MaxAspectRatio,
1451                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
1452                            bool                                   IsParametric)
1453 {
1454   initData();
1455
1456   SMESHDS_Mesh* aMesh = GetMeshDS();
1457
1458   TIDSortedElemSet elements;
1459   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
1460
1461   set<const SMDS_MeshNode*> fixedNodes;
1462   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
1463     CORBA::Long index = IDsOfFixedNodes[i];
1464     const SMDS_MeshNode * node = aMesh->FindNode(index);
1465     if ( node )
1466       fixedNodes.insert( node );
1467   }
1468   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
1469   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
1470     method = ::SMESH_MeshEditor::CENTROIDAL;
1471
1472   ::SMESH_MeshEditor anEditor( myMesh );
1473   anEditor.Smooth(elements, fixedNodes, method,
1474                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
1475
1476   myMesh->GetMeshDS()->Modified();
1477   myMesh->SetIsModified( true ); // issue 0020693
1478
1479   storeResult(anEditor);
1480
1481   // Update Python script
1482   TPythonDump() << "isDone = " << this << "."
1483                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
1484                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
1485                 << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1486                 << "SMESH.SMESH_MeshEditor."
1487                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1488                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1489
1490   return true;
1491 }
1492
1493
1494 //=============================================================================
1495 /*!
1496  *
1497  */
1498 //=============================================================================
1499
1500 CORBA::Boolean
1501 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
1502                                  const SMESH::long_array &              IDsOfFixedNodes,
1503                                  CORBA::Long                            MaxNbOfIterations,
1504                                  CORBA::Double                          MaxAspectRatio,
1505                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
1506                                  bool                                   IsParametric)
1507 {
1508   initData();
1509
1510   TPythonDump aTPythonDump;  // suppress dump in smooth()
1511
1512   SMESH::long_array_var anElementsId = theObject->GetIDs();
1513   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
1514                                   MaxAspectRatio, Method, IsParametric);
1515
1516   // Update Python script
1517   aTPythonDump << "isDone = " << this << "."
1518                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
1519                << theObject << ", " << IDsOfFixedNodes << ", "
1520                << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
1521                << "SMESH.SMESH_MeshEditor."
1522                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
1523                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
1524
1525   return isDone;
1526 }
1527
1528
1529 //=============================================================================
1530 /*!
1531  *
1532  */
1533 //=============================================================================
1534
1535 void SMESH_MeshEditor_i::RenumberNodes()
1536 {
1537   // Update Python script
1538   TPythonDump() << this << ".RenumberNodes()";
1539
1540   GetMeshDS()->Renumber( true );
1541 }
1542
1543
1544 //=============================================================================
1545 /*!
1546  *
1547  */
1548 //=============================================================================
1549
1550 void SMESH_MeshEditor_i::RenumberElements()
1551 {
1552   // Update Python script
1553   TPythonDump() << this << ".RenumberElements()";
1554
1555   GetMeshDS()->Renumber( false );
1556 }
1557
1558 //=======================================================================
1559 /*!
1560  * \brief Return groups by their IDs
1561  */
1562 //=======================================================================
1563
1564 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
1565 {
1566   if ( !groupIDs )
1567     return 0;
1568   myMesh_i->CreateGroupServants();
1569   return myMesh_i->GetGroups( *groupIDs );
1570 }
1571
1572 //=======================================================================
1573 //function : rotationSweep
1574 //purpose  :
1575 //=======================================================================
1576
1577 SMESH::ListOfGroups*
1578 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
1579                                   const SMESH::AxisStruct & theAxis,
1580                                   CORBA::Double             theAngleInRadians,
1581                                   CORBA::Long               theNbOfSteps,
1582                                   CORBA::Double             theTolerance,
1583                                   const bool                theMakeGroups,
1584                                   const SMDSAbs_ElementType theElementType)
1585 {
1586   initData();
1587
1588   TIDSortedElemSet inElements, copyElements;
1589   arrayToSet(theIDsOfElements, GetMeshDS(), inElements, theElementType);
1590
1591   TIDSortedElemSet* workElements = & inElements;
1592   TPreviewMesh      tmpMesh( SMDSAbs_Face );
1593   SMESH_Mesh*       mesh = 0;
1594   bool              makeWalls=true;
1595   if ( myPreviewMode )
1596   {
1597     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1598     tmpMesh.Copy( inElements, copyElements, select, avoid );
1599     mesh = &tmpMesh;
1600     workElements = & copyElements;
1601     //makeWalls = false;
1602   }
1603   else
1604   {
1605     mesh = myMesh;
1606   }
1607
1608   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
1609               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
1610
1611   ::SMESH_MeshEditor anEditor( mesh );
1612   ::SMESH_MeshEditor::PGroupIDs groupIds =
1613       anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
1614                               theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
1615   storeResult(anEditor);
1616   myMesh->GetMeshDS()->Modified();
1617
1618   //  myMesh->SetIsModified( true ); -- it does not influence Compute()
1619
1620   return theMakeGroups ? getGroups(groupIds.get()) : 0;
1621 }
1622
1623 //=======================================================================
1624 //function : RotationSweep
1625 //purpose  :
1626 //=======================================================================
1627
1628 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
1629                                        const SMESH::AxisStruct & theAxis,
1630                                        CORBA::Double             theAngleInRadians,
1631                                        CORBA::Long               theNbOfSteps,
1632                                        CORBA::Double             theTolerance)
1633 {
1634   if ( !myPreviewMode ) {
1635     TPythonDump() << this << ".RotationSweep( "
1636                   << theIDsOfElements << ", "
1637                   << theAxis << ", "
1638                   << theAngleInRadians << ", "
1639                   << theNbOfSteps << ", "
1640                   << theTolerance << " )";
1641   }
1642   rotationSweep(theIDsOfElements,
1643                 theAxis,
1644                 theAngleInRadians,
1645                 theNbOfSteps,
1646                 theTolerance,
1647                 false);
1648 }
1649
1650 //=======================================================================
1651 //function : RotationSweepMakeGroups
1652 //purpose  :
1653 //=======================================================================
1654
1655 SMESH::ListOfGroups*
1656 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
1657                                             const SMESH::AxisStruct& theAxis,
1658                                             CORBA::Double            theAngleInRadians,
1659                                             CORBA::Long              theNbOfSteps,
1660                                             CORBA::Double            theTolerance)
1661 {
1662   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
1663
1664   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
1665                                                theAxis,
1666                                                theAngleInRadians,
1667                                                theNbOfSteps,
1668                                                theTolerance,
1669                                                true);
1670   if (!myPreviewMode) {
1671     DumpGroupsList(aPythonDump, aGroups);
1672     aPythonDump << this << ".RotationSweepMakeGroups( "
1673                 << theIDsOfElements << ", "
1674                 << theAxis << ", "
1675                 << theAngleInRadians << ", "
1676                 << theNbOfSteps << ", "
1677                 << theTolerance << " )";
1678   }
1679   return aGroups;
1680 }
1681
1682 //=======================================================================
1683 //function : RotationSweepObject
1684 //purpose  :
1685 //=======================================================================
1686
1687 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1688                                              const SMESH::AxisStruct & theAxis,
1689                                              CORBA::Double             theAngleInRadians,
1690                                              CORBA::Long               theNbOfSteps,
1691                                              CORBA::Double             theTolerance)
1692 {
1693   if ( !myPreviewMode ) {
1694     TPythonDump() << this << ".RotationSweepObject( "
1695                   << theObject << ", "
1696                   << theAxis << ", "
1697                   << theAngleInRadians << ", "
1698                   << theNbOfSteps << ", "
1699                   << theTolerance << " )";
1700   }
1701   SMESH::long_array_var anElementsId = theObject->GetIDs();
1702   rotationSweep(anElementsId,
1703                 theAxis,
1704                 theAngleInRadians,
1705                 theNbOfSteps,
1706                 theTolerance,
1707                 false);
1708 }
1709
1710 //=======================================================================
1711 //function : RotationSweepObject1D
1712 //purpose  :
1713 //=======================================================================
1714
1715 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
1716                                                const SMESH::AxisStruct & theAxis,
1717                                                CORBA::Double             theAngleInRadians,
1718                                                CORBA::Long               theNbOfSteps,
1719                                                CORBA::Double             theTolerance)
1720 {
1721   if ( !myPreviewMode ) {
1722     TPythonDump() << this << ".RotationSweepObject1D( "
1723                   << theObject << ", "
1724                   << theAxis << ", "
1725                   << theAngleInRadians << ", "
1726                   << theNbOfSteps << ", "
1727                   << theTolerance << " )";
1728   }
1729   SMESH::long_array_var anElementsId = theObject->GetIDs();
1730   rotationSweep(anElementsId,
1731                 theAxis,
1732                 theAngleInRadians,
1733                 theNbOfSteps,
1734                 theTolerance,
1735                 false,
1736                 SMDSAbs_Edge);
1737 }
1738
1739 //=======================================================================
1740 //function : RotationSweepObject2D
1741 //purpose  :
1742 //=======================================================================
1743
1744 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
1745                                                const SMESH::AxisStruct & theAxis,
1746                                                CORBA::Double             theAngleInRadians,
1747                                                CORBA::Long               theNbOfSteps,
1748                                                CORBA::Double             theTolerance)
1749 {
1750   if ( !myPreviewMode ) {
1751     TPythonDump() << this << ".RotationSweepObject2D( "
1752                   << theObject << ", "
1753                   << theAxis << ", "
1754                   << theAngleInRadians << ", "
1755                   << theNbOfSteps << ", "
1756                   << theTolerance << " )";
1757   }
1758   SMESH::long_array_var anElementsId = theObject->GetIDs();
1759   rotationSweep(anElementsId,
1760                 theAxis,
1761                 theAngleInRadians,
1762                 theNbOfSteps,
1763                 theTolerance,
1764                 false,
1765                 SMDSAbs_Face);
1766 }
1767
1768 //=======================================================================
1769 //function : RotationSweepObjectMakeGroups
1770 //purpose  :
1771 //=======================================================================
1772
1773 SMESH::ListOfGroups*
1774 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1775                                                   const SMESH::AxisStruct&  theAxis,
1776                                                   CORBA::Double             theAngleInRadians,
1777                                                   CORBA::Long               theNbOfSteps,
1778                                                   CORBA::Double             theTolerance)
1779 {
1780   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
1781
1782   SMESH::long_array_var anElementsId = theObject->GetIDs();
1783   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1784                                                theAxis,
1785                                                theAngleInRadians,
1786                                                theNbOfSteps,
1787                                                theTolerance,
1788                                                true);
1789   if (!myPreviewMode) {
1790     DumpGroupsList(aPythonDump, aGroups);
1791     aPythonDump << this << ".RotationSweepObjectMakeGroups( "
1792                 << theObject << ", "
1793                 << theAxis << ", "
1794                 << theAngleInRadians << ", "
1795                 << theNbOfSteps << ", "
1796                 << theTolerance << " )";
1797   }
1798   return aGroups;
1799 }
1800
1801 //=======================================================================
1802 //function : RotationSweepObject1DMakeGroups
1803 //purpose  :
1804 //=======================================================================
1805
1806 SMESH::ListOfGroups*
1807 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1808                                                     const SMESH::AxisStruct&  theAxis,
1809                                                     CORBA::Double             theAngleInRadians,
1810                                                     CORBA::Long               theNbOfSteps,
1811                                                     CORBA::Double             theTolerance)
1812 {
1813   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
1814
1815   SMESH::long_array_var anElementsId = theObject->GetIDs();
1816   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1817                                                theAxis,
1818                                                theAngleInRadians,
1819                                                theNbOfSteps,
1820                                                theTolerance,
1821                                                true,
1822                                                SMDSAbs_Edge);
1823   if (!myPreviewMode) {
1824     DumpGroupsList(aPythonDump, aGroups);
1825     aPythonDump << this << ".RotationSweepObject1DMakeGroups( "
1826                 << theObject << ", "
1827                 << theAxis << ", "
1828                 << theAngleInRadians << ", "
1829                 << theNbOfSteps << ", "
1830                 << theTolerance << " )";
1831   }
1832   return aGroups;
1833 }
1834
1835 //=======================================================================
1836 //function : RotationSweepObject2DMakeGroups
1837 //purpose  :
1838 //=======================================================================
1839
1840 SMESH::ListOfGroups*
1841 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
1842                                                     const SMESH::AxisStruct&  theAxis,
1843                                                     CORBA::Double             theAngleInRadians,
1844                                                     CORBA::Long               theNbOfSteps,
1845                                                     CORBA::Double             theTolerance)
1846 {
1847   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
1848
1849   SMESH::long_array_var anElementsId = theObject->GetIDs();
1850   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
1851                                                theAxis,
1852                                                theAngleInRadians,
1853                                                theNbOfSteps,
1854                                                theTolerance,
1855                                                true,
1856                                                SMDSAbs_Face);
1857   if (!myPreviewMode) {
1858     DumpGroupsList(aPythonDump, aGroups);
1859     aPythonDump << this << ".RotationSweepObject2DMakeGroups( "
1860                 << theObject << ", "
1861                 << theAxis << ", "
1862                 << theAngleInRadians << ", "
1863                 << theNbOfSteps << ", "
1864                 << theTolerance << " )";
1865   }
1866   return aGroups;
1867 }
1868
1869
1870 //=======================================================================
1871 //function : extrusionSweep
1872 //purpose  :
1873 //=======================================================================
1874
1875 SMESH::ListOfGroups*
1876 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
1877                                    const SMESH::DirStruct &  theStepVector,
1878                                    CORBA::Long               theNbOfSteps,
1879                                    bool                      theMakeGroups,
1880                                    const SMDSAbs_ElementType theElementType)
1881 {
1882   initData();
1883
1884   try {
1885 #ifdef NO_CAS_CATCH
1886     OCC_CATCH_SIGNALS;
1887 #endif
1888     TIDSortedElemSet elements, copyElements;
1889     arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
1890
1891     const SMESH::PointStruct * P = &theStepVector.PS;
1892     gp_Vec stepVec( P->x, P->y, P->z );
1893
1894     TIDSortedElemSet* workElements = & elements;
1895
1896     SMDSAbs_ElementType aType = SMDSAbs_Face;
1897     //::SMESH_MeshEditor::ExtrusionFlags aFlag = ::SMESH_MeshEditor::ExtrusionFlags::EXTRUSION_FLAG_BOUNDARY;
1898     if (theElementType == SMDSAbs_Node)
1899     {
1900       aType = SMDSAbs_Edge;
1901       //aFlag = ::SMESH_MeshEditor::ExtrusionFlags::EXTRUSION_FLAG_SEW;
1902     }
1903     TPreviewMesh      tmpMesh( aType );
1904     SMESH_Mesh* mesh = myMesh;
1905
1906     if ( myPreviewMode ) {
1907       SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
1908       tmpMesh.Copy( elements, copyElements, select, avoid );
1909       mesh = &tmpMesh;
1910       workElements = & copyElements;
1911       theMakeGroups = false;
1912     }
1913
1914     TElemOfElemListMap aHystory;
1915     ::SMESH_MeshEditor anEditor( mesh );
1916     ::SMESH_MeshEditor::PGroupIDs groupIds = 
1917         anEditor.ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
1918
1919     myMesh->GetMeshDS()->Modified();
1920     storeResult(anEditor);
1921
1922     return theMakeGroups ? getGroups(groupIds.get()) : 0;
1923
1924   } catch(Standard_Failure) {
1925     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1926     INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
1927   }
1928   return 0;
1929 }
1930
1931 //=======================================================================
1932 //function : ExtrusionSweep
1933 //purpose  :
1934 //=======================================================================
1935
1936 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
1937                                         const SMESH::DirStruct &  theStepVector,
1938                                         CORBA::Long               theNbOfSteps)
1939 {
1940   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
1941   if (!myPreviewMode) {
1942     TPythonDump() << this << ".ExtrusionSweep( "
1943                   << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1944   }
1945 }
1946
1947 //=======================================================================
1948 //function : ExtrusionSweep0D
1949 //purpose  :
1950 //=======================================================================
1951
1952 void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElements,
1953                                         const SMESH::DirStruct &  theStepVector,
1954                                         CORBA::Long               theNbOfSteps)
1955 {
1956   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
1957   if (!myPreviewMode) {
1958     TPythonDump() << this << ".ExtrusionSweep0D( "
1959                   << theIDsOfElements << ", " << theStepVector <<", " << theNbOfSteps << " )";
1960   }
1961 }
1962
1963 //=======================================================================
1964 //function : ExtrusionSweepObject
1965 //purpose  :
1966 //=======================================================================
1967
1968 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
1969                                               const SMESH::DirStruct &  theStepVector,
1970                                               CORBA::Long               theNbOfSteps)
1971 {
1972   SMESH::long_array_var anElementsId = theObject->GetIDs();
1973   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
1974   if (!myPreviewMode) {
1975     TPythonDump() << this << ".ExtrusionSweepObject( "
1976                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1977   }
1978 }
1979
1980 //=======================================================================
1981 //function : ExtrusionSweepObject0D
1982 //purpose  :
1983 //=======================================================================
1984
1985 void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObject,
1986                                                 const SMESH::DirStruct &  theStepVector,
1987                                                 CORBA::Long               theNbOfSteps)
1988 {
1989   SMESH::long_array_var anElementsId = theObject->GetIDs();
1990   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
1991   if ( !myPreviewMode ) {
1992     TPythonDump() << this << ".ExtrusionSweepObject0D( "
1993                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
1994   }
1995 }
1996
1997 //=======================================================================
1998 //function : ExtrusionSweepObject1D
1999 //purpose  :
2000 //=======================================================================
2001
2002 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2003                                                 const SMESH::DirStruct &  theStepVector,
2004                                                 CORBA::Long               theNbOfSteps)
2005 {
2006   SMESH::long_array_var anElementsId = theObject->GetIDs();
2007   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
2008   if ( !myPreviewMode ) {
2009     TPythonDump() << this << ".ExtrusionSweepObject1D( "
2010                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
2011   }
2012 }
2013
2014 //=======================================================================
2015 //function : ExtrusionSweepObject2D
2016 //purpose  :
2017 //=======================================================================
2018
2019 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2020                                                 const SMESH::DirStruct &  theStepVector,
2021                                                 CORBA::Long               theNbOfSteps)
2022 {
2023   SMESH::long_array_var anElementsId = theObject->GetIDs();
2024   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
2025   if ( !myPreviewMode ) {
2026     TPythonDump() << this << ".ExtrusionSweepObject2D( "
2027                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
2028   }
2029 }
2030
2031 //=======================================================================
2032 //function : ExtrusionSweepMakeGroups
2033 //purpose  :
2034 //=======================================================================
2035
2036 SMESH::ListOfGroups*
2037 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2038                                              const SMESH::DirStruct&  theStepVector,
2039                                              CORBA::Long              theNbOfSteps)
2040 {
2041   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2042
2043   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true);
2044
2045   if (!myPreviewMode) {
2046     DumpGroupsList(aPythonDump, aGroups);
2047     aPythonDump << this << ".ExtrusionSweepMakeGroups( " << theIDsOfElements
2048                 << ", " << theStepVector <<", " << theNbOfSteps << " )";
2049   }
2050   return aGroups;
2051 }
2052
2053 //=======================================================================
2054 //function : ExtrusionSweepMakeGroups0D
2055 //purpose  :
2056 //=======================================================================
2057
2058 SMESH::ListOfGroups*
2059 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOfElements,
2060                                              const SMESH::DirStruct&  theStepVector,
2061                                              CORBA::Long              theNbOfSteps)
2062 {
2063   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2064
2065   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true,SMDSAbs_Node);
2066
2067   if (!myPreviewMode) {
2068     DumpGroupsList(aPythonDump, aGroups);
2069     aPythonDump << this << ".ExtrusionSweepMakeGroups0D( " << theIDsOfElements
2070                 << ", " << theStepVector <<", " << theNbOfSteps << " )";
2071   }
2072   return aGroups;
2073 }
2074
2075 //=======================================================================
2076 //function : ExtrusionSweepObjectMakeGroups
2077 //purpose  :
2078 //=======================================================================
2079
2080 SMESH::ListOfGroups*
2081 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2082                                                    const SMESH::DirStruct&   theStepVector,
2083                                                    CORBA::Long               theNbOfSteps)
2084 {
2085   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2086
2087   SMESH::long_array_var anElementsId = theObject->GetIDs();
2088   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector, theNbOfSteps, true);
2089
2090   if (!myPreviewMode) {
2091     DumpGroupsList(aPythonDump, aGroups);
2092     aPythonDump << this << ".ExtrusionSweepObjectMakeGroups( " << theObject
2093                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2094   }
2095   return aGroups;
2096 }
2097
2098 //=======================================================================
2099 //function : ExtrusionSweepObject0DMakeGroups
2100 //purpose  :
2101 //=======================================================================
2102
2103 SMESH::ListOfGroups*
2104 SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2105                                                      const SMESH::DirStruct&   theStepVector,
2106                                                      CORBA::Long               theNbOfSteps)
2107 {
2108   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2109
2110   SMESH::long_array_var anElementsId = theObject->GetIDs();
2111   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2112                                                  theNbOfSteps, true, SMDSAbs_Node);
2113   if (!myPreviewMode) {
2114     DumpGroupsList(aPythonDump, aGroups);
2115     aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
2116                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2117   }
2118   return aGroups;
2119 }
2120
2121 //=======================================================================
2122 //function : ExtrusionSweepObject1DMakeGroups
2123 //purpose  :
2124 //=======================================================================
2125
2126 SMESH::ListOfGroups*
2127 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2128                                                      const SMESH::DirStruct&   theStepVector,
2129                                                      CORBA::Long               theNbOfSteps)
2130 {
2131   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2132
2133   SMESH::long_array_var anElementsId = theObject->GetIDs();
2134   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2135                                                  theNbOfSteps, true, SMDSAbs_Edge);
2136   if (!myPreviewMode) {
2137     DumpGroupsList(aPythonDump, aGroups);
2138     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
2139                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2140   }
2141   return aGroups;
2142 }
2143
2144 //=======================================================================
2145 //function : ExtrusionSweepObject2DMakeGroups
2146 //purpose  :
2147 //=======================================================================
2148
2149 SMESH::ListOfGroups*
2150 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2151                                                      const SMESH::DirStruct&   theStepVector,
2152                                                      CORBA::Long               theNbOfSteps)
2153 {
2154   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2155
2156   SMESH::long_array_var anElementsId = theObject->GetIDs();
2157   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2158                                                  theNbOfSteps, true, SMDSAbs_Face);
2159   if (!myPreviewMode) {
2160     DumpGroupsList(aPythonDump, aGroups);
2161     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
2162                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2163   }
2164   return aGroups;
2165 }
2166
2167
2168 //=======================================================================
2169 //function : advancedExtrusion
2170 //purpose  :
2171 //=======================================================================
2172
2173 SMESH::ListOfGroups*
2174 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
2175                                       const SMESH::DirStruct &  theStepVector,
2176                                       CORBA::Long               theNbOfSteps,
2177                                       CORBA::Long               theExtrFlags,
2178                                       CORBA::Double             theSewTolerance,
2179                                       const bool                theMakeGroups)
2180 {
2181   initData();
2182
2183   TIDSortedElemSet elements;
2184   arrayToSet(theIDsOfElements, GetMeshDS(), elements);
2185
2186   const SMESH::PointStruct * P = &theStepVector.PS;
2187   gp_Vec stepVec( P->x, P->y, P->z );
2188
2189   ::SMESH_MeshEditor anEditor( myMesh );
2190   TElemOfElemListMap aHystory;
2191   ::SMESH_MeshEditor::PGroupIDs groupIds =
2192       anEditor.ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
2193                                theMakeGroups, theExtrFlags, theSewTolerance);
2194   storeResult(anEditor);
2195
2196   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2197 }
2198
2199 //=======================================================================
2200 //function : AdvancedExtrusion
2201 //purpose  :
2202 //=======================================================================
2203
2204 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2205                                            const SMESH::DirStruct &  theStepVector,
2206                                            CORBA::Long               theNbOfSteps,
2207                                            CORBA::Long               theExtrFlags,
2208                                            CORBA::Double             theSewTolerance)
2209 {
2210   if ( !myPreviewMode ) {
2211     TPythonDump() << "stepVector = " << theStepVector;
2212     TPythonDump() << this << ".AdvancedExtrusion("
2213                   << theIDsOfElements
2214                   << ", stepVector, "
2215                   << theNbOfSteps << ","
2216                   << theExtrFlags << ", "
2217                   << theSewTolerance <<  " )";
2218   }
2219   advancedExtrusion( theIDsOfElements,
2220                      theStepVector,
2221                      theNbOfSteps,
2222                      theExtrFlags,
2223                      theSewTolerance,
2224                      false);
2225 }
2226
2227 //=======================================================================
2228 //function : AdvancedExtrusionMakeGroups
2229 //purpose  :
2230 //=======================================================================
2231 SMESH::ListOfGroups*
2232 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
2233                                                 const SMESH::DirStruct&  theStepVector,
2234                                                 CORBA::Long              theNbOfSteps,
2235                                                 CORBA::Long              theExtrFlags,
2236                                                 CORBA::Double            theSewTolerance)
2237 {
2238   if (!myPreviewMode) {
2239     TPythonDump() << "stepVector = " << theStepVector;
2240   }
2241   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2242
2243   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
2244                                                      theStepVector,
2245                                                      theNbOfSteps,
2246                                                      theExtrFlags,
2247                                                      theSewTolerance,
2248                                                      true);
2249
2250   if (!myPreviewMode) {
2251     DumpGroupsList(aPythonDump, aGroups);
2252     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
2253                 << theIDsOfElements
2254                 << ", stepVector, "
2255                 << theNbOfSteps << ","
2256                 << theExtrFlags << ", "
2257                 << theSewTolerance <<  " )";
2258   }
2259   return aGroups;
2260 }
2261
2262
2263 //================================================================================
2264 /*!
2265  * \brief Convert extrusion error to IDL enum
2266  */
2267 //================================================================================
2268
2269 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2270
2271 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
2272 {
2273   switch ( e ) {
2274     RETCASE( EXTR_OK );
2275     RETCASE( EXTR_NO_ELEMENTS );
2276     RETCASE( EXTR_PATH_NOT_EDGE );
2277     RETCASE( EXTR_BAD_PATH_SHAPE );
2278     RETCASE( EXTR_BAD_STARTING_NODE );
2279     RETCASE( EXTR_BAD_ANGLES_NUMBER );
2280     RETCASE( EXTR_CANT_GET_TANGENT );
2281   }
2282   return SMESH::SMESH_MeshEditor::EXTR_OK;
2283 }
2284
2285
2286 //=======================================================================
2287 //function : extrusionAlongPath
2288 //purpose  :
2289 //=======================================================================
2290 SMESH::ListOfGroups*
2291 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2292                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2293                                        GEOM::GEOM_Object_ptr       thePathShape,
2294                                        CORBA::Long                 theNodeStart,
2295                                        CORBA::Boolean              theHasAngles,
2296                                        const SMESH::double_array & theAngles,
2297                                        CORBA::Boolean              theHasRefPoint,
2298                                        const SMESH::PointStruct &  theRefPoint,
2299                                        const bool                  theMakeGroups,
2300                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
2301                                        const SMDSAbs_ElementType   theElementType)
2302 {
2303   MESSAGE("extrusionAlongPath");
2304   initData();
2305
2306   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
2307     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2308     return 0;
2309   }
2310   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2311
2312   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2313   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2314
2315   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
2316     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2317     return 0;
2318   }
2319
2320   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
2321   if ( !nodeStart ) {
2322     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2323     return 0;
2324   }
2325
2326   TIDSortedElemSet elements;
2327   arrayToSet(theIDsOfElements, GetMeshDS(), elements, theElementType);
2328
2329   list<double> angles;
2330   for (int i = 0; i < theAngles.length(); i++) {
2331     angles.push_back( theAngles[i] );
2332   }
2333
2334   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
2335
2336   int nbOldGroups = myMesh->NbGroup();
2337
2338   ::SMESH_MeshEditor anEditor( myMesh );
2339   ::SMESH_MeshEditor::Extrusion_Error error =
2340       anEditor.ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
2341                                     theHasAngles, angles, false,
2342                                     theHasRefPoint, refPnt, theMakeGroups );
2343   myMesh->GetMeshDS()->Modified();
2344   storeResult(anEditor);
2345   theError = convExtrError( error );
2346
2347   if ( theMakeGroups ) {
2348     list<int> groupIDs = myMesh->GetGroupIds();
2349     list<int>::iterator newBegin = groupIDs.begin();
2350     std::advance( newBegin, nbOldGroups ); // skip old groups
2351     groupIDs.erase( groupIDs.begin(), newBegin );
2352     return getGroups( & groupIDs );
2353   }
2354   return 0;
2355 }
2356
2357
2358 //=======================================================================
2359 //function : extrusionAlongPathX
2360 //purpose  :
2361 //=======================================================================
2362 SMESH::ListOfGroups*
2363 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
2364                                         SMESH::SMESH_IDSource_ptr  Path,
2365                                         CORBA::Long                NodeStart,
2366                                         CORBA::Boolean             HasAngles,
2367                                         const SMESH::double_array& Angles,
2368                                         CORBA::Boolean             LinearVariation,
2369                                         CORBA::Boolean             HasRefPoint,
2370                                         const SMESH::PointStruct&  RefPoint,
2371                                         bool                       MakeGroups,
2372                                         const SMDSAbs_ElementType  ElementType,
2373                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
2374 {
2375   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
2376
2377   initData();
2378
2379   list<double> angles;
2380   for (int i = 0; i < Angles.length(); i++) {
2381     angles.push_back( Angles[i] );
2382   }
2383   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
2384   int nbOldGroups = myMesh->NbGroup();
2385
2386   if ( Path->_is_nil() ) {
2387     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2388     return EmptyGr;
2389   }
2390
2391   TIDSortedElemSet elements, copyElements;
2392   arrayToSet(IDsOfElements, GetMeshDS(), elements, ElementType);
2393
2394   TIDSortedElemSet* workElements = &elements;
2395   TPreviewMesh      tmpMesh( SMDSAbs_Face );
2396   SMESH_Mesh*       mesh = myMesh;
2397
2398   if ( myPreviewMode )
2399   {
2400     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2401     tmpMesh.Copy( elements, copyElements, select, avoid );
2402     mesh = &tmpMesh;
2403     workElements = & copyElements;
2404     MakeGroups = false;
2405   }
2406
2407   ::SMESH_MeshEditor anEditor( mesh );
2408   ::SMESH_MeshEditor::Extrusion_Error error;
2409
2410   if ( SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path ))
2411   {
2412     // path as mesh
2413     SMDS_MeshNode* aNodeStart =
2414       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2415     if ( !aNodeStart ) {
2416       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2417       return EmptyGr;
2418     }
2419     error = anEditor.ExtrusionAlongTrack( *workElements, &(aMeshImp->GetImpl()), aNodeStart,
2420                                           HasAngles, angles, LinearVariation,
2421                                           HasRefPoint, refPnt, MakeGroups );
2422     myMesh->GetMeshDS()->Modified();
2423   }
2424   else if ( SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path ))
2425   {
2426     // path as submesh
2427     SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
2428     aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
2429     SMDS_MeshNode* aNodeStart =
2430       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
2431     if ( !aNodeStart ) {
2432       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
2433       return EmptyGr;
2434     }
2435     SMESH_subMesh* aSubMesh =
2436       aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
2437     error = anEditor.ExtrusionAlongTrack( *workElements, aSubMesh, aNodeStart,
2438                                           HasAngles, angles, LinearVariation,
2439                                           HasRefPoint, refPnt, MakeGroups );
2440     myMesh->GetMeshDS()->Modified();
2441   }
2442   else if ( SMESH::DownCast<SMESH_Group_i*>( Path ))
2443   {
2444     // path as group of 1D elements
2445     // ????????
2446   }
2447   else
2448   {
2449     // invalid path
2450     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2451     return EmptyGr;
2452   }
2453
2454   storeResult(anEditor);
2455   Error = convExtrError( error );
2456
2457   if ( MakeGroups ) {
2458     list<int> groupIDs = myMesh->GetGroupIds();
2459     list<int>::iterator newBegin = groupIDs.begin();
2460     std::advance( newBegin, nbOldGroups ); // skip old groups
2461     groupIDs.erase( groupIDs.begin(), newBegin );
2462     return getGroups( & groupIDs );
2463   }
2464   return EmptyGr;
2465 }
2466
2467
2468 //=======================================================================
2469 //function : ExtrusionAlongPath
2470 //purpose  :
2471 //=======================================================================
2472 SMESH::SMESH_MeshEditor::Extrusion_Error
2473 SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2474                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2475                                        GEOM::GEOM_Object_ptr       thePathShape,
2476                                        CORBA::Long                 theNodeStart,
2477                                        CORBA::Boolean              theHasAngles,
2478                                        const SMESH::double_array & theAngles,
2479                                        CORBA::Boolean              theHasRefPoint,
2480                                        const SMESH::PointStruct &  theRefPoint)
2481 {
2482   MESSAGE("ExtrusionAlongPath");
2483   if ( !myPreviewMode ) {
2484     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
2485                   << theIDsOfElements << ", "
2486                   << thePathMesh      << ", "
2487                   << thePathShape     << ", "
2488                   << theNodeStart     << ", "
2489                   << theHasAngles     << ", "
2490                   << theAngles        << ", "
2491                   << theHasRefPoint   << ", "
2492                   << "SMESH.PointStruct( "
2493                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2494                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2495                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2496   }
2497   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2498   extrusionAlongPath( theIDsOfElements,
2499                       thePathMesh,
2500                       thePathShape,
2501                       theNodeStart,
2502                       theHasAngles,
2503                       theAngles,
2504                       theHasRefPoint,
2505                       theRefPoint,
2506                       false,
2507                       anError);
2508   return anError;
2509 }
2510
2511 //=======================================================================
2512 //function : ExtrusionAlongPathObject
2513 //purpose  :
2514 //=======================================================================
2515 SMESH::SMESH_MeshEditor::Extrusion_Error
2516 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
2517                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
2518                                              GEOM::GEOM_Object_ptr       thePathShape,
2519                                              CORBA::Long                 theNodeStart,
2520                                              CORBA::Boolean              theHasAngles,
2521                                              const SMESH::double_array & theAngles,
2522                                              CORBA::Boolean              theHasRefPoint,
2523                                              const SMESH::PointStruct &  theRefPoint)
2524 {
2525   if ( !myPreviewMode ) {
2526     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
2527                   << theObject        << ", "
2528                   << thePathMesh      << ", "
2529                   << thePathShape     << ", "
2530                   << theNodeStart     << ", "
2531                   << theHasAngles     << ", "
2532                   << theAngles        << ", "
2533                   << theHasRefPoint   << ", "
2534                   << "SMESH.PointStruct( "
2535                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2536                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2537                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2538   }
2539   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2540   SMESH::long_array_var anElementsId = theObject->GetIDs();
2541   extrusionAlongPath( anElementsId,
2542                       thePathMesh,
2543                       thePathShape,
2544                       theNodeStart,
2545                       theHasAngles,
2546                       theAngles,
2547                       theHasRefPoint,
2548                       theRefPoint,
2549                       false,
2550                       anError);
2551   return anError;
2552 }
2553
2554 //=======================================================================
2555 //function : ExtrusionAlongPathObject1D
2556 //purpose  :
2557 //=======================================================================
2558 SMESH::SMESH_MeshEditor::Extrusion_Error
2559 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
2560                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2561                                                GEOM::GEOM_Object_ptr       thePathShape,
2562                                                CORBA::Long                 theNodeStart,
2563                                                CORBA::Boolean              theHasAngles,
2564                                                const SMESH::double_array & theAngles,
2565                                                CORBA::Boolean              theHasRefPoint,
2566                                                const SMESH::PointStruct &  theRefPoint)
2567 {
2568   if ( !myPreviewMode ) {
2569     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
2570                   << theObject        << ", "
2571                   << thePathMesh      << ", "
2572                   << thePathShape     << ", "
2573                   << theNodeStart     << ", "
2574                   << theHasAngles     << ", "
2575                   << theAngles        << ", "
2576                   << theHasRefPoint   << ", "
2577                   << "SMESH.PointStruct( "
2578                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2579                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2580                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2581   }
2582   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2583   SMESH::long_array_var anElementsId = theObject->GetIDs();
2584   extrusionAlongPath( anElementsId,
2585                       thePathMesh,
2586                       thePathShape,
2587                       theNodeStart,
2588                       theHasAngles,
2589                       theAngles,
2590                       theHasRefPoint,
2591                       theRefPoint,
2592                       false,
2593                       anError,
2594                       SMDSAbs_Edge);
2595   return anError;
2596 }
2597
2598 //=======================================================================
2599 //function : ExtrusionAlongPathObject2D
2600 //purpose  :
2601 //=======================================================================
2602 SMESH::SMESH_MeshEditor::Extrusion_Error
2603 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
2604                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
2605                                                GEOM::GEOM_Object_ptr       thePathShape,
2606                                                CORBA::Long                 theNodeStart,
2607                                                CORBA::Boolean              theHasAngles,
2608                                                const SMESH::double_array & theAngles,
2609                                                CORBA::Boolean              theHasRefPoint,
2610                                                const SMESH::PointStruct &  theRefPoint)
2611 {
2612   if ( !myPreviewMode ) {
2613     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
2614                   << theObject        << ", "
2615                   << thePathMesh      << ", "
2616                   << thePathShape     << ", "
2617                   << theNodeStart     << ", "
2618                   << theHasAngles     << ", "
2619                   << theAngles        << ", "
2620                   << theHasRefPoint   << ", "
2621                   << "SMESH.PointStruct( "
2622                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2623                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2624                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2625   }
2626   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
2627   SMESH::long_array_var anElementsId = theObject->GetIDs();
2628   extrusionAlongPath( anElementsId,
2629                       thePathMesh,
2630                       thePathShape,
2631                       theNodeStart,
2632                       theHasAngles,
2633                       theAngles,
2634                       theHasRefPoint,
2635                       theRefPoint,
2636                       false,
2637                       anError,
2638                       SMDSAbs_Face);
2639   return anError;
2640 }
2641
2642
2643 //=======================================================================
2644 //function : ExtrusionAlongPathMakeGroups
2645 //purpose  :
2646 //=======================================================================
2647 SMESH::ListOfGroups*
2648 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
2649                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
2650                                                  GEOM::GEOM_Object_ptr      thePathShape,
2651                                                  CORBA::Long                theNodeStart,
2652                                                  CORBA::Boolean             theHasAngles,
2653                                                  const SMESH::double_array& theAngles,
2654                                                  CORBA::Boolean             theHasRefPoint,
2655                                                  const SMESH::PointStruct&  theRefPoint,
2656                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2657 {
2658   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2659
2660   SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
2661                                                        thePathMesh,
2662                                                        thePathShape,
2663                                                        theNodeStart,
2664                                                        theHasAngles,
2665                                                        theAngles,
2666                                                        theHasRefPoint,
2667                                                        theRefPoint,
2668                                                        true,
2669                                                        Error);
2670   if (!myPreviewMode) {
2671     bool isDumpGroups = aGroups && aGroups->length() > 0;
2672     if (isDumpGroups)
2673       aPythonDump << "(" << aGroups << ", error)";
2674     else
2675       aPythonDump <<"error";
2676
2677     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
2678                << theIDsOfElements << ", "
2679                << thePathMesh      << ", "
2680                << thePathShape     << ", "
2681                << theNodeStart     << ", "
2682                << theHasAngles     << ", "
2683                << theAngles        << ", "
2684                << theHasRefPoint   << ", "
2685                << "SMESH.PointStruct( "
2686                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2687                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2688                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2689   }
2690   return aGroups;
2691 }
2692
2693 //=======================================================================
2694 //function : ExtrusionAlongPathObjectMakeGroups
2695 //purpose  :
2696 //=======================================================================
2697 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2698 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2699                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
2700                                    GEOM::GEOM_Object_ptr      thePathShape,
2701                                    CORBA::Long                theNodeStart,
2702                                    CORBA::Boolean             theHasAngles,
2703                                    const SMESH::double_array& theAngles,
2704                                    CORBA::Boolean             theHasRefPoint,
2705                                    const SMESH::PointStruct&  theRefPoint,
2706                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2707 {
2708   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2709
2710   SMESH::long_array_var anElementsId = theObject->GetIDs();
2711   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2712                                                       thePathMesh,
2713                                                       thePathShape,
2714                                                       theNodeStart,
2715                                                       theHasAngles,
2716                                                       theAngles,
2717                                                       theHasRefPoint,
2718                                                       theRefPoint,
2719                                                       true,
2720                                                       Error);
2721
2722   if (!myPreviewMode) {
2723     bool isDumpGroups = aGroups && aGroups->length() > 0;
2724     if (isDumpGroups)
2725       aPythonDump << "(" << aGroups << ", error)";
2726     else
2727       aPythonDump <<"error";
2728
2729     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
2730                 << theObject << ", "
2731                 << thePathMesh      << ", "
2732                 << thePathShape     << ", "
2733                 << theNodeStart     << ", "
2734                 << theHasAngles     << ", "
2735                 << theAngles        << ", "
2736                 << theHasRefPoint   << ", "
2737                 << "SMESH.PointStruct( "
2738                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2739                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2740                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2741   }
2742   return aGroups;
2743 }
2744
2745 //=======================================================================
2746 //function : ExtrusionAlongPathObject1DMakeGroups
2747 //purpose  :
2748 //=======================================================================
2749 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2750 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2751                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2752                                      GEOM::GEOM_Object_ptr      thePathShape,
2753                                      CORBA::Long                theNodeStart,
2754                                      CORBA::Boolean             theHasAngles,
2755                                      const SMESH::double_array& theAngles,
2756                                      CORBA::Boolean             theHasRefPoint,
2757                                      const SMESH::PointStruct&  theRefPoint,
2758                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2759 {
2760   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2761
2762   SMESH::long_array_var anElementsId = theObject->GetIDs();
2763   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2764                                                       thePathMesh,
2765                                                       thePathShape,
2766                                                       theNodeStart,
2767                                                       theHasAngles,
2768                                                       theAngles,
2769                                                       theHasRefPoint,
2770                                                       theRefPoint,
2771                                                       true,
2772                                                       Error,
2773                                                       SMDSAbs_Edge);
2774
2775   if (!myPreviewMode) {
2776     bool isDumpGroups = aGroups && aGroups->length() > 0;
2777     if (isDumpGroups)
2778       aPythonDump << "(" << aGroups << ", error)";
2779     else
2780       aPythonDump << "error";
2781
2782     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
2783                 << theObject << ", "
2784                 << thePathMesh      << ", "
2785                 << thePathShape     << ", "
2786                 << theNodeStart     << ", "
2787                 << theHasAngles     << ", "
2788                 << theAngles        << ", "
2789                 << theHasRefPoint   << ", "
2790                 << "SMESH.PointStruct( "
2791                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2792                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2793                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2794   }
2795   return aGroups;
2796 }
2797
2798 //=======================================================================
2799 //function : ExtrusionAlongPathObject2DMakeGroups
2800 //purpose  :
2801 //=======================================================================
2802 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2803 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
2804                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
2805                                      GEOM::GEOM_Object_ptr      thePathShape,
2806                                      CORBA::Long                theNodeStart,
2807                                      CORBA::Boolean             theHasAngles,
2808                                      const SMESH::double_array& theAngles,
2809                                      CORBA::Boolean             theHasRefPoint,
2810                                      const SMESH::PointStruct&  theRefPoint,
2811                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2812 {
2813   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2814
2815   SMESH::long_array_var anElementsId = theObject->GetIDs();
2816   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
2817                                                       thePathMesh,
2818                                                       thePathShape,
2819                                                       theNodeStart,
2820                                                       theHasAngles,
2821                                                       theAngles,
2822                                                       theHasRefPoint,
2823                                                       theRefPoint,
2824                                                       true,
2825                                                       Error,
2826                                                       SMDSAbs_Face);
2827
2828   if (!myPreviewMode) {
2829     bool isDumpGroups = aGroups && aGroups->length() > 0;
2830     if (isDumpGroups)
2831       aPythonDump << "(" << aGroups << ", error)";
2832     else
2833       aPythonDump << "error";
2834
2835     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
2836                 << theObject << ", "
2837                 << thePathMesh      << ", "
2838                 << thePathShape     << ", "
2839                 << theNodeStart     << ", "
2840                 << theHasAngles     << ", "
2841                 << theAngles        << ", "
2842                 << theHasRefPoint   << ", "
2843                 << "SMESH.PointStruct( "
2844                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
2845                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
2846                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
2847   }
2848   return aGroups;
2849 }
2850
2851
2852 //=======================================================================
2853 //function : ExtrusionAlongPathObjX
2854 //purpose  :
2855 //=======================================================================
2856 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2857 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
2858                        SMESH::SMESH_IDSource_ptr  Path,
2859                        CORBA::Long                NodeStart,
2860                        CORBA::Boolean             HasAngles,
2861                        const SMESH::double_array& Angles,
2862                        CORBA::Boolean             LinearVariation,
2863                        CORBA::Boolean             HasRefPoint,
2864                        const SMESH::PointStruct&  RefPoint,
2865                        CORBA::Boolean             MakeGroups,
2866                        SMESH::ElementType         ElemType,
2867                        SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2868 {
2869   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2870
2871   SMESH::long_array_var anElementsId = Object->GetIDs();
2872   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
2873                                                       Path,
2874                                                       NodeStart,
2875                                                       HasAngles,
2876                                                       Angles,
2877                                                       LinearVariation,
2878                                                       HasRefPoint,
2879                                                       RefPoint,
2880                                                       MakeGroups,
2881                                                       (SMDSAbs_ElementType)ElemType,
2882                                                       Error);
2883
2884   if (!myPreviewMode) {
2885     bool isDumpGroups = aGroups && aGroups->length() > 0;
2886     if (isDumpGroups)
2887       aPythonDump << "(" << *aGroups << ", error)";
2888     else
2889       aPythonDump << "error";
2890
2891     aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
2892                 << Object      << ", "
2893                 << Path        << ", "
2894                 << NodeStart   << ", "
2895                 << HasAngles   << ", "
2896                 << Angles      << ", "
2897                 << LinearVariation << ", "
2898                 << HasRefPoint << ", "
2899                 << "SMESH.PointStruct( "
2900                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2901                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2902                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2903                 << MakeGroups << ", "
2904                 << ElemType << " )";
2905   }
2906   return aGroups;
2907 }
2908
2909
2910 //=======================================================================
2911 //function : ExtrusionAlongPathX
2912 //purpose  :
2913 //=======================================================================
2914 SMESH::ListOfGroups* SMESH_MeshEditor_i::
2915 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
2916                     SMESH::SMESH_IDSource_ptr  Path,
2917                     CORBA::Long                NodeStart,
2918                     CORBA::Boolean             HasAngles,
2919                     const SMESH::double_array& Angles,
2920                     CORBA::Boolean             LinearVariation,
2921                     CORBA::Boolean             HasRefPoint,
2922                     const SMESH::PointStruct&  RefPoint,
2923                     CORBA::Boolean             MakeGroups,
2924                     SMESH::ElementType         ElemType,
2925                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
2926 {
2927   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2928
2929   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
2930                                                       Path,
2931                                                       NodeStart,
2932                                                       HasAngles,
2933                                                       Angles,
2934                                                       LinearVariation,
2935                                                       HasRefPoint,
2936                                                       RefPoint,
2937                                                       MakeGroups,
2938                                                       (SMDSAbs_ElementType)ElemType,
2939                                                       Error);
2940
2941   if (!myPreviewMode) {
2942     bool isDumpGroups = aGroups && aGroups->length() > 0;
2943     if (isDumpGroups)
2944       aPythonDump << "(" << *aGroups << ", error)";
2945     else
2946       aPythonDump <<"error";
2947
2948     aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
2949                 << IDsOfElements << ", "
2950                 << Path        << ", "
2951                 << NodeStart   << ", "
2952                 << HasAngles   << ", "
2953                 << Angles      << ", "
2954                 << LinearVariation << ", "
2955                 << HasRefPoint << ", "
2956                 << "SMESH.PointStruct( "
2957                 << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
2958                 << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
2959                 << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
2960                 << MakeGroups << ", "
2961                 << ElemType << " )";
2962   }
2963   return aGroups;
2964 }
2965
2966
2967 //================================================================================
2968 /*!
2969  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
2970  * of given angles along path steps
2971  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
2972  *                which proceeds the extrusion
2973  * \param PathShape is shape(edge); as the mesh can be complex, the edge
2974  *                 is used to define the sub-mesh for the path
2975  */
2976 //================================================================================
2977
2978 SMESH::double_array*
2979 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
2980                                           GEOM::GEOM_Object_ptr       thePathShape,
2981                                           const SMESH::double_array & theAngles)
2982 {
2983   SMESH::double_array_var aResult = new SMESH::double_array();
2984   int nbAngles = theAngles.length();
2985   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
2986   {
2987     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
2988     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
2989     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
2990     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
2991       return aResult._retn();
2992     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
2993     if ( nbSteps == nbAngles )
2994     {
2995       aResult.inout() = theAngles;
2996     }
2997     else
2998     {
2999       aResult->length( nbSteps );
3000       double rAn2St = double( nbAngles ) / double( nbSteps );
3001       double angPrev = 0, angle;
3002       for ( int iSt = 0; iSt < nbSteps; ++iSt )
3003       {
3004         double angCur = rAn2St * ( iSt+1 );
3005         double angCurFloor  = floor( angCur );
3006         double angPrevFloor = floor( angPrev );
3007         if ( angPrevFloor == angCurFloor )
3008           angle = rAn2St * theAngles[ int( angCurFloor ) ];
3009         else
3010         {
3011           int iP = int( angPrevFloor );
3012           double angPrevCeil = ceil(angPrev);
3013           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3014
3015           int iC = int( angCurFloor );
3016           if ( iC < nbAngles )
3017             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3018
3019           iP = int( angPrevCeil );
3020           while ( iC-- > iP )
3021             angle += theAngles[ iC ];
3022         }
3023         aResult[ iSt ] = angle;
3024         angPrev = angCur;
3025       }
3026     }
3027   }
3028   // Update Python script
3029   TPythonDump() << "rotAngles = " << theAngles;
3030   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3031                 << thePathMesh  << ", "
3032                 << thePathShape << ", "
3033                 << "rotAngles )";
3034
3035   return aResult._retn();
3036 }
3037
3038
3039 //=======================================================================
3040 //function : mirror
3041 //purpose  :
3042 //=======================================================================
3043
3044 SMESH::ListOfGroups*
3045 SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
3046                            const SMESH::AxisStruct &           theAxis,
3047                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3048                            CORBA::Boolean                      theCopy,
3049                            bool                                theMakeGroups,
3050                            ::SMESH_Mesh*                       theTargetMesh)
3051 {
3052   initData();
3053
3054   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3055   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3056
3057   if ( theTargetMesh )
3058     theCopy = false;
3059
3060   gp_Trsf aTrsf;
3061   switch ( theMirrorType ) {
3062   case  SMESH::SMESH_MeshEditor::POINT:
3063     aTrsf.SetMirror( P );
3064     break;
3065   case  SMESH::SMESH_MeshEditor::AXIS:
3066     aTrsf.SetMirror( gp_Ax1( P, V ));
3067     break;
3068   default:
3069     aTrsf.SetMirror( gp_Ax2( P, V ));
3070   }
3071
3072   TIDSortedElemSet  copyElements;
3073   TPreviewMesh      tmpMesh;
3074   TIDSortedElemSet* workElements = & theElements;
3075   SMESH_Mesh*       mesh = myMesh;
3076
3077   if ( myPreviewMode )
3078   {
3079     tmpMesh.Copy( theElements, copyElements);
3080     if ( !theCopy && !theTargetMesh )
3081     {
3082       TIDSortedElemSet elemsAround, elemsAroundCopy;
3083       getElementsAround( theElements, GetMeshDS(), elemsAround );
3084       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3085     }
3086     mesh = &tmpMesh;
3087     workElements = & copyElements;
3088     theMakeGroups = false;
3089   }
3090
3091   ::SMESH_MeshEditor anEditor( mesh );
3092   ::SMESH_MeshEditor::PGroupIDs groupIds =
3093       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3094
3095   if(theCopy || myPreviewMode)
3096     storeResult(anEditor); // store preview data or new elements
3097
3098   if ( !myPreviewMode )
3099   {
3100     if ( theTargetMesh )
3101     {
3102       theTargetMesh->GetMeshDS()->Modified();
3103     }
3104     else
3105     {
3106       myMesh->GetMeshDS()->Modified();
3107       myMesh->SetIsModified( true );
3108     }
3109   }
3110   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3111 }
3112
3113 //=======================================================================
3114 //function : Mirror
3115 //purpose  :
3116 //=======================================================================
3117
3118 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
3119                                 const SMESH::AxisStruct &           theAxis,
3120                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3121                                 CORBA::Boolean                      theCopy)
3122 {
3123   if ( !myPreviewMode ) {
3124     TPythonDump() << this << ".Mirror( "
3125                   << theIDsOfElements << ", "
3126                   << theAxis          << ", "
3127                   << mirrorTypeName(theMirrorType) << ", "
3128                   << theCopy          << " )";
3129   }
3130   if ( theIDsOfElements.length() > 0 )
3131   {
3132     TIDSortedElemSet elements;
3133     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3134     mirror(elements, theAxis, theMirrorType, theCopy, false);
3135   }
3136 }
3137
3138
3139 //=======================================================================
3140 //function : MirrorObject
3141 //purpose  :
3142 //=======================================================================
3143
3144 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
3145                                       const SMESH::AxisStruct &           theAxis,
3146                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3147                                       CORBA::Boolean                      theCopy)
3148 {
3149   if ( !myPreviewMode ) {
3150     TPythonDump() << this << ".MirrorObject( "
3151                   << theObject << ", "
3152                   << theAxis   << ", "
3153                   << mirrorTypeName(theMirrorType) << ", "
3154                   << theCopy   << " )";
3155   }
3156   TIDSortedElemSet elements;
3157
3158   bool emptyIfIsMesh = myPreviewMode ? false : true;
3159
3160   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3161     mirror(elements, theAxis, theMirrorType, theCopy, false);
3162 }
3163
3164 //=======================================================================
3165 //function : MirrorMakeGroups
3166 //purpose  :
3167 //=======================================================================
3168
3169 SMESH::ListOfGroups*
3170 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
3171                                      const SMESH::AxisStruct&            theMirror,
3172                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3173 {
3174   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3175
3176   SMESH::ListOfGroups * aGroups = 0;
3177   if ( theIDsOfElements.length() > 0 )
3178   {
3179     TIDSortedElemSet elements;
3180     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3181     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3182   }
3183   if (!myPreviewMode) {
3184     DumpGroupsList(aPythonDump, aGroups);
3185     aPythonDump << this << ".MirrorMakeGroups( "
3186                 << theIDsOfElements << ", "
3187                 << theMirror << ", "
3188                 << mirrorTypeName(theMirrorType) << " )";
3189   }
3190   return aGroups;
3191 }
3192
3193 //=======================================================================
3194 //function : MirrorObjectMakeGroups
3195 //purpose  :
3196 //=======================================================================
3197
3198 SMESH::ListOfGroups*
3199 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
3200                                            const SMESH::AxisStruct&            theMirror,
3201                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3202 {
3203   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3204
3205   SMESH::ListOfGroups * aGroups = 0;
3206   TIDSortedElemSet elements;
3207   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3208     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3209
3210   if (!myPreviewMode)
3211   {
3212     DumpGroupsList(aPythonDump,aGroups);
3213     aPythonDump << this << ".MirrorObjectMakeGroups( "
3214                 << theObject << ", "
3215                 << theMirror << ", "
3216                 << mirrorTypeName(theMirrorType) << " )";
3217   }
3218   return aGroups;
3219 }
3220
3221 //=======================================================================
3222 //function : MirrorMakeMesh
3223 //purpose  :
3224 //=======================================================================
3225
3226 SMESH::SMESH_Mesh_ptr
3227 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
3228                                    const SMESH::AxisStruct&            theMirror,
3229                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3230                                    CORBA::Boolean                      theCopyGroups,
3231                                    const char*                         theMeshName)
3232 {
3233   SMESH_Mesh_i* mesh_i;
3234   SMESH::SMESH_Mesh_var mesh;
3235   { // open new scope to dump "MakeMesh" command
3236     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3237
3238     TPythonDump pydump; // to prevent dump at mesh creation
3239
3240     mesh = makeMesh( theMeshName );
3241     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3242     if (mesh_i && theIDsOfElements.length() > 0 )
3243     {
3244       TIDSortedElemSet elements;
3245       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3246       mirror(elements, theMirror, theMirrorType,
3247              false, theCopyGroups, & mesh_i->GetImpl());
3248       mesh_i->CreateGroupServants();
3249     }
3250
3251     if (!myPreviewMode) {
3252       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3253              << theIDsOfElements << ", "
3254              << theMirror   << ", "
3255              << mirrorTypeName(theMirrorType) << ", "
3256              << theCopyGroups << ", '"
3257              << theMeshName << "' )";
3258     }
3259   }
3260
3261   //dump "GetGroups"
3262   if (!myPreviewMode && mesh_i)
3263     mesh_i->GetGroups();
3264
3265   return mesh._retn();
3266 }
3267
3268 //=======================================================================
3269 //function : MirrorObjectMakeMesh
3270 //purpose  :
3271 //=======================================================================
3272
3273 SMESH::SMESH_Mesh_ptr
3274 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
3275                                          const SMESH::AxisStruct&            theMirror,
3276                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3277                                          CORBA::Boolean                      theCopyGroups,
3278                                          const char*                         theMeshName)
3279 {
3280   SMESH_Mesh_i* mesh_i;
3281   SMESH::SMESH_Mesh_var mesh;
3282   { // open new scope to dump "MakeMesh" command
3283     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3284
3285     TPythonDump pydump; // to prevent dump at mesh creation
3286
3287     mesh = makeMesh( theMeshName );
3288     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3289     TIDSortedElemSet elements;
3290     if ( mesh_i &&
3291          idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3292     {
3293       mirror(elements, theMirror, theMirrorType,
3294              false, theCopyGroups, & mesh_i->GetImpl());
3295       mesh_i->CreateGroupServants();
3296     }
3297     if (!myPreviewMode) {
3298       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3299              << theObject << ", "
3300              << theMirror   << ", "
3301              << mirrorTypeName(theMirrorType) << ", "
3302              << theCopyGroups << ", '"
3303              << theMeshName << "' )";
3304     }
3305   }
3306
3307   //dump "GetGroups"
3308   if (!myPreviewMode && mesh_i)
3309     mesh_i->GetGroups();
3310
3311   return mesh._retn();
3312 }
3313
3314 //=======================================================================
3315 //function : translate
3316 //purpose  :
3317 //=======================================================================
3318
3319 SMESH::ListOfGroups*
3320 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
3321                               const SMESH::DirStruct &  theVector,
3322                               CORBA::Boolean            theCopy,
3323                               bool                      theMakeGroups,
3324                               ::SMESH_Mesh*             theTargetMesh)
3325 {
3326   initData();
3327
3328   if ( theTargetMesh )
3329     theCopy = false;
3330
3331   gp_Trsf aTrsf;
3332   const SMESH::PointStruct * P = &theVector.PS;
3333   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3334
3335   TIDSortedElemSet  copyElements;
3336   TIDSortedElemSet* workElements = &theElements;
3337   TPreviewMesh      tmpMesh;
3338   SMESH_Mesh*       mesh = myMesh;
3339
3340   if ( myPreviewMode )
3341   {
3342     tmpMesh.Copy( theElements, copyElements);
3343     if ( !theCopy && !theTargetMesh )
3344     {
3345       TIDSortedElemSet elemsAround, elemsAroundCopy;
3346       getElementsAround( theElements, GetMeshDS(), elemsAround );
3347       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3348     }
3349     mesh = &tmpMesh;
3350     workElements = & copyElements;
3351     theMakeGroups = false;
3352   }
3353
3354   ::SMESH_MeshEditor anEditor( mesh );
3355   ::SMESH_MeshEditor::PGroupIDs groupIds =
3356       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3357
3358   if(theCopy || myPreviewMode)
3359     storeResult(anEditor);
3360
3361   if ( !myPreviewMode )
3362   {
3363     if ( theTargetMesh )
3364     {
3365       theTargetMesh->GetMeshDS()->Modified();
3366     }
3367     else
3368     {
3369       myMesh->GetMeshDS()->Modified();
3370       myMesh->SetIsModified( true );
3371     }
3372   }
3373
3374   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3375 }
3376
3377 //=======================================================================
3378 //function : Translate
3379 //purpose  :
3380 //=======================================================================
3381
3382 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3383                                    const SMESH::DirStruct &  theVector,
3384                                    CORBA::Boolean            theCopy)
3385 {
3386   if (!myPreviewMode) {
3387     TPythonDump() << this << ".Translate( "
3388                   << theIDsOfElements << ", "
3389                   << theVector << ", "
3390                   << theCopy << " )";
3391   }
3392   if (theIDsOfElements.length()) {
3393     TIDSortedElemSet elements;
3394     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3395     translate(elements, theVector, theCopy, false);
3396   }
3397 }
3398
3399 //=======================================================================
3400 //function : TranslateObject
3401 //purpose  :
3402 //=======================================================================
3403
3404 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3405                                          const SMESH::DirStruct &  theVector,
3406                                          CORBA::Boolean            theCopy)
3407 {
3408   if (!myPreviewMode) {
3409     TPythonDump() << this << ".TranslateObject( "
3410                   << theObject << ", "
3411                   << theVector << ", "
3412                   << theCopy << " )";
3413   }
3414   TIDSortedElemSet elements;
3415
3416   bool emptyIfIsMesh = myPreviewMode ? false : true;
3417   
3418   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3419     translate(elements, theVector, theCopy, false);
3420 }
3421
3422 //=======================================================================
3423 //function : TranslateMakeGroups
3424 //purpose  :
3425 //=======================================================================
3426
3427 SMESH::ListOfGroups*
3428 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3429                                         const SMESH::DirStruct&  theVector)
3430 {
3431   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3432
3433   SMESH::ListOfGroups * aGroups = 0;
3434   if (theIDsOfElements.length()) {
3435     TIDSortedElemSet elements;
3436     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3437     aGroups = translate(elements,theVector,true,true);
3438   }
3439   if (!myPreviewMode) {
3440     DumpGroupsList(aPythonDump, aGroups);
3441     aPythonDump << this << ".TranslateMakeGroups( "
3442                 << theIDsOfElements << ", "
3443                 << theVector << " )";
3444   }
3445   return aGroups;
3446 }
3447
3448 //=======================================================================
3449 //function : TranslateObjectMakeGroups
3450 //purpose  :
3451 //=======================================================================
3452
3453 SMESH::ListOfGroups*
3454 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3455                                               const SMESH::DirStruct&   theVector)
3456 {
3457   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3458
3459   SMESH::ListOfGroups * aGroups = 0;
3460   TIDSortedElemSet elements;
3461   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3462     aGroups = translate(elements, theVector, true, true);
3463
3464   if (!myPreviewMode) {
3465     DumpGroupsList(aPythonDump, aGroups);
3466     aPythonDump << this << ".TranslateObjectMakeGroups( "
3467                 << theObject << ", "
3468                 << theVector << " )";
3469   }
3470   return aGroups;
3471 }
3472
3473 //=======================================================================
3474 //function : TranslateMakeMesh
3475 //purpose  :
3476 //=======================================================================
3477
3478 SMESH::SMESH_Mesh_ptr
3479 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3480                                       const SMESH::DirStruct&  theVector,
3481                                       CORBA::Boolean           theCopyGroups,
3482                                       const char*              theMeshName)
3483 {
3484   SMESH_Mesh_i* mesh_i;
3485   SMESH::SMESH_Mesh_var mesh;
3486
3487   { // open new scope to dump "MakeMesh" command
3488     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3489
3490     TPythonDump pydump; // to prevent dump at mesh creation
3491
3492     mesh = makeMesh( theMeshName );
3493     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3494
3495     if ( mesh_i && theIDsOfElements.length() )
3496     {
3497       TIDSortedElemSet elements;
3498       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3499       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3500       mesh_i->CreateGroupServants();
3501     }
3502
3503     if ( !myPreviewMode ) {
3504       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3505              << theIDsOfElements << ", "
3506              << theVector   << ", "
3507              << theCopyGroups << ", '"
3508              << theMeshName << "' )";
3509     }
3510   }
3511
3512   //dump "GetGroups"
3513   if (!myPreviewMode && mesh_i)
3514     mesh_i->GetGroups();
3515
3516   return mesh._retn();
3517 }
3518
3519 //=======================================================================
3520 //function : TranslateObjectMakeMesh
3521 //purpose  :
3522 //=======================================================================
3523
3524 SMESH::SMESH_Mesh_ptr
3525 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3526                                             const SMESH::DirStruct&   theVector,
3527                                             CORBA::Boolean            theCopyGroups,
3528                                             const char*               theMeshName)
3529 {
3530   SMESH_Mesh_i* mesh_i;
3531   SMESH::SMESH_Mesh_var mesh;
3532   { // open new scope to dump "MakeMesh" command
3533     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3534
3535     TPythonDump pydump; // to prevent dump at mesh creation
3536     mesh = makeMesh( theMeshName );
3537     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3538
3539     TIDSortedElemSet elements;
3540     if ( mesh_i &&
3541       idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3542     {
3543       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3544       mesh_i->CreateGroupServants();
3545     }
3546     if ( !myPreviewMode ) {
3547       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3548              << theObject << ", "
3549              << theVector   << ", "
3550              << theCopyGroups << ", '"
3551              << theMeshName << "' )";
3552     }
3553   }
3554
3555   // dump "GetGroups"
3556   if (!myPreviewMode && mesh_i)
3557     mesh_i->GetGroups();
3558
3559   return mesh._retn();
3560 }
3561
3562 //=======================================================================
3563 //function : rotate
3564 //purpose  :
3565 //=======================================================================
3566
3567 SMESH::ListOfGroups*
3568 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
3569                            const SMESH::AxisStruct & theAxis,
3570                            CORBA::Double             theAngle,
3571                            CORBA::Boolean            theCopy,
3572                            bool                      theMakeGroups,
3573                            ::SMESH_Mesh*             theTargetMesh)
3574 {
3575   initData();
3576
3577   if ( theTargetMesh )
3578     theCopy = false;
3579
3580   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3581   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3582
3583   gp_Trsf aTrsf;
3584   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3585
3586   TIDSortedElemSet  copyElements;
3587   TIDSortedElemSet* workElements = &theElements;
3588   TPreviewMesh      tmpMesh;
3589   SMESH_Mesh*       mesh = myMesh;
3590
3591   if ( myPreviewMode ) {
3592     tmpMesh.Copy( theElements, copyElements );
3593     if ( !theCopy && !theTargetMesh )
3594     {
3595       TIDSortedElemSet elemsAround, elemsAroundCopy;
3596       getElementsAround( theElements, GetMeshDS(), elemsAround );
3597       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3598     }
3599     mesh = &tmpMesh;
3600     workElements = &copyElements;
3601     theMakeGroups = false;
3602   }
3603
3604   ::SMESH_MeshEditor anEditor( mesh );
3605   ::SMESH_MeshEditor::PGroupIDs groupIds =
3606       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3607
3608   if(theCopy || myPreviewMode)
3609     storeResult(anEditor);
3610
3611   if ( !myPreviewMode )
3612   {
3613     if ( theTargetMesh )
3614     {
3615       theTargetMesh->GetMeshDS()->Modified();
3616     }
3617     else
3618     {
3619       myMesh->GetMeshDS()->Modified();
3620       myMesh->SetIsModified( true );
3621     }
3622   }
3623
3624   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3625 }
3626
3627 //=======================================================================
3628 //function : Rotate
3629 //purpose  :
3630 //=======================================================================
3631
3632 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3633                                 const SMESH::AxisStruct & theAxis,
3634                                 CORBA::Double             theAngle,
3635                                 CORBA::Boolean            theCopy)
3636 {
3637   if (!myPreviewMode) {
3638     TPythonDump() << this << ".Rotate( "
3639                   << theIDsOfElements << ", "
3640                   << theAxis << ", "
3641                   << theAngle << ", "
3642                   << theCopy << " )";
3643   }
3644   if (theIDsOfElements.length() > 0)
3645   {
3646     TIDSortedElemSet elements;
3647     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3648     rotate(elements,theAxis,theAngle,theCopy,false);
3649   }
3650 }
3651
3652 //=======================================================================
3653 //function : RotateObject
3654 //purpose  :
3655 //=======================================================================
3656
3657 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3658                                       const SMESH::AxisStruct & theAxis,
3659                                       CORBA::Double             theAngle,
3660                                       CORBA::Boolean            theCopy)
3661 {
3662   if ( !myPreviewMode ) {
3663     TPythonDump() << this << ".RotateObject( "
3664                   << theObject << ", "
3665                   << theAxis << ", "
3666                   << theAngle << ", "
3667                   << theCopy << " )";
3668   }
3669   TIDSortedElemSet elements;
3670   bool emptyIfIsMesh = myPreviewMode ? false : true;
3671   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3672     rotate(elements,theAxis,theAngle,theCopy,false);
3673 }
3674
3675 //=======================================================================
3676 //function : RotateMakeGroups
3677 //purpose  :
3678 //=======================================================================
3679
3680 SMESH::ListOfGroups*
3681 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3682                                      const SMESH::AxisStruct& theAxis,
3683                                      CORBA::Double            theAngle)
3684 {
3685   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3686
3687   SMESH::ListOfGroups * aGroups = 0;
3688   if (theIDsOfElements.length() > 0)
3689   {
3690     TIDSortedElemSet elements;
3691     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3692     aGroups = rotate(elements,theAxis,theAngle,true,true);
3693   }
3694   if (!myPreviewMode) {
3695     DumpGroupsList(aPythonDump, aGroups);
3696     aPythonDump << this << ".RotateMakeGroups( "
3697                 << theIDsOfElements << ", "
3698                 << theAxis << ", "
3699                 << theAngle << " )";
3700   }
3701   return aGroups;
3702 }
3703
3704 //=======================================================================
3705 //function : RotateObjectMakeGroups
3706 //purpose  :
3707 //=======================================================================
3708
3709 SMESH::ListOfGroups*
3710 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3711                                            const SMESH::AxisStruct&  theAxis,
3712                                            CORBA::Double             theAngle)
3713 {
3714   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3715
3716   SMESH::ListOfGroups * aGroups = 0;
3717   TIDSortedElemSet elements;
3718   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3719     aGroups = rotate(elements, theAxis, theAngle, true, true);
3720
3721   if (!myPreviewMode) {
3722     DumpGroupsList(aPythonDump, aGroups);
3723     aPythonDump << this << ".RotateObjectMakeGroups( "
3724                 << theObject << ", "
3725                 << theAxis << ", "
3726                 << theAngle << " )";
3727   }
3728   return aGroups;
3729 }
3730
3731 //=======================================================================
3732 //function : RotateMakeMesh
3733 //purpose  :
3734 //=======================================================================
3735
3736 SMESH::SMESH_Mesh_ptr
3737 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3738                                    const SMESH::AxisStruct& theAxis,
3739                                    CORBA::Double            theAngleInRadians,
3740                                    CORBA::Boolean           theCopyGroups,
3741                                    const char*              theMeshName)
3742 {
3743   SMESH::SMESH_Mesh_var mesh;
3744   SMESH_Mesh_i* mesh_i;
3745
3746   { // open new scope to dump "MakeMesh" command
3747     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3748
3749     TPythonDump pydump; // to prevent dump at mesh creation
3750
3751     mesh = makeMesh( theMeshName );
3752     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3753
3754     if ( mesh_i && theIDsOfElements.length() > 0 )
3755     {
3756       TIDSortedElemSet elements;
3757       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3758       rotate(elements, theAxis, theAngleInRadians,
3759              false, theCopyGroups, & mesh_i->GetImpl());
3760       mesh_i->CreateGroupServants();
3761     }
3762     if ( !myPreviewMode ) {
3763       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3764              << theIDsOfElements << ", "
3765              << theAxis << ", "
3766              << theAngleInRadians   << ", "
3767              << theCopyGroups << ", '"
3768              << theMeshName << "' )";
3769     }
3770   }
3771
3772   // dump "GetGroups"
3773   if (!myPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3774     mesh_i->GetGroups();
3775
3776   return mesh._retn();
3777 }
3778
3779 //=======================================================================
3780 //function : RotateObjectMakeMesh
3781 //purpose  :
3782 //=======================================================================
3783
3784 SMESH::SMESH_Mesh_ptr
3785 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3786                                          const SMESH::AxisStruct&  theAxis,
3787                                          CORBA::Double             theAngleInRadians,
3788                                          CORBA::Boolean            theCopyGroups,
3789                                          const char*               theMeshName)
3790 {
3791   SMESH::SMESH_Mesh_var mesh;
3792   SMESH_Mesh_i* mesh_i;
3793
3794   {// open new scope to dump "MakeMesh" command
3795    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3796
3797     TPythonDump pydump; // to prevent dump at mesh creation
3798     mesh = makeMesh( theMeshName );
3799     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3800
3801     TIDSortedElemSet elements;
3802     if (mesh_i &&
3803         idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3804     {
3805       rotate(elements, theAxis, theAngleInRadians,
3806              false, theCopyGroups, & mesh_i->GetImpl());
3807       mesh_i->CreateGroupServants();
3808     }
3809     if ( !myPreviewMode ) {
3810       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3811              << theObject << ", "
3812              << theAxis << ", "
3813              << theAngleInRadians   << ", "
3814              << theCopyGroups << ", '"
3815              << theMeshName << "' )";
3816     }
3817   }
3818
3819   // dump "GetGroups"
3820   if (!myPreviewMode && mesh_i)
3821     mesh_i->GetGroups();
3822
3823   return mesh._retn();
3824 }
3825
3826 //=======================================================================
3827 //function : scale
3828 //purpose  :
3829 //=======================================================================
3830
3831 SMESH::ListOfGroups*
3832 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
3833                           const SMESH::PointStruct&  thePoint,
3834                           const SMESH::double_array& theScaleFact,
3835                           CORBA::Boolean             theCopy,
3836                           bool                       theMakeGroups,
3837                           ::SMESH_Mesh*              theTargetMesh)
3838 {
3839   initData();
3840   if ( theScaleFact.length() < 1 )
3841     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3842   if ( theScaleFact.length() == 2 )
3843     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3844
3845   if ( theTargetMesh )
3846     theCopy = false;
3847
3848   TIDSortedElemSet elements;
3849   bool emptyIfIsMesh = myPreviewMode ? false : true;
3850   if ( !idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3851     return 0;
3852
3853   double S[3] = {
3854     theScaleFact[0],
3855     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3856     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3857   };
3858   double tol = std::numeric_limits<double>::max();
3859   gp_Trsf aTrsf;
3860   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
3861                    0,    S[1], 0,    thePoint.y * (1-S[1]),
3862                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
3863
3864   TIDSortedElemSet  copyElements;
3865   TPreviewMesh      tmpMesh;
3866   TIDSortedElemSet* workElements = &elements;
3867   SMESH_Mesh*       mesh = myMesh;
3868   
3869   if ( myPreviewMode )
3870   {
3871     tmpMesh.Copy( elements, copyElements);
3872     if ( !theCopy && !theTargetMesh )
3873     {
3874       TIDSortedElemSet elemsAround, elemsAroundCopy;
3875       getElementsAround( elements, GetMeshDS(), elemsAround );
3876       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3877     }
3878     mesh = &tmpMesh;
3879     workElements = & copyElements;
3880     theMakeGroups = false;
3881   }
3882
3883   ::SMESH_MeshEditor anEditor( mesh );
3884   ::SMESH_MeshEditor::PGroupIDs groupIds =
3885       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3886
3887   if(theCopy || myPreviewMode )
3888     storeResult(anEditor);
3889
3890   if ( !myPreviewMode )
3891   {
3892     if ( theTargetMesh )
3893     {
3894       theTargetMesh->GetMeshDS()->Modified();
3895     }
3896     else
3897     {
3898       myMesh->GetMeshDS()->Modified();
3899       myMesh->SetIsModified( true );
3900     }
3901   }
3902
3903   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3904 }
3905
3906 //=======================================================================
3907 //function : Scale
3908 //purpose  :
3909 //=======================================================================
3910
3911 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
3912                                const SMESH::PointStruct&  thePoint,
3913                                const SMESH::double_array& theScaleFact,
3914                                CORBA::Boolean             theCopy)
3915 {
3916   if ( !myPreviewMode ) {
3917     TPythonDump() << this << ".Scale( "
3918                   << theObject << ", "
3919                   << "SMESH.PointStruct( "  << thePoint.x << ", "
3920                   << thePoint.y << ", " << thePoint.z << " ) ,"
3921                   << theScaleFact << ", "
3922                   << theCopy << " )";
3923   }
3924   scale(theObject, thePoint, theScaleFact, theCopy, false);
3925 }
3926
3927
3928 //=======================================================================
3929 //function : ScaleMakeGroups
3930 //purpose  :
3931 //=======================================================================
3932
3933 SMESH::ListOfGroups*
3934 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3935                                     const SMESH::PointStruct&  thePoint,
3936                                     const SMESH::double_array& theScaleFact)
3937 {
3938   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3939
3940   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3941   if (!myPreviewMode) {
3942     DumpGroupsList(aPythonDump, aGroups);
3943     aPythonDump << this << ".Scale("
3944                 << theObject << ","
3945                 << "SMESH.PointStruct(" <<thePoint.x << ","
3946                 << thePoint.y << "," << thePoint.z << "),"
3947                 << theScaleFact << ",True,True)";
3948   }
3949   return aGroups;
3950 }
3951
3952
3953 //=======================================================================
3954 //function : ScaleMakeMesh
3955 //purpose  :
3956 //=======================================================================
3957
3958 SMESH::SMESH_Mesh_ptr
3959 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
3960                                   const SMESH::PointStruct&  thePoint,
3961                                   const SMESH::double_array& theScaleFact,
3962                                   CORBA::Boolean             theCopyGroups,
3963                                   const char*                theMeshName)
3964 {
3965   SMESH_Mesh_i* mesh_i;
3966   SMESH::SMESH_Mesh_var mesh;
3967   { // open new scope to dump "MakeMesh" command
3968     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3969
3970     TPythonDump pydump; // to prevent dump at mesh creation
3971     mesh = makeMesh( theMeshName );
3972     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3973
3974     if ( mesh_i )
3975     {
3976       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3977       mesh_i->CreateGroupServants();
3978     }
3979     if ( !myPreviewMode )
3980       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3981              << theObject << ", "
3982              << "SMESH.PointStruct( "  << thePoint.x << ", "
3983              << thePoint.y << ", " << thePoint.z << " ) ,"
3984              << theScaleFact << ", "
3985              << theCopyGroups << ", '"
3986              << theMeshName << "' )";
3987   }
3988
3989   // dump "GetGroups"
3990   if (!myPreviewMode && mesh_i)
3991     mesh_i->GetGroups();
3992
3993   return mesh._retn();
3994 }
3995
3996
3997 //=======================================================================
3998 //function : FindCoincidentNodes
3999 //purpose  :
4000 //=======================================================================
4001
4002 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
4003                                               SMESH::array_of_long_array_out GroupsOfNodes)
4004 {
4005   initData();
4006
4007   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4008   ::SMESH_MeshEditor anEditor( myMesh );
4009   TIDSortedNodeSet nodes; // no input nodes
4010   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4011
4012   GroupsOfNodes = new SMESH::array_of_long_array;
4013   GroupsOfNodes->length( aListOfListOfNodes.size() );
4014   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4015   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
4016     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4017     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4018     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4019     aGroup.length( aListOfNodes.size() );
4020     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4021       aGroup[ j ] = (*lIt)->GetID();
4022   }
4023   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4024                 << Tolerance << " )";
4025 }
4026
4027 //=======================================================================
4028 //function : FindCoincidentNodesOnPart
4029 //purpose  :
4030 //=======================================================================
4031 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
4032                                                    CORBA::Double                  Tolerance,
4033                                                    SMESH::array_of_long_array_out GroupsOfNodes)
4034 {
4035   initData();
4036
4037   TIDSortedNodeSet nodes;
4038   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
4039
4040   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4041   ::SMESH_MeshEditor anEditor( myMesh );
4042   if(!nodes.empty())
4043     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4044
4045   GroupsOfNodes = new SMESH::array_of_long_array;
4046   GroupsOfNodes->length( aListOfListOfNodes.size() );
4047   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4048   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4049   {
4050     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4051     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4052     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4053     aGroup.length( aListOfNodes.size() );
4054     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4055       aGroup[ j ] = (*lIt)->GetID();
4056   }
4057   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4058                 <<theObject<<", "
4059                 << Tolerance << " )";
4060 }
4061
4062 //================================================================================
4063 /*!
4064  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4065  *        ExceptSubMeshOrGroups
4066  */
4067 //================================================================================
4068
4069 void SMESH_MeshEditor_i::
4070 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
4071                              CORBA::Double                  theTolerance,
4072                              SMESH::array_of_long_array_out theGroupsOfNodes,
4073                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
4074 {
4075   initData();
4076
4077   TIDSortedNodeSet nodes;
4078   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
4079
4080   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4081   {
4082     TIDSortedNodeSet exceptNodes;
4083     idSourceToNodeSet( theExceptSubMeshOrGroups[i], GetMeshDS(), exceptNodes );
4084     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4085     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4086       nodes.erase( *avoidNode );
4087   }
4088   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4089   ::SMESH_MeshEditor anEditor( myMesh );
4090   if(!nodes.empty())
4091     anEditor.FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4092
4093   theGroupsOfNodes = new SMESH::array_of_long_array;
4094   theGroupsOfNodes->length( aListOfListOfNodes.size() );
4095   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4096   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4097   {
4098     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4099     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4100     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4101     aGroup.length( aListOfNodes.size() );
4102     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4103       aGroup[ j ] = (*lIt)->GetID();
4104   }
4105   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4106                 << theObject<<", "
4107                 << theTolerance << ", "
4108                 << theExceptSubMeshOrGroups << " )";
4109 }
4110
4111 //=======================================================================
4112 //function : MergeNodes
4113 //purpose  :
4114 //=======================================================================
4115
4116 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4117 {
4118   initData();
4119
4120   SMESHDS_Mesh* aMesh = GetMeshDS();
4121
4122   TPythonDump aTPythonDump;
4123   aTPythonDump << this << ".MergeNodes([";
4124   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4125   for (int i = 0; i < GroupsOfNodes.length(); i++)
4126   {
4127     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4128     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4129     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4130     for ( int j = 0; j < aNodeGroup.length(); j++ )
4131     {
4132       CORBA::Long index = aNodeGroup[ j ];
4133       const SMDS_MeshNode * node = aMesh->FindNode(index);
4134       if ( node )
4135         aListOfNodes.push_back( node );
4136     }
4137     if ( aListOfNodes.size() < 2 )
4138       aListOfListOfNodes.pop_back();
4139
4140     if ( i > 0 ) aTPythonDump << ", ";
4141     aTPythonDump << aNodeGroup;
4142   }
4143   ::SMESH_MeshEditor anEditor( myMesh );
4144   anEditor.MergeNodes( aListOfListOfNodes );
4145
4146   aTPythonDump <<  "])";
4147   myMesh->GetMeshDS()->Modified();
4148   myMesh->SetIsModified( true );
4149 }
4150
4151 //=======================================================================
4152 //function : FindEqualElements
4153 //purpose  :
4154 //=======================================================================
4155 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
4156                                            SMESH::array_of_long_array_out GroupsOfElementsID)
4157 {
4158   initData();
4159
4160   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4161   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4162   {
4163     typedef list<int> TListOfIDs;
4164     set<const SMDS_MeshElement*> elems;
4165     SMESH::long_array_var aElementsId = theObject->GetIDs();
4166     SMESHDS_Mesh* aMesh = GetMeshDS();
4167
4168     for(int i = 0; i < aElementsId->length(); i++) {
4169       CORBA::Long anID = aElementsId[i];
4170       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
4171       if (elem) {
4172         elems.insert(elem);
4173       }
4174     }
4175
4176     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4177     ::SMESH_MeshEditor anEditor( myMesh );
4178     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
4179
4180     GroupsOfElementsID = new SMESH::array_of_long_array;
4181     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4182
4183     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
4184     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
4185       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4186       TListOfIDs& listOfIDs = *arraysIt;
4187       aGroup.length( listOfIDs.size() );
4188       TListOfIDs::iterator idIt = listOfIDs.begin();
4189       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
4190         aGroup[ k ] = *idIt;
4191       }
4192     }
4193
4194     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4195                   <<theObject<<" )";
4196   }
4197 }
4198
4199 //=======================================================================
4200 //function : MergeElements
4201 //purpose  :
4202 //=======================================================================
4203
4204 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4205 {
4206   initData();
4207
4208   TPythonDump aTPythonDump;
4209   aTPythonDump << this << ".MergeElements( [";
4210
4211   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4212
4213   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4214     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4215     aListOfListOfElementsID.push_back( list< int >() );
4216     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4217     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4218       CORBA::Long id = anElemsIDGroup[ j ];
4219       aListOfElemsID.push_back( id );
4220     }
4221     if ( aListOfElemsID.size() < 2 )
4222       aListOfListOfElementsID.pop_back();
4223     if ( i > 0 ) aTPythonDump << ", ";
4224     aTPythonDump << anElemsIDGroup;
4225   }
4226
4227   ::SMESH_MeshEditor anEditor( myMesh );
4228   anEditor.MergeElements(aListOfListOfElementsID);
4229   myMesh->GetMeshDS()->Modified();
4230   myMesh->SetIsModified( true );
4231
4232   aTPythonDump << "] )";
4233 }
4234
4235 //=======================================================================
4236 //function : MergeEqualElements
4237 //purpose  :
4238 //=======================================================================
4239
4240 void SMESH_MeshEditor_i::MergeEqualElements()
4241 {
4242   initData();
4243
4244   ::SMESH_MeshEditor anEditor( myMesh );
4245   anEditor.MergeEqualElements();
4246
4247   myMesh->GetMeshDS()->Modified();
4248
4249   TPythonDump() << this << ".MergeEqualElements()";
4250 }
4251
4252 //=============================================================================
4253 /*!
4254  * Move the node to a given point
4255  */
4256 //=============================================================================
4257
4258 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
4259                                             CORBA::Double x,
4260                                             CORBA::Double y,
4261                                             CORBA::Double z)
4262 {
4263   initData(/*deleteSearchers=*/false);
4264
4265   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
4266   if ( !node )
4267     return false;
4268
4269   if ( theNodeSearcher )
4270     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4271
4272   if ( myPreviewMode ) // make preview data
4273   {
4274     // in a preview mesh, make edges linked to a node
4275     TPreviewMesh tmpMesh;
4276     TIDSortedElemSet linkedNodes;
4277     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4278     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4279     SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4280     for ( ; nIt != linkedNodes.end(); ++nIt )
4281     {
4282       SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4283       tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4284     }
4285     // move copied node
4286     if ( nodeCpy1 )
4287       tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4288     // fill preview data
4289     ::SMESH_MeshEditor anEditor( & tmpMesh );
4290     storeResult( anEditor );
4291   }
4292   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4293     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4294   else
4295     GetMeshDS()->MoveNode(node, x, y, z);
4296
4297   if ( !myPreviewMode )
4298   {
4299     // Update Python script
4300     TPythonDump() << "isDone = " << this << ".MoveNode( "
4301                   << NodeID << ", " << x << ", " << y << ", " << z << " )";
4302     myMesh->GetMeshDS()->Modified();
4303     myMesh->SetIsModified( true );
4304   }
4305
4306   return true;
4307 }
4308
4309 //================================================================================
4310 /*!
4311  * \brief Return ID of node closest to a given point
4312  */
4313 //================================================================================
4314
4315 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4316                                                   CORBA::Double y,
4317                                                   CORBA::Double z)
4318 {
4319   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4320
4321   if ( !theNodeSearcher ) {
4322     ::SMESH_MeshEditor anEditor( myMesh );
4323     theNodeSearcher = anEditor.GetNodeSearcher();
4324   }
4325   gp_Pnt p( x,y,z );
4326   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4327     return node->GetID();
4328
4329   return 0;
4330 }
4331
4332 //================================================================================
4333 /*!
4334  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4335  * move the node closest to the point to point's location and return ID of the node
4336  */
4337 //================================================================================
4338
4339 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4340                                                        CORBA::Double y,
4341                                                        CORBA::Double z,
4342                                                        CORBA::Long   theNodeID)
4343 {
4344   // We keep theNodeSearcher until any mesh modification:
4345   // 1) initData() deletes theNodeSearcher at any edition,
4346   // 2) TSearchersDeleter - at any mesh compute event and mesh change
4347
4348   initData(/*deleteSearchers=*/false);
4349
4350   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4351
4352   int nodeID = theNodeID;
4353   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
4354   if ( !node ) // preview moving node
4355   {
4356     if ( !theNodeSearcher ) {
4357       ::SMESH_MeshEditor anEditor( myMesh );
4358       theNodeSearcher = anEditor.GetNodeSearcher();
4359     }
4360     gp_Pnt p( x,y,z );
4361     node = theNodeSearcher->FindClosestTo( p );
4362   }
4363   if ( node ) {
4364     nodeID = node->GetID();
4365     if ( myPreviewMode ) // make preview data
4366     {
4367       // in a preview mesh, make edges linked to a node
4368       TPreviewMesh tmpMesh;
4369       TIDSortedElemSet linkedNodes;
4370       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4371       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4372       for ( ; nIt != linkedNodes.end(); ++nIt )
4373       {
4374         SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4375         tmpMesh.Copy( &edge );
4376       }
4377       // move copied node
4378       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4379       if ( node )
4380         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4381       // fill preview data
4382       ::SMESH_MeshEditor anEditor( & tmpMesh );
4383       storeResult( anEditor );
4384     }
4385     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4386     {
4387       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4388     }
4389     else
4390     {
4391       GetMeshDS()->MoveNode(node, x, y, z);
4392     }
4393   }
4394
4395   if ( !myPreviewMode )
4396   {
4397     TPythonDump() << "nodeID = " << this
4398                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4399                   << ", " << nodeID << " )";
4400
4401     myMesh->GetMeshDS()->Modified();
4402     myMesh->SetIsModified( true );
4403   }
4404
4405   return nodeID;
4406 }
4407
4408 //=======================================================================
4409 /*!
4410  * Return elements of given type where the given point is IN or ON.
4411  *
4412  * 'ALL' type means elements of any type excluding nodes
4413  */
4414 //=======================================================================
4415
4416 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
4417                                                            CORBA::Double      y,
4418                                                            CORBA::Double      z,
4419                                                            SMESH::ElementType type)
4420 {
4421   SMESH::long_array_var res = new SMESH::long_array;
4422   vector< const SMDS_MeshElement* > foundElems;
4423
4424   theSearchersDeleter.Set( myMesh );
4425   if ( !theElementSearcher ) {
4426     ::SMESH_MeshEditor anEditor( myMesh );
4427     theElementSearcher = anEditor.GetElementSearcher();
4428   }
4429   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4430                                            SMDSAbs_ElementType( type ),
4431                                            foundElems);
4432   res->length( foundElems.size() );
4433   for ( int i = 0; i < foundElems.size(); ++i )
4434     res[i] = foundElems[i]->GetID();
4435
4436   if ( !myPreviewMode ) // call from tui
4437     TPythonDump() << "res = " << this << ".FindElementsByPoint( "
4438                   << x << ", "
4439                   << y << ", "
4440                   << z << ", "
4441                   << type << " )";
4442
4443   return res._retn();
4444 }
4445
4446 //=======================================================================
4447 //function : FindAmongElementsByPoint
4448 //purpose  : Searching among the given elements, return elements of given type 
4449 //           where the given point is IN or ON.
4450 //           'ALL' type means elements of any type excluding nodes
4451 //=======================================================================
4452
4453 SMESH::long_array*
4454 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
4455                                              CORBA::Double             x,
4456                                              CORBA::Double             y,
4457                                              CORBA::Double             z,
4458                                              SMESH::ElementType        type)
4459 {
4460   SMESH::long_array_var res = new SMESH::long_array;
4461   
4462   SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
4463   if ( types->length() == 1 && // a part contains only nodes or 0D elements
4464        ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D ) &&
4465        type != types[0] ) // but search of elements of dim > 0
4466     return res._retn();
4467
4468   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
4469     return FindElementsByPoint( x,y,z, type );
4470
4471   string partIOR = SMESH_Gen_i::GetORB()->object_to_string( elementIDs );
4472   if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( elementIDs ))
4473     // take into account passible group modification
4474     partIOR += SMESH_Comment( ((SMESHDS_Group*)group_i->GetGroupDS())->SMDSGroup().Tic() );
4475   partIOR += SMESH_Comment( type );
4476
4477   TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
4478
4479   theSearchersDeleter.Set( myMesh, partIOR );
4480   if ( !theElementSearcher )
4481   {
4482     // create a searcher from elementIDs
4483     SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
4484     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
4485
4486     if ( !idSourceToSet( elementIDs, meshDS, elements,
4487                          SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
4488       return res._retn();
4489
4490     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4491     SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
4492
4493     ::SMESH_MeshEditor anEditor( myMesh );
4494     theElementSearcher = anEditor.GetElementSearcher(elemsIt);
4495   }
4496
4497   vector< const SMDS_MeshElement* > foundElems;
4498
4499   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4500                                            SMDSAbs_ElementType( type ),
4501                                            foundElems);
4502   res->length( foundElems.size() );
4503   for ( int i = 0; i < foundElems.size(); ++i )
4504     res[i] = foundElems[i]->GetID();
4505
4506   if ( !myPreviewMode ) // call from tui
4507     TPythonDump() << "res = " << this << ".FindAmongElementsByPoint( "
4508                   << elementIDs << ", "
4509                   << x << ", "
4510                   << y << ", "
4511                   << z << ", "
4512                   << type << " )";
4513
4514   return res._retn();
4515   
4516 }
4517 //=======================================================================
4518 //function : GetPointState
4519 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4520 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4521 //=======================================================================
4522
4523 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4524                                                CORBA::Double y,
4525                                                CORBA::Double z)
4526 {
4527   theSearchersDeleter.Set( myMesh );
4528   if ( !theElementSearcher ) {
4529     ::SMESH_MeshEditor anEditor( myMesh );
4530     theElementSearcher = anEditor.GetElementSearcher();
4531   }
4532   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4533 }
4534
4535 //=======================================================================
4536 //function : convError
4537 //purpose  :
4538 //=======================================================================
4539
4540 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4541
4542 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4543 {
4544   switch ( e ) {
4545     RETCASE( SEW_OK );
4546     RETCASE( SEW_BORDER1_NOT_FOUND );
4547     RETCASE( SEW_BORDER2_NOT_FOUND );
4548     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4549     RETCASE( SEW_BAD_SIDE_NODES );
4550     RETCASE( SEW_VOLUMES_TO_SPLIT );
4551     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4552     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4553     RETCASE( SEW_BAD_SIDE1_NODES );
4554     RETCASE( SEW_BAD_SIDE2_NODES );
4555   }
4556   return SMESH::SMESH_MeshEditor::SEW_OK;
4557 }
4558
4559 //=======================================================================
4560 //function : SewFreeBorders
4561 //purpose  :
4562 //=======================================================================
4563
4564 SMESH::SMESH_MeshEditor::Sew_Error
4565 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4566                                    CORBA::Long SecondNodeID1,
4567                                    CORBA::Long LastNodeID1,
4568                                    CORBA::Long FirstNodeID2,
4569                                    CORBA::Long SecondNodeID2,
4570                                    CORBA::Long LastNodeID2,
4571                                    CORBA::Boolean CreatePolygons,
4572                                    CORBA::Boolean CreatePolyedrs)
4573 {
4574   initData();
4575
4576   SMESHDS_Mesh* aMesh = GetMeshDS();
4577
4578   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4579   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4580   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4581   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4582   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4583   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
4584
4585   if (!aBorderFirstNode ||
4586       !aBorderSecondNode||
4587       !aBorderLastNode)
4588     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4589   if (!aSide2FirstNode  ||
4590       !aSide2SecondNode ||
4591       !aSide2ThirdNode)
4592     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4593
4594   TPythonDump() << "error = " << this << ".SewFreeBorders( "
4595                 << FirstNodeID1  << ", "
4596                 << SecondNodeID1 << ", "
4597                 << LastNodeID1   << ", "
4598                 << FirstNodeID2  << ", "
4599                 << SecondNodeID2 << ", "
4600                 << LastNodeID2   << ", "
4601                 << CreatePolygons<< ", "
4602                 << CreatePolyedrs<< " )";
4603
4604   ::SMESH_MeshEditor anEditor( myMesh );
4605   SMESH::SMESH_MeshEditor::Sew_Error error =
4606     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4607                                        aBorderSecondNode,
4608                                        aBorderLastNode,
4609                                        aSide2FirstNode,
4610                                        aSide2SecondNode,
4611                                        aSide2ThirdNode,
4612                                        true,
4613                                        CreatePolygons,
4614                                        CreatePolyedrs) );
4615
4616   storeResult(anEditor);
4617
4618   myMesh->GetMeshDS()->Modified();
4619   myMesh->SetIsModified( true );
4620
4621   return error;
4622 }
4623
4624
4625 //=======================================================================
4626 //function : SewConformFreeBorders
4627 //purpose  :
4628 //=======================================================================
4629
4630 SMESH::SMESH_MeshEditor::Sew_Error
4631 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4632                                           CORBA::Long SecondNodeID1,
4633                                           CORBA::Long LastNodeID1,
4634                                           CORBA::Long FirstNodeID2,
4635                                           CORBA::Long SecondNodeID2)
4636 {
4637   initData();
4638
4639   SMESHDS_Mesh* aMesh = GetMeshDS();
4640
4641   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4642   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4643   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4644   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4645   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4646   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4647
4648   if (!aBorderFirstNode ||
4649       !aBorderSecondNode||
4650       !aBorderLastNode )
4651     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4652   if (!aSide2FirstNode  ||
4653       !aSide2SecondNode)
4654     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4655
4656   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4657                 << FirstNodeID1  << ", "
4658                 << SecondNodeID1 << ", "
4659                 << LastNodeID1   << ", "
4660                 << FirstNodeID2  << ", "
4661                 << SecondNodeID2 << " )";
4662
4663   ::SMESH_MeshEditor anEditor( myMesh );
4664   SMESH::SMESH_MeshEditor::Sew_Error error =
4665     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4666                                        aBorderSecondNode,
4667                                        aBorderLastNode,
4668                                        aSide2FirstNode,
4669                                        aSide2SecondNode,
4670                                        aSide2ThirdNode,
4671                                        true,
4672                                        false, false) );
4673
4674   storeResult(anEditor);
4675
4676   myMesh->GetMeshDS()->Modified();
4677   myMesh->SetIsModified( true );
4678
4679   return error;
4680 }
4681
4682
4683 //=======================================================================
4684 //function : SewBorderToSide
4685 //purpose  :
4686 //=======================================================================
4687
4688 SMESH::SMESH_MeshEditor::Sew_Error
4689 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4690                                     CORBA::Long SecondNodeIDOnFreeBorder,
4691                                     CORBA::Long LastNodeIDOnFreeBorder,
4692                                     CORBA::Long FirstNodeIDOnSide,
4693                                     CORBA::Long LastNodeIDOnSide,
4694                                     CORBA::Boolean CreatePolygons,
4695                                     CORBA::Boolean CreatePolyedrs)
4696 {
4697   initData();
4698
4699   SMESHDS_Mesh* aMesh = GetMeshDS();
4700
4701   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
4702   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4703   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
4704   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
4705   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
4706   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4707
4708   if (!aBorderFirstNode ||
4709       !aBorderSecondNode||
4710       !aBorderLastNode  )
4711     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4712   if (!aSide2FirstNode  ||
4713       !aSide2SecondNode)
4714     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4715
4716   TPythonDump() << "error = " << this << ".SewBorderToSide( "
4717                 << FirstNodeIDOnFreeBorder  << ", "
4718                 << SecondNodeIDOnFreeBorder << ", "
4719                 << LastNodeIDOnFreeBorder   << ", "
4720                 << FirstNodeIDOnSide        << ", "
4721                 << LastNodeIDOnSide         << ", "
4722                 << CreatePolygons           << ", "
4723                 << CreatePolyedrs           << ") ";
4724
4725   ::SMESH_MeshEditor anEditor( myMesh );
4726   SMESH::SMESH_MeshEditor::Sew_Error error =
4727     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4728                                        aBorderSecondNode,
4729                                        aBorderLastNode,
4730                                        aSide2FirstNode,
4731                                        aSide2SecondNode,
4732                                        aSide2ThirdNode,
4733                                        false,
4734                                        CreatePolygons,
4735                                        CreatePolyedrs) );
4736
4737   storeResult(anEditor);
4738
4739   myMesh->GetMeshDS()->Modified();
4740   myMesh->SetIsModified( true );
4741
4742   return error;
4743 }
4744
4745
4746 //=======================================================================
4747 //function : SewSideElements
4748 //purpose  :
4749 //=======================================================================
4750
4751 SMESH::SMESH_MeshEditor::Sew_Error
4752 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4753                                     const SMESH::long_array& IDsOfSide2Elements,
4754                                     CORBA::Long NodeID1OfSide1ToMerge,
4755                                     CORBA::Long NodeID1OfSide2ToMerge,
4756                                     CORBA::Long NodeID2OfSide1ToMerge,
4757                                     CORBA::Long NodeID2OfSide2ToMerge)
4758 {
4759   initData();
4760
4761   SMESHDS_Mesh* aMesh = GetMeshDS();
4762
4763   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
4764   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
4765   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4766   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4767
4768   if (!aFirstNode1ToMerge ||
4769       !aFirstNode2ToMerge )
4770     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4771   if (!aSecondNode1ToMerge||
4772       !aSecondNode2ToMerge)
4773     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4774
4775   TIDSortedElemSet aSide1Elems, aSide2Elems;
4776   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4777   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4778
4779   TPythonDump() << "error = " << this << ".SewSideElements( "
4780                 << IDsOfSide1Elements << ", "
4781                 << IDsOfSide2Elements << ", "
4782                 << NodeID1OfSide1ToMerge << ", "
4783                 << NodeID1OfSide2ToMerge << ", "
4784                 << NodeID2OfSide1ToMerge << ", "
4785                 << NodeID2OfSide2ToMerge << ")";
4786
4787   ::SMESH_MeshEditor anEditor( myMesh );
4788   SMESH::SMESH_MeshEditor::Sew_Error error =
4789     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
4790                                          aFirstNode1ToMerge,
4791                                          aFirstNode2ToMerge,
4792                                          aSecondNode1ToMerge,
4793                                          aSecondNode2ToMerge));
4794
4795   storeResult(anEditor);
4796
4797   myMesh->GetMeshDS()->Modified();
4798   myMesh->SetIsModified( true );
4799
4800   return error;
4801 }
4802
4803 //================================================================================
4804 /*!
4805  * \brief Set new nodes for given element
4806  * \param ide - element id
4807  * \param newIDs - new node ids
4808  * \retval CORBA::Boolean - true if result is OK
4809  */
4810 //================================================================================
4811
4812 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4813                                                    const SMESH::long_array& newIDs)
4814 {
4815   initData();
4816
4817   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4818   if(!elem) return false;
4819
4820   int nbn = newIDs.length();
4821   int i=0;
4822   vector<const SMDS_MeshNode*> aNodes(nbn);
4823   int nbn1=-1;
4824   for(; i<nbn; i++) {
4825     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4826     if(aNode) {
4827       nbn1++;
4828       aNodes[nbn1] = aNode;
4829     }
4830   }
4831   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4832                 << ide << ", " << newIDs << " )";
4833
4834   MESSAGE("ChangeElementNodes");
4835   bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4836
4837   myMesh->GetMeshDS()->Modified();
4838   if ( res )
4839     myMesh->SetIsModified( true );
4840
4841   return res;
4842 }
4843
4844 //================================================================================
4845 /*!
4846  * \brief Update myLastCreated* or myPreviewData
4847  * \param anEditor - it contains last modification results
4848  */
4849 //================================================================================
4850
4851 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4852 {
4853   if ( myPreviewMode ) { // --- MeshPreviewStruct filling ---
4854
4855     list<int> aNodesConnectivity;
4856     typedef map<int, int> TNodesMap;
4857     TNodesMap nodesMap;
4858
4859     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4860     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4861
4862     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4863     int nbEdges = aMeshDS->NbEdges();
4864     int nbFaces = aMeshDS->NbFaces();
4865     int nbVolum = aMeshDS->NbVolumes();
4866     switch ( previewType ) {
4867     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4868     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4869     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4870     default:;
4871     }
4872     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4873     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4874     int i = 0, j = 0;
4875     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4876
4877     while ( itMeshElems->more() ) {
4878       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4879       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4880         continue;
4881
4882       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4883       while ( itElemNodes->more() ) {
4884         const SMDS_MeshNode* aMeshNode =
4885           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4886         int aNodeID = aMeshNode->GetID();
4887         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4888         if ( anIter == nodesMap.end() ) {
4889           // filling the nodes coordinates
4890           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4891           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4892           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4893           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4894           j++;
4895         }
4896         aNodesConnectivity.push_back(anIter->second);
4897       }
4898
4899       // filling the elements types
4900       SMDSAbs_ElementType aType;
4901       bool isPoly;
4902       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4903         aType = SMDSAbs_Node;
4904         isPoly = false;
4905         }
4906         else*/ {
4907         aType = aMeshElem->GetType();
4908         isPoly = aMeshElem->IsPoly();
4909       }
4910
4911       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4912       myPreviewData->elementTypes[i].isPoly = isPoly;
4913       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4914       i++;
4915
4916     }
4917     myPreviewData->nodesXYZ.length( j );
4918
4919     // filling the elements connectivities
4920     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4921     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4922     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4923       myPreviewData->elementConnectivities[i] = *aConnIter;
4924
4925     return;
4926   }
4927
4928   {
4929     // append new nodes into myLastCreatedNodes
4930     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4931     int j = myLastCreatedNodes->length();
4932     int newLen = j + aSeq.Length();
4933     myLastCreatedNodes->length( newLen );
4934     for(int i=0; j<newLen; i++,j++)
4935       myLastCreatedNodes[j] = aSeq.Value(i+1)->GetID();
4936   }
4937   {
4938     // append new elements into myLastCreatedElems
4939     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4940     int j = myLastCreatedElems->length();
4941     int newLen = j + aSeq.Length();
4942     myLastCreatedElems->length( newLen );
4943     for(int i=0; j<newLen; i++,j++)
4944       myLastCreatedElems[j] = aSeq.Value(i+1)->GetID();
4945   }
4946 }
4947
4948 //================================================================================
4949 /*!
4950  * Return data of mesh edition preview
4951  */
4952 //================================================================================
4953
4954 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4955 {
4956   return myPreviewData._retn();
4957 }
4958
4959 //================================================================================
4960 /*!
4961  * \brief Returns list of it's IDs of created nodes
4962  * \retval SMESH::long_array* - list of node ID
4963  */
4964 //================================================================================
4965
4966 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4967 {
4968   return myLastCreatedNodes._retn();
4969 }
4970
4971 //================================================================================
4972 /*!
4973  * \brief Returns list of it's IDs of created elements
4974  * \retval SMESH::long_array* - list of elements' ID
4975  */
4976 //================================================================================
4977
4978 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4979 {
4980   return myLastCreatedElems._retn();
4981 }
4982
4983 //=======================================================================
4984 //function : ConvertToQuadratic
4985 //purpose  :
4986 //=======================================================================
4987
4988 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4989 {
4990   ::SMESH_MeshEditor anEditor( myMesh );
4991   anEditor.ConvertToQuadratic(theForce3d);
4992   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4993   myMesh->GetMeshDS()->Modified();
4994   myMesh->SetIsModified( true );
4995 }
4996
4997 //=======================================================================
4998 //function : ConvertFromQuadratic
4999 //purpose  :
5000 //=======================================================================
5001
5002 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5003 {
5004   ::SMESH_MeshEditor anEditor( myMesh );
5005   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
5006   TPythonDump() << this << ".ConvertFromQuadratic()";
5007   myMesh->GetMeshDS()->Modified();
5008   if ( isDone )
5009     myMesh->SetIsModified( true );
5010   return isDone;
5011 }
5012 //================================================================================
5013 /*!
5014  * \brief Makes a part of the mesh quadratic
5015  */
5016 //================================================================================
5017
5018 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theForce3d,
5019                                                   SMESH::SMESH_IDSource_ptr theObject)
5020   throw (SALOME::SALOME_Exception)
5021 {
5022   Unexpect aCatch(SALOME_SalomeException);
5023   TPythonDump pyDump;
5024   TIDSortedElemSet elems;
5025   if ( idSourceToSet( theObject, GetMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5026   {
5027     if ( elems.empty() )
5028     {
5029       ConvertToQuadratic( theForce3d );
5030     }
5031     else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5032     {
5033       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5034     }
5035     else
5036     {
5037       ::SMESH_MeshEditor anEditor( myMesh );
5038       anEditor.ConvertToQuadratic(theForce3d, elems);
5039     }
5040   }
5041   myMesh->GetMeshDS()->Modified();
5042   myMesh->SetIsModified( true );
5043
5044   pyDump << this << ".ConvertToQuadraticObject( "<<theForce3d<<", "<<theObject<<" )";
5045 }
5046
5047 //================================================================================
5048 /*!
5049  * \brief Makes a part of the mesh linear
5050  */
5051 //================================================================================
5052
5053 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5054   throw (SALOME::SALOME_Exception)
5055 {
5056   Unexpect aCatch(SALOME_SalomeException);
5057   TPythonDump pyDump;
5058   TIDSortedElemSet elems;
5059   if ( idSourceToSet( theObject, GetMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5060   {
5061     if ( elems.empty() )
5062     {
5063       ConvertFromQuadratic();
5064     }
5065     else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5066     {
5067       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5068     }
5069     else
5070     {
5071       ::SMESH_MeshEditor anEditor( myMesh );
5072       anEditor.ConvertFromQuadratic(elems);
5073     }
5074   }
5075   myMesh->GetMeshDS()->Modified();
5076   myMesh->SetIsModified( true );
5077
5078   pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5079 }
5080
5081 //=======================================================================
5082 //function : makeMesh
5083 //purpose  : create a named imported mesh
5084 //=======================================================================
5085
5086 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5087 {
5088   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
5089   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
5090   SALOMEDS::Study_var study = gen->GetCurrentStudy();
5091   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
5092   gen->SetName( meshSO, theMeshName, "Mesh" );
5093   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5094
5095   return mesh._retn();
5096 }
5097
5098 //=======================================================================
5099 //function : DumpGroupsList
5100 //purpose  :
5101 //=======================================================================
5102 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython,
5103                                         const SMESH::ListOfGroups * theGroupList)
5104 {
5105   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
5106   if(isDumpGroupList) {
5107     theDumpPython << theGroupList << " = ";
5108   }
5109 }
5110
5111 //================================================================================
5112 /*!
5113   \brief Generates the unique group name.
5114   \param thePrefix name prefix
5115   \return unique name
5116 */
5117 //================================================================================
5118 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5119 {
5120   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5121   set<string> groupNames;
5122
5123   // Get existing group names
5124   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5125     SMESH::SMESH_GroupBase_var aGroup = groups[i];
5126     if (CORBA::is_nil(aGroup))
5127       continue;
5128
5129     groupNames.insert(aGroup->GetName());
5130   }
5131
5132   // Find new name
5133   string name = thePrefix;
5134   int index = 0;
5135
5136   while (!groupNames.insert(name).second) {
5137     if (index == 0) {
5138       name += "_1";
5139     }
5140     else {
5141       TCollection_AsciiString nbStr(index+1);
5142       name.resize( name.rfind('_')+1 );
5143       name += nbStr.ToCString();
5144     }
5145     ++index;
5146   }
5147
5148   return name;
5149 }
5150
5151 //================================================================================
5152 /*!
5153   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5154   \param theNodes - identifiers of nodes to be doubled
5155   \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5156          nodes. If list of element identifiers is empty then nodes are doubled but
5157          they not assigned to elements
5158   \return TRUE if operation has been completed successfully, FALSE otherwise
5159   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5160 */
5161 //================================================================================
5162
5163 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5164                                                 const SMESH::long_array& theModifiedElems )
5165 {
5166   initData();
5167
5168   ::SMESH_MeshEditor aMeshEditor( myMesh );
5169   list< int > aListOfNodes;
5170   int i, n;
5171   for ( i = 0, n = theNodes.length(); i < n; i++ )
5172     aListOfNodes.push_back( theNodes[ i ] );
5173
5174   list< int > aListOfElems;
5175   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5176     aListOfElems.push_back( theModifiedElems[ i ] );
5177
5178   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
5179
5180   myMesh->GetMeshDS()->Modified();
5181   storeResult( aMeshEditor) ;
5182   if ( aResult )
5183     myMesh->SetIsModified( true );
5184
5185   // Update Python script
5186   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5187
5188   return aResult;
5189 }
5190
5191 //================================================================================
5192 /*!
5193   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5194   This method provided for convenience works as DoubleNodes() described above.
5195   \param theNodeId - identifier of node to be doubled.
5196   \param theModifiedElems - identifiers of elements to be updated.
5197   \return TRUE if operation has been completed successfully, FALSE otherwise
5198   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5199 */
5200 //================================================================================
5201
5202 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
5203                                                const SMESH::long_array& theModifiedElems )
5204 {
5205   SMESH::long_array_var aNodes = new SMESH::long_array;
5206   aNodes->length( 1 );
5207   aNodes[ 0 ] = theNodeId;
5208
5209   TPythonDump pyDump; // suppress dump by the next line
5210
5211   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5212
5213   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5214
5215   return done;
5216 }
5217
5218 //================================================================================
5219 /*!
5220   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5221   This method provided for convenience works as DoubleNodes() described above.
5222   \param theNodes - group of nodes to be doubled.
5223   \param theModifiedElems - group of elements to be updated.
5224   \return TRUE if operation has been completed successfully, FALSE otherwise
5225   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5226 */
5227 //================================================================================
5228
5229 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5230                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
5231 {
5232   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5233     return false;
5234
5235   SMESH::long_array_var aNodes = theNodes->GetListOfID();
5236   SMESH::long_array_var aModifiedElems;
5237   if ( !CORBA::is_nil( theModifiedElems ) )
5238     aModifiedElems = theModifiedElems->GetListOfID();
5239   else
5240   {
5241     aModifiedElems = new SMESH::long_array;
5242     aModifiedElems->length( 0 );
5243   }
5244
5245   TPythonDump pyDump; // suppress dump by the next line
5246
5247   bool done = DoubleNodes( aNodes, aModifiedElems );
5248
5249   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5250
5251   return done;
5252 }
5253
5254 /*!
5255  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5256  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
5257  * \param theNodes - group of nodes to be doubled.
5258  * \param theModifiedElems - group of elements to be updated.
5259  * \return a new group with newly created nodes
5260  * \sa DoubleNodeGroup()
5261  */
5262 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
5263                                                                SMESH::SMESH_GroupBase_ptr theModifiedElems )
5264 {
5265   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5266     return false;
5267
5268   SMESH::SMESH_Group_var aNewGroup;
5269
5270   // Duplicate nodes
5271   SMESH::long_array_var aNodes = theNodes->GetListOfID();
5272   SMESH::long_array_var aModifiedElems;
5273   if ( !CORBA::is_nil( theModifiedElems ) )
5274     aModifiedElems = theModifiedElems->GetListOfID();
5275   else {
5276     aModifiedElems = new SMESH::long_array;
5277     aModifiedElems->length( 0 );
5278   }
5279
5280   TPythonDump pyDump; // suppress dump by the next line
5281
5282   bool aResult = DoubleNodes( aNodes, aModifiedElems );
5283
5284   if ( aResult )
5285   {
5286     // Create group with newly created nodes
5287     SMESH::long_array_var anIds = GetLastCreatedNodes();
5288     if (anIds->length() > 0) {
5289       string anUnindexedName (theNodes->GetName());
5290       string aNewName = generateGroupName(anUnindexedName + "_double");
5291       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5292       aNewGroup->Add(anIds);
5293     }
5294   }
5295
5296   pyDump << "createdNodes = " << this << ".DoubleNodeGroupNew( " << theNodes << ", "
5297     << theModifiedElems << " )";
5298
5299   return aNewGroup._retn();
5300 }
5301
5302 //================================================================================
5303 /*!
5304   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5305   This method provided for convenience works as DoubleNodes() described above.
5306   \param theNodes - list of groups of nodes to be doubled
5307   \param theModifiedElems - list of groups of elements to be updated.
5308   \return TRUE if operation has been completed successfully, FALSE otherwise
5309   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5310 */
5311 //================================================================================
5312
5313 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5314                                                     const SMESH::ListOfGroups& theModifiedElems )
5315 {
5316   initData();
5317
5318   ::SMESH_MeshEditor aMeshEditor( myMesh );
5319
5320   std::list< int > aNodes;
5321   int i, n, j, m;
5322   for ( i = 0, n = theNodes.length(); i < n; i++ )
5323   {
5324     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5325     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5326     {
5327       SMESH::long_array_var aCurr = aGrp->GetListOfID();
5328       for ( j = 0, m = aCurr->length(); j < m; j++ )
5329         aNodes.push_back( aCurr[ j ] );
5330     }
5331   }
5332
5333   std::list< int > anElems;
5334   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5335   {
5336     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
5337     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
5338     {
5339       SMESH::long_array_var aCurr = aGrp->GetListOfID();
5340       for ( j = 0, m = aCurr->length(); j < m; j++ )
5341         anElems.push_back( aCurr[ j ] );
5342     }
5343   }
5344
5345   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
5346
5347   storeResult( aMeshEditor) ;
5348
5349   myMesh->GetMeshDS()->Modified();
5350   if ( aResult )
5351     myMesh->SetIsModified( true );
5352
5353
5354   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5355
5356   return aResult;
5357 }
5358
5359 //================================================================================
5360 /*!
5361  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5362  * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5363  * \param theNodes - group of nodes to be doubled.
5364  * \param theModifiedElems - group of elements to be updated.
5365  * \return a new group with newly created nodes
5366  * \sa DoubleNodeGroups()
5367  */
5368 //================================================================================
5369
5370 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5371                                                                 const SMESH::ListOfGroups& theModifiedElems )
5372 {
5373   SMESH::SMESH_Group_var aNewGroup;
5374
5375   TPythonDump pyDump; // suppress dump by the next line
5376
5377   bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5378
5379   if ( aResult )
5380   {
5381     // Create group with newly created nodes
5382     SMESH::long_array_var anIds = GetLastCreatedNodes();
5383     if (anIds->length() > 0) {
5384       string anUnindexedName (theNodes[0]->GetName());
5385       string aNewName = generateGroupName(anUnindexedName + "_double");
5386       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5387       aNewGroup->Add(anIds);
5388     }
5389   }
5390
5391   pyDump << "createdNodes = " << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5392     << theModifiedElems << " )";
5393
5394   return aNewGroup._retn();
5395 }
5396
5397
5398 //================================================================================
5399 /*!
5400   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5401   \param theElems - the list of elements (edges or faces) to be replicated
5402   The nodes for duplication could be found from these elements
5403   \param theNodesNot - list of nodes to NOT replicate
5404   \param theAffectedElems - the list of elements (cells and edges) to which the
5405   replicated nodes should be associated to.
5406   \return TRUE if operation has been completed successfully, FALSE otherwise
5407   \sa DoubleNodeGroup(), DoubleNodeGroups()
5408 */
5409 //================================================================================
5410
5411 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5412                                                    const SMESH::long_array& theNodesNot,
5413                                                    const SMESH::long_array& theAffectedElems )
5414
5415 {
5416   initData();
5417
5418   ::SMESH_MeshEditor aMeshEditor( myMesh );
5419
5420   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5421   TIDSortedElemSet anElems, aNodes, anAffected;
5422   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5423   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5424   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5425
5426   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5427
5428   storeResult( aMeshEditor) ;
5429
5430   myMesh->GetMeshDS()->Modified();
5431   if ( aResult )
5432     myMesh->SetIsModified( true );
5433
5434   // Update Python script
5435   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5436                 << theNodesNot << ", " << theAffectedElems << " )";
5437   return aResult;
5438 }
5439
5440 //================================================================================
5441 /*!
5442   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5443   \param theElems - the list of elements (edges or faces) to be replicated
5444   The nodes for duplication could be found from these elements
5445   \param theNodesNot - list of nodes to NOT replicate
5446   \param theShape - shape to detect affected elements (element which geometric center
5447   located on or inside shape).
5448   The replicated nodes should be associated to affected elements.
5449   \return TRUE if operation has been completed successfully, FALSE otherwise
5450   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5451 */
5452 //================================================================================
5453
5454 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5455                                                             const SMESH::long_array& theNodesNot,
5456                                                             GEOM::GEOM_Object_ptr    theShape )
5457
5458 {
5459   initData();
5460
5461   ::SMESH_MeshEditor aMeshEditor( myMesh );
5462
5463   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5464   TIDSortedElemSet anElems, aNodes;
5465   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5466   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5467
5468   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5469   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5470
5471   storeResult( aMeshEditor) ;
5472
5473   myMesh->GetMeshDS()->Modified();
5474   if ( aResult )
5475     myMesh->SetIsModified( true );
5476
5477   // Update Python script
5478   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5479                 << theNodesNot << ", " << theShape << " )";
5480   return aResult;
5481 }
5482
5483 //================================================================================
5484 /*!
5485   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5486   \param theElems - group of of elements (edges or faces) to be replicated
5487   \param theNodesNot - group of nodes not to replicated
5488   \param theAffectedElems - group of elements to which the replicated nodes
5489   should be associated to.
5490   \return TRUE if operation has been completed successfully, FALSE otherwise
5491   \sa DoubleNodes(), DoubleNodeGroups()
5492 */
5493 //================================================================================
5494
5495 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5496                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
5497                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
5498 {
5499   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5500     return false;
5501
5502   initData();
5503
5504   ::SMESH_MeshEditor aMeshEditor( myMesh );
5505
5506   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5507   TIDSortedElemSet anElems, aNodes, anAffected;
5508   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5509   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5510   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5511
5512   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5513
5514   storeResult( aMeshEditor) ;
5515
5516   myMesh->GetMeshDS()->Modified();
5517   if ( aResult )
5518     myMesh->SetIsModified( true );
5519
5520   // Update Python script
5521   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5522                 << theNodesNot << ", " << theAffectedElems << " )";
5523   return aResult;
5524 }
5525
5526 /*!
5527  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5528  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5529  * \param theElems - group of of elements (edges or faces) to be replicated
5530  * \param theNodesNot - group of nodes not to replicated
5531  * \param theAffectedElems - group of elements to which the replicated nodes
5532  *        should be associated to.
5533  * \return a new group with newly created elements
5534  * \sa DoubleNodeElemGroup()
5535  */
5536 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5537                                                                   SMESH::SMESH_GroupBase_ptr theNodesNot,
5538                                                                   SMESH::SMESH_GroupBase_ptr theAffectedElems)
5539 {
5540   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5541     return false;
5542
5543   SMESH::SMESH_Group_var aNewGroup;
5544
5545   initData();
5546
5547   ::SMESH_MeshEditor aMeshEditor( myMesh );
5548
5549   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5550   TIDSortedElemSet anElems, aNodes, anAffected;
5551   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5552   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5553   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5554
5555
5556   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5557
5558   storeResult( aMeshEditor) ;
5559
5560   if ( aResult ) {
5561     myMesh->SetIsModified( true );
5562
5563     // Create group with newly created elements
5564     SMESH::long_array_var anIds = GetLastCreatedElems();
5565     if (anIds->length() > 0) {
5566       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5567       string anUnindexedName (theElems->GetName());
5568       string aNewName = generateGroupName(anUnindexedName + "_double");
5569       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5570       aNewGroup->Add(anIds);
5571     }
5572   }
5573
5574   // Update Python script
5575   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupNew( " << theElems << ", "
5576     << theNodesNot << ", " << theAffectedElems << " )";
5577   return aNewGroup._retn();
5578 }
5579
5580 //================================================================================
5581 /*!
5582   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5583   \param theElems - group of of elements (edges or faces) to be replicated
5584   \param theNodesNot - group of nodes not to replicated
5585   \param theShape - shape to detect affected elements (element which geometric center
5586   located on or inside shape).
5587   The replicated nodes should be associated to affected elements.
5588   \return TRUE if operation has been completed successfully, FALSE otherwise
5589   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5590 */
5591 //================================================================================
5592
5593 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5594                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
5595                                                                GEOM::GEOM_Object_ptr      theShape )
5596
5597 {
5598   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5599     return false;
5600
5601   initData();
5602
5603   ::SMESH_MeshEditor aMeshEditor( myMesh );
5604
5605   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5606   TIDSortedElemSet anElems, aNodes, anAffected;
5607   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5608   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5609
5610   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5611   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5612
5613   storeResult( aMeshEditor) ;
5614
5615   myMesh->GetMeshDS()->Modified();
5616   if ( aResult )
5617     myMesh->SetIsModified( true );
5618
5619   // Update Python script
5620   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5621                 << theNodesNot << ", " << theShape << " )";
5622   return aResult;
5623 }
5624
5625 //================================================================================
5626 /*!
5627   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5628   This method provided for convenience works as DoubleNodes() described above.
5629   \param theElems - list of groups of elements (edges or faces) to be replicated
5630   \param theNodesNot - list of groups of nodes not to replicated
5631   \param theAffectedElems - group of elements to which the replicated nodes
5632   should be associated to.
5633   \return TRUE if operation has been completed successfully, FALSE otherwise
5634   \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5635 */
5636 //================================================================================
5637
5638 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5639                              SMESHDS_Mesh*              theMeshDS,
5640                              TIDSortedElemSet&          theElemSet,
5641                              const bool                 theIsNodeGrp)
5642 {
5643   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5644   {
5645     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5646     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5647                                     : aGrp->GetType() != SMESH::NODE ) )
5648     {
5649       SMESH::long_array_var anIDs = aGrp->GetIDs();
5650       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5651     }
5652   }
5653 }
5654
5655 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5656                                                         const SMESH::ListOfGroups& theNodesNot,
5657                                                         const SMESH::ListOfGroups& theAffectedElems)
5658 {
5659   initData();
5660
5661   ::SMESH_MeshEditor aMeshEditor( myMesh );
5662
5663   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5664   TIDSortedElemSet anElems, aNodes, anAffected;
5665   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5666   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5667   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5668
5669   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5670
5671   storeResult( aMeshEditor) ;
5672
5673   myMesh->GetMeshDS()->Modified();
5674   if ( aResult )
5675     myMesh->SetIsModified( true );
5676
5677   // Update Python script
5678   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5679                 << &theNodesNot << ", " << &theAffectedElems << " )";
5680   return aResult;
5681 }
5682
5683 //================================================================================
5684 /*!
5685  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5686  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5687   \param theElems - list of groups of elements (edges or faces) to be replicated
5688   \param theNodesNot - list of groups of nodes not to replicated
5689   \param theAffectedElems - group of elements to which the replicated nodes
5690   should be associated to.
5691  * \return a new group with newly created elements
5692  * \sa DoubleNodeElemGroups()
5693  */
5694 //================================================================================
5695
5696 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5697                                                                    const SMESH::ListOfGroups& theNodesNot,
5698                                                                    const SMESH::ListOfGroups& theAffectedElems)
5699 {
5700   SMESH::SMESH_Group_var aNewGroup;
5701   
5702   initData();
5703
5704   ::SMESH_MeshEditor aMeshEditor( myMesh );
5705
5706   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5707   TIDSortedElemSet anElems, aNodes, anAffected;
5708   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5709   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5710   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5711
5712   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5713
5714   storeResult( aMeshEditor) ;
5715
5716   myMesh->GetMeshDS()->Modified();
5717   if ( aResult ) {
5718     myMesh->SetIsModified( true );
5719
5720     // Create group with newly created elements
5721     SMESH::long_array_var anIds = GetLastCreatedElems();
5722     if (anIds->length() > 0) {
5723       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5724       string anUnindexedName (theElems[0]->GetName());
5725       string aNewName = generateGroupName(anUnindexedName + "_double");
5726       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5727       aNewGroup->Add(anIds);
5728     }
5729   }
5730
5731   // Update Python script
5732   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupsNew( " << &theElems << ", "
5733                 << &theNodesNot << ", " << &theAffectedElems << " )";
5734   return aNewGroup._retn();
5735 }
5736
5737 //================================================================================
5738 /*!
5739   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5740   This method provided for convenience works as DoubleNodes() described above.
5741   \param theElems - list of groups of elements (edges or faces) to be replicated
5742   \param theNodesNot - list of groups of nodes not to replicated
5743   \param theShape - shape to detect affected elements (element which geometric center
5744   located on or inside shape).
5745   The replicated nodes should be associated to affected elements.
5746   \return TRUE if operation has been completed successfully, FALSE otherwise
5747   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5748 */
5749 //================================================================================
5750
5751 CORBA::Boolean
5752 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5753                                                  const SMESH::ListOfGroups& theNodesNot,
5754                                                  GEOM::GEOM_Object_ptr      theShape )
5755 {
5756   initData();
5757
5758   ::SMESH_MeshEditor aMeshEditor( myMesh );
5759
5760   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5761   TIDSortedElemSet anElems, aNodes;
5762   listOfGroupToSet(theElems, aMeshDS, anElems,false );
5763   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5764
5765   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5766   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5767
5768   storeResult( aMeshEditor) ;
5769
5770   myMesh->GetMeshDS()->Modified();
5771   if ( aResult )
5772     myMesh->SetIsModified( true );
5773
5774   // Update Python script
5775   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5776                 << &theNodesNot << ", " << theShape << " )";
5777   return aResult;
5778 }
5779
5780 //================================================================================
5781 /*!
5782   \brief Generated skin mesh (containing 2D cells) from 3D mesh
5783    The created 2D mesh elements based on nodes of free faces of boundary volumes
5784   \return TRUE if operation has been completed successfully, FALSE otherwise
5785 */
5786 //================================================================================
5787
5788 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5789 {
5790   initData();
5791
5792   ::SMESH_MeshEditor aMeshEditor( myMesh );
5793   bool aResult = aMeshEditor.Make2DMeshFrom3D();
5794   storeResult( aMeshEditor) ;
5795   myMesh->GetMeshDS()->Modified();
5796   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
5797   return aResult;
5798 }
5799
5800 //================================================================================
5801 /*!
5802  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
5803  * The list of groups must describe a partition of the mesh volumes.
5804  * The nodes of the internal faces at the boundaries of the groups are doubled.
5805  * In option, the internal faces are replaced by flat elements.
5806  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
5807  * The flat elements are stored in groups of volumes.
5808  * @param theDomains - list of groups of volumes
5809  * @param createJointElems - if TRUE, create the elements
5810  * @return TRUE if operation has been completed successfully, FALSE otherwise
5811  */
5812 //================================================================================
5813
5814 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
5815                                                                  CORBA::Boolean createJointElems )
5816   throw (SALOME::SALOME_Exception)
5817 {
5818   initData();
5819
5820   ::SMESH_MeshEditor aMeshEditor( myMesh );
5821
5822   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5823
5824   vector<TIDSortedElemSet> domains;
5825   domains.clear();
5826
5827   for ( int i = 0, n = theDomains.length(); i < n; i++ )
5828   {
5829     SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
5830     if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
5831     {
5832 //      if ( aGrp->GetType() != SMESH::VOLUME )
5833 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
5834       TIDSortedElemSet domain;
5835       domain.clear();
5836       domains.push_back(domain);
5837       SMESH::long_array_var anIDs = aGrp->GetIDs();
5838       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
5839     }
5840   }
5841
5842   bool aResult = aMeshEditor.DoubleNodesOnGroupBoundaries( domains, createJointElems );
5843   // TODO publish the groups of flat elements in study
5844
5845   storeResult( aMeshEditor) ;
5846   myMesh->GetMeshDS()->Modified();
5847
5848   // Update Python script
5849   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
5850       << ", " << createJointElems << " )";
5851   return aResult;
5852 }
5853
5854 //================================================================================
5855 /*!
5856  * \brief Double nodes on some external faces and create flat elements.
5857  * Flat elements are mainly used by some types of mechanic calculations.
5858  *
5859  * Each group of the list must be constituted of faces.
5860  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
5861  * @param theGroupsOfFaces - list of groups of faces
5862  * @return TRUE if operation has been completed successfully, FALSE otherwise
5863  */
5864 //================================================================================
5865
5866 CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
5867 {
5868   initData();
5869
5870   ::SMESH_MeshEditor aMeshEditor( myMesh );
5871
5872   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5873
5874   vector<TIDSortedElemSet> faceGroups;
5875   faceGroups.clear();
5876
5877   for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
5878   {
5879     SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
5880     if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
5881     {
5882       TIDSortedElemSet faceGroup;
5883       faceGroup.clear();
5884       faceGroups.push_back(faceGroup);
5885       SMESH::long_array_var anIDs = aGrp->GetIDs();
5886       arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
5887     }
5888   }
5889
5890   bool aResult = aMeshEditor.CreateFlatElementsOnFacesGroups( faceGroups );
5891   // TODO publish the groups of flat elements in study
5892
5893   storeResult( aMeshEditor) ;
5894   myMesh->GetMeshDS()->Modified();
5895
5896   // Update Python script
5897   TPythonDump() << "isDone = " << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
5898   return aResult;
5899 }
5900
5901 // issue 20749 ===================================================================
5902 /*!
5903  * \brief Creates missing boundary elements
5904  *  \param elements - elements whose boundary is to be checked
5905  *  \param dimension - defines type of boundary elements to create
5906  *  \param groupName - a name of group to store created boundary elements in,
5907  *                     "" means not to create the group
5908  *  \param meshName - a name of new mesh to store created boundary elements in,
5909  *                     "" means not to create the new mesh
5910  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
5911  *  \param toCopyExistingBondary - if true, not only new but also pre-existing
5912  *                                boundary elements will be copied into the new mesh
5913  *  \param group - returns the create group, if any
5914  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
5915  */
5916 // ================================================================================
5917
5918 SMESH::SMESH_Mesh_ptr
5919 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
5920                                      SMESH::Bnd_Dimension      dim,
5921                                      const char*               groupName,
5922                                      const char*               meshName,
5923                                      CORBA::Boolean            toCopyElements,
5924                                      CORBA::Boolean            toCopyExistingBondary,
5925                                      SMESH::SMESH_Group_out    group)
5926 {
5927   initData();
5928
5929   if ( dim > SMESH::BND_1DFROM2D )
5930     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
5931
5932   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5933
5934   SMESH::SMESH_Mesh_var mesh_var;
5935   SMESH::SMESH_Group_var group_var;
5936
5937   TPythonDump pyDump;
5938
5939   TIDSortedElemSet elements;
5940   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
5941   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
5942   {
5943     // mesh to fill in
5944     mesh_var =
5945       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
5946     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
5947     // other mesh
5948     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
5949
5950     // group of new boundary elements
5951     SMESH_Group* smesh_group = 0;
5952     if ( strlen(groupName) )
5953     {
5954       group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
5955       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
5956         smesh_group = group_i->GetSmeshGroup();
5957     }
5958
5959     // do it
5960     ::SMESH_MeshEditor aMeshEditor( myMesh );
5961     aMeshEditor.MakeBoundaryMesh( elements,
5962                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
5963                                   smesh_group,
5964                                   smesh_mesh,
5965                                   toCopyElements,
5966                                   toCopyExistingBondary);
5967     storeResult( aMeshEditor );
5968
5969     if ( smesh_mesh )
5970       smesh_mesh->GetMeshDS()->Modified();
5971   }
5972
5973   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
5974
5975   // result of MakeBoundaryMesh() is a tuple (mesh, group)
5976   if ( mesh_var->_is_nil() )
5977     pyDump << myMesh_i->_this() << ", ";
5978   else
5979     pyDump << mesh_var << ", ";
5980   if ( group_var->_is_nil() )
5981     pyDump << "_NoneGroup = "; // assignment to None is forbiden
5982   else
5983     pyDump << group_var << " = ";
5984   pyDump << this << ".MakeBoundaryMesh( "
5985          << idSource << ", "
5986          << "SMESH." << dimName[int(dim)] << ", "
5987          << "'" << groupName << "', "
5988          << "'" << meshName<< "', "
5989          << toCopyElements << ", "
5990          << toCopyExistingBondary << ")";
5991
5992   group = group_var._retn();
5993   return mesh_var._retn();
5994 }
5995
5996 //================================================================================
5997 /*!
5998  * \brief Creates missing boundary elements
5999  *  \param dimension - defines type of boundary elements to create
6000  *  \param groupName - a name of group to store all boundary elements in,
6001  *    "" means not to create the group
6002  *  \param meshName - a name of a new mesh, which is a copy of the initial 
6003  *    mesh + created boundary elements; "" means not to create the new mesh
6004  *  \param toCopyAll - if true, the whole initial mesh will be copied into
6005  *    the new mesh else only boundary elements will be copied into the new mesh
6006  *  \param groups - optional groups of elements to make boundary around
6007  *  \param mesh - returns the mesh where elements were added to
6008  *  \param group - returns the created group, if any
6009  *  \retval long - number of added boundary elements
6010  */
6011 //================================================================================
6012
6013 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
6014                                                      const char* groupName,
6015                                                      const char* meshName,
6016                                                      CORBA::Boolean toCopyAll,
6017                                                      const SMESH::ListOfIDSources& groups,
6018                                                      SMESH::SMESH_Mesh_out mesh,
6019                                                      SMESH::SMESH_Group_out group)
6020   throw (SALOME::SALOME_Exception)
6021 {
6022   Unexpect aCatch(SALOME_SalomeException);
6023
6024   initData();
6025
6026   if ( dim > SMESH::BND_1DFROM2D )
6027     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
6028
6029   // separate groups belonging to this and other mesh
6030   SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
6031   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
6032   groupsOfThisMesh->length( groups.length() );
6033   groupsOfOtherMesh->length( groups.length() );
6034   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
6035   for ( int i = 0; i < groups.length(); ++i )
6036   {
6037     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
6038     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
6039       groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
6040     else
6041       groupsOfThisMesh[ nbGroups++ ] = groups[i];
6042     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
6043       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
6044   }
6045   groupsOfThisMesh->length( nbGroups );
6046   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
6047
6048   int nbAdded = 0;
6049   TPythonDump pyDump;
6050
6051   if ( nbGroupsOfOtherMesh > 0 )
6052   {
6053     // process groups belonging to another mesh
6054     SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
6055     SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
6056     nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
6057                                              groupsOfOtherMesh, mesh, group );
6058   }
6059
6060   SMESH::SMESH_Mesh_var mesh_var;
6061   SMESH::SMESH_Group_var group_var;
6062
6063   // get mesh to fill
6064   mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
6065   const bool toCopyMesh = ( strlen( meshName ) > 0 );
6066   if ( toCopyMesh )
6067   {
6068     if ( toCopyAll )
6069       mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
6070                                                       meshName,
6071                                                       /*toCopyGroups=*/false,
6072                                                       /*toKeepIDs=*/true);
6073     else
6074       mesh_var = makeMesh(meshName);
6075   }
6076   SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
6077   SMESH_Mesh*  tgtMesh = &mesh_i->GetImpl();
6078
6079   // source mesh
6080   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
6081   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
6082
6083   // group of boundary elements
6084   SMESH_Group* smesh_group = 0;
6085   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
6086   if ( strlen(groupName) )
6087   {
6088     SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
6089     group_var = mesh_i->CreateGroup( groupType, groupName );
6090     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
6091       smesh_group = group_i->GetSmeshGroup();
6092   }
6093
6094   TIDSortedElemSet elements;
6095
6096   if ( groups.length() > 0 )
6097   {
6098     for ( int i = 0; i < nbGroups; ++i )
6099     {
6100       elements.clear();
6101       if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
6102       {
6103         SMESH::Bnd_Dimension bdim = 
6104           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
6105         ::SMESH_MeshEditor aMeshEditor( srcMesh );
6106         nbAdded += aMeshEditor.MakeBoundaryMesh( elements,
6107                                                  ::SMESH_MeshEditor::Bnd_Dimension(bdim),
6108                                                  smesh_group,
6109                                                  tgtMesh,
6110                                                  /*toCopyElements=*/false,
6111                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6112                                                  /*toAddExistingBondary=*/true,
6113                                                  /*aroundElements=*/true);
6114         storeResult( aMeshEditor );
6115       }
6116     }
6117   }
6118   else
6119   {
6120     ::SMESH_MeshEditor aMeshEditor( srcMesh );
6121     nbAdded += aMeshEditor.MakeBoundaryMesh( elements,
6122                                              ::SMESH_MeshEditor::Bnd_Dimension(dim),
6123                                              smesh_group,
6124                                              tgtMesh,
6125                                              /*toCopyElements=*/false,
6126                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
6127                                              /*toAddExistingBondary=*/true);
6128     storeResult( aMeshEditor );
6129   }
6130   tgtMesh->GetMeshDS()->Modified();
6131
6132   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
6133
6134   // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
6135   pyDump << "nbAdded, ";
6136   if ( mesh_var->_is_nil() )
6137     pyDump << myMesh_i->_this() << ", ";
6138   else
6139     pyDump << mesh_var << ", ";
6140   if ( group_var->_is_nil() )
6141     pyDump << "_NoneGroup = "; // assignment to None is forbiden
6142   else
6143     pyDump << group_var << " = ";
6144   pyDump << this << ".MakeBoundaryElements( "
6145          << "SMESH." << dimName[int(dim)] << ", "
6146          << "'" << groupName << "', "
6147          << "'" << meshName<< "', "
6148          << toCopyAll << ", "
6149          << groups << ")";
6150
6151   mesh  = mesh_var._retn();
6152   group = group_var._retn();
6153   return nbAdded;
6154 }