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