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