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