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