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