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