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   gp_Trsf aTrsf;
2940   switch ( theMirrorType ) {
2941   case  SMESH::SMESH_MeshEditor::POINT:
2942     aTrsf.SetMirror( P );
2943     break;
2944   case  SMESH::SMESH_MeshEditor::AXIS:
2945     aTrsf.SetMirror( gp_Ax1( P, V ));
2946     break;
2947   default:
2948     aTrsf.SetMirror( gp_Ax2( P, V ));
2949   }
2950
2951   TIDSortedElemSet  copyElements;
2952   TPreviewMesh      tmpMesh;
2953   TIDSortedElemSet* workElements = & theElements;
2954   SMESH_Mesh*       mesh = myMesh;
2955
2956   if ( myPreviewMode )
2957   {
2958     tmpMesh.Copy( theElements, copyElements);
2959     if ( !theCopy )
2960     {
2961       TIDSortedElemSet elemsAround, elemsAroundCopy;
2962       getElementsAround( theElements, GetMeshDS(), elemsAround );
2963       tmpMesh.Copy( elemsAround, elemsAroundCopy);
2964     }
2965     mesh = &tmpMesh;
2966     workElements = & copyElements;
2967     theMakeGroups = false;
2968   }
2969
2970   ::SMESH_MeshEditor anEditor( mesh );
2971   ::SMESH_MeshEditor::PGroupIDs groupIds =
2972       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
2973
2974   if(theCopy || myPreviewMode)
2975     storeResult(anEditor);
2976   else
2977   {
2978     myMesh->SetIsModified( true );
2979     myMesh->GetMeshDS()->Modified();
2980   }
2981   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2982 }
2983
2984 //=======================================================================
2985 //function : Mirror
2986 //purpose  :
2987 //=======================================================================
2988
2989 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
2990                                 const SMESH::AxisStruct &           theAxis,
2991                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
2992                                 CORBA::Boolean                      theCopy)
2993 {
2994   if ( !myPreviewMode ) {
2995     TPythonDump() << this << ".Mirror( "
2996                   << theIDsOfElements << ", "
2997                   << theAxis          << ", "
2998                   << mirrorTypeName(theMirrorType) << ", "
2999                   << theCopy          << " )";
3000   }
3001   if ( theIDsOfElements.length() > 0 )
3002   {
3003     TIDSortedElemSet elements;
3004     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3005     mirror(elements, theAxis, theMirrorType, theCopy, false);
3006   }
3007 }
3008
3009
3010 //=======================================================================
3011 //function : MirrorObject
3012 //purpose  :
3013 //=======================================================================
3014
3015 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
3016                                       const SMESH::AxisStruct &           theAxis,
3017                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3018                                       CORBA::Boolean                      theCopy)
3019 {
3020   if ( !myPreviewMode ) {
3021     TPythonDump() << this << ".MirrorObject( "
3022                   << theObject << ", "
3023                   << theAxis   << ", "
3024                   << mirrorTypeName(theMirrorType) << ", "
3025                   << theCopy   << " )";
3026   }
3027   TIDSortedElemSet elements;
3028
3029   bool emptyIfIsMesh = myPreviewMode ? false : true;
3030
3031   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3032     mirror(elements, theAxis, theMirrorType, theCopy, false);
3033 }
3034
3035 //=======================================================================
3036 //function : MirrorMakeGroups
3037 //purpose  :
3038 //=======================================================================
3039
3040 SMESH::ListOfGroups*
3041 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
3042                                      const SMESH::AxisStruct&            theMirror,
3043                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3044 {
3045   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3046
3047   SMESH::ListOfGroups * aGroups = 0;
3048   if ( theIDsOfElements.length() > 0 )
3049   {
3050     TIDSortedElemSet elements;
3051     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3052     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3053   }
3054   if (!myPreviewMode) {
3055     DumpGroupsList(aPythonDump, aGroups);
3056     aPythonDump << this << ".MirrorMakeGroups( "
3057                 << theIDsOfElements << ", "
3058                 << theMirror << ", "
3059                 << mirrorTypeName(theMirrorType) << " )";
3060   }
3061   return aGroups;
3062 }
3063
3064 //=======================================================================
3065 //function : MirrorObjectMakeGroups
3066 //purpose  :
3067 //=======================================================================
3068
3069 SMESH::ListOfGroups*
3070 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
3071                                            const SMESH::AxisStruct&            theMirror,
3072                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3073 {
3074   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3075
3076   SMESH::ListOfGroups * aGroups = 0;
3077   TIDSortedElemSet elements;
3078   if ( idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3079     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3080
3081   if (!myPreviewMode)
3082   {
3083     DumpGroupsList(aPythonDump,aGroups);
3084     aPythonDump << this << ".MirrorObjectMakeGroups( "
3085                 << theObject << ", "
3086                 << theMirror << ", "
3087                 << mirrorTypeName(theMirrorType) << " )";
3088   }
3089   return aGroups;
3090 }
3091
3092 //=======================================================================
3093 //function : MirrorMakeMesh
3094 //purpose  :
3095 //=======================================================================
3096
3097 SMESH::SMESH_Mesh_ptr
3098 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
3099                                    const SMESH::AxisStruct&            theMirror,
3100                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3101                                    CORBA::Boolean                      theCopyGroups,
3102                                    const char*                         theMeshName)
3103 {
3104   SMESH_Mesh_i* mesh_i;
3105   SMESH::SMESH_Mesh_var mesh;
3106   { // open new scope to dump "MakeMesh" command
3107     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3108
3109     TPythonDump pydump; // to prevent dump at mesh creation
3110
3111     mesh = makeMesh( theMeshName );
3112     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3113     if (mesh_i && theIDsOfElements.length() > 0 )
3114     {
3115       TIDSortedElemSet elements;
3116       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3117       mirror(elements, theMirror, theMirrorType,
3118              false, theCopyGroups, & mesh_i->GetImpl());
3119       mesh_i->CreateGroupServants();
3120     }
3121
3122     if (!myPreviewMode) {
3123       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3124              << theIDsOfElements << ", "
3125              << theMirror   << ", "
3126              << mirrorTypeName(theMirrorType) << ", "
3127              << theCopyGroups << ", '"
3128              << theMeshName << "' )";
3129     }
3130   }
3131
3132   //dump "GetGroups"
3133   if (!myPreviewMode && mesh_i)
3134     mesh_i->GetGroups();
3135
3136   return mesh._retn();
3137 }
3138
3139 //=======================================================================
3140 //function : MirrorObjectMakeMesh
3141 //purpose  :
3142 //=======================================================================
3143
3144 SMESH::SMESH_Mesh_ptr
3145 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
3146                                          const SMESH::AxisStruct&            theMirror,
3147                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3148                                          CORBA::Boolean                      theCopyGroups,
3149                                          const char*                         theMeshName)
3150 {
3151   SMESH_Mesh_i* mesh_i;
3152   SMESH::SMESH_Mesh_var mesh;
3153   { // open new scope to dump "MakeMesh" command
3154     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3155
3156     TPythonDump pydump; // to prevent dump at mesh creation
3157
3158     mesh = makeMesh( theMeshName );
3159     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3160     TIDSortedElemSet elements;
3161     if ( mesh_i &&
3162          idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3163     {
3164       mirror(elements, theMirror, theMirrorType,
3165              false, theCopyGroups, & mesh_i->GetImpl());
3166       mesh_i->CreateGroupServants();
3167     }
3168     if (!myPreviewMode) {
3169       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
3170              << theObject << ", "
3171              << theMirror   << ", "
3172              << mirrorTypeName(theMirrorType) << ", "
3173              << theCopyGroups << ", '"
3174              << theMeshName << "' )";
3175     }
3176   }
3177
3178   //dump "GetGroups"
3179   if (!myPreviewMode && mesh_i)
3180     mesh_i->GetGroups();
3181
3182   return mesh._retn();
3183 }
3184
3185 //=======================================================================
3186 //function : translate
3187 //purpose  :
3188 //=======================================================================
3189
3190 SMESH::ListOfGroups*
3191 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
3192                               const SMESH::DirStruct &  theVector,
3193                               CORBA::Boolean            theCopy,
3194                               bool                      theMakeGroups,
3195                               ::SMESH_Mesh*             theTargetMesh)
3196 {
3197   initData();
3198
3199   gp_Trsf aTrsf;
3200   const SMESH::PointStruct * P = &theVector.PS;
3201   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
3202
3203   TIDSortedElemSet  copyElements;
3204   TIDSortedElemSet* workElements = &theElements;
3205   TPreviewMesh      tmpMesh;
3206   SMESH_Mesh*       mesh = myMesh;
3207
3208   if ( myPreviewMode )
3209   {
3210     tmpMesh.Copy( theElements, copyElements);
3211     if ( !theCopy )
3212     {
3213       TIDSortedElemSet elemsAround, elemsAroundCopy;
3214       getElementsAround( theElements, GetMeshDS(), elemsAround );
3215       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3216     }
3217     mesh = &tmpMesh;
3218     workElements = & copyElements;
3219     theMakeGroups = false;
3220   }
3221
3222   ::SMESH_MeshEditor anEditor( mesh );
3223   ::SMESH_MeshEditor::PGroupIDs groupIds =
3224       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3225
3226   if(theCopy || myPreviewMode)
3227     storeResult(anEditor);
3228   else
3229   {
3230     myMesh->GetMeshDS()->Modified();
3231     myMesh->SetIsModified( true );
3232   }
3233
3234   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3235 }
3236
3237 //=======================================================================
3238 //function : Translate
3239 //purpose  :
3240 //=======================================================================
3241
3242 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
3243                                    const SMESH::DirStruct &  theVector,
3244                                    CORBA::Boolean            theCopy)
3245 {
3246   if (!myPreviewMode) {
3247     TPythonDump() << this << ".Translate( "
3248                   << theIDsOfElements << ", "
3249                   << theVector << ", "
3250                   << theCopy << " )";
3251   }
3252   if (theIDsOfElements.length()) {
3253     TIDSortedElemSet elements;
3254     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3255     translate(elements, theVector, theCopy, false);
3256   }
3257 }
3258
3259 //=======================================================================
3260 //function : TranslateObject
3261 //purpose  :
3262 //=======================================================================
3263
3264 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
3265                                          const SMESH::DirStruct &  theVector,
3266                                          CORBA::Boolean            theCopy)
3267 {
3268   if (!myPreviewMode) {
3269     TPythonDump() << this << ".TranslateObject( "
3270                   << theObject << ", "
3271                   << theVector << ", "
3272                   << theCopy << " )";
3273   }
3274   TIDSortedElemSet elements;
3275
3276   bool emptyIfIsMesh = myPreviewMode ? false : true;
3277   
3278   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3279     translate(elements, theVector, theCopy, false);
3280 }
3281
3282 //=======================================================================
3283 //function : TranslateMakeGroups
3284 //purpose  :
3285 //=======================================================================
3286
3287 SMESH::ListOfGroups*
3288 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
3289                                         const SMESH::DirStruct&  theVector)
3290 {
3291   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3292
3293   SMESH::ListOfGroups * aGroups = 0;
3294   if (theIDsOfElements.length()) {
3295     TIDSortedElemSet elements;
3296     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3297     aGroups = translate(elements,theVector,true,true);
3298   }
3299   if (!myPreviewMode) {
3300     DumpGroupsList(aPythonDump, aGroups);
3301     aPythonDump << this << ".TranslateMakeGroups( "
3302                 << theIDsOfElements << ", "
3303                 << theVector << " )";
3304   }
3305   return aGroups;
3306 }
3307
3308 //=======================================================================
3309 //function : TranslateObjectMakeGroups
3310 //purpose  :
3311 //=======================================================================
3312
3313 SMESH::ListOfGroups*
3314 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3315                                               const SMESH::DirStruct&   theVector)
3316 {
3317   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3318
3319   SMESH::ListOfGroups * aGroups = 0;
3320   TIDSortedElemSet elements;
3321   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3322     aGroups = translate(elements, theVector, true, true);
3323
3324   if (!myPreviewMode) {
3325     DumpGroupsList(aPythonDump, aGroups);
3326     aPythonDump << this << ".TranslateObjectMakeGroups( "
3327                 << theObject << ", "
3328                 << theVector << " )";
3329   }
3330   return aGroups;
3331 }
3332
3333 //=======================================================================
3334 //function : TranslateMakeMesh
3335 //purpose  :
3336 //=======================================================================
3337
3338 SMESH::SMESH_Mesh_ptr
3339 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
3340                                       const SMESH::DirStruct&  theVector,
3341                                       CORBA::Boolean           theCopyGroups,
3342                                       const char*              theMeshName)
3343 {
3344   SMESH_Mesh_i* mesh_i;
3345   SMESH::SMESH_Mesh_var mesh;
3346
3347   { // open new scope to dump "MakeMesh" command
3348     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3349
3350     TPythonDump pydump; // to prevent dump at mesh creation
3351
3352     mesh = makeMesh( theMeshName );
3353     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3354
3355     if ( mesh_i && theIDsOfElements.length() )
3356     {
3357       TIDSortedElemSet elements;
3358       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3359       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
3360       mesh_i->CreateGroupServants();
3361     }
3362
3363     if ( !myPreviewMode ) {
3364       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
3365              << theIDsOfElements << ", "
3366              << theVector   << ", "
3367              << theCopyGroups << ", '"
3368              << theMeshName << "' )";
3369     }
3370   }
3371
3372   //dump "GetGroups"
3373   if (!myPreviewMode && mesh_i)
3374     mesh_i->GetGroups();
3375
3376   return mesh._retn();
3377 }
3378
3379 //=======================================================================
3380 //function : TranslateObjectMakeMesh
3381 //purpose  :
3382 //=======================================================================
3383
3384 SMESH::SMESH_Mesh_ptr
3385 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3386                                             const SMESH::DirStruct&   theVector,
3387                                             CORBA::Boolean            theCopyGroups,
3388                                             const char*               theMeshName)
3389 {
3390   SMESH_Mesh_i* mesh_i;
3391   SMESH::SMESH_Mesh_var mesh;
3392   { // open new scope to dump "MakeMesh" command
3393     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3394
3395     TPythonDump pydump; // to prevent dump at mesh creation
3396     mesh = makeMesh( theMeshName );
3397     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3398
3399     TIDSortedElemSet elements;
3400     if ( mesh_i &&
3401       idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3402     {
3403       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
3404       mesh_i->CreateGroupServants();
3405     }
3406     if ( !myPreviewMode ) {
3407       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
3408              << theObject << ", "
3409              << theVector   << ", "
3410              << theCopyGroups << ", '"
3411              << theMeshName << "' )";
3412     }
3413   }
3414
3415   // dump "GetGroups"
3416   if (!myPreviewMode && mesh_i)
3417     mesh_i->GetGroups();
3418
3419   return mesh._retn();
3420 }
3421
3422 //=======================================================================
3423 //function : rotate
3424 //purpose  :
3425 //=======================================================================
3426
3427 SMESH::ListOfGroups*
3428 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
3429                            const SMESH::AxisStruct & theAxis,
3430                            CORBA::Double             theAngle,
3431                            CORBA::Boolean            theCopy,
3432                            bool                      theMakeGroups,
3433                            ::SMESH_Mesh*             theTargetMesh)
3434 {
3435   initData();
3436
3437   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3438   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3439
3440   gp_Trsf aTrsf;
3441   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
3442
3443   TIDSortedElemSet  copyElements;
3444   TIDSortedElemSet* workElements = &theElements;
3445   TPreviewMesh      tmpMesh;
3446   SMESH_Mesh*       mesh = myMesh;
3447
3448   if ( myPreviewMode ) {
3449     tmpMesh.Copy( theElements, copyElements );
3450     if ( !theCopy )
3451     {
3452       TIDSortedElemSet elemsAround, elemsAroundCopy;
3453       getElementsAround( theElements, GetMeshDS(), elemsAround );
3454       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3455     }
3456     mesh = &tmpMesh;
3457     workElements = &copyElements;
3458     theMakeGroups = false;
3459   }
3460
3461   ::SMESH_MeshEditor anEditor( mesh );
3462   ::SMESH_MeshEditor::PGroupIDs groupIds =
3463       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3464
3465   if(theCopy || myPreviewMode)
3466     storeResult(anEditor);
3467   else
3468   {
3469     myMesh->GetMeshDS()->Modified();
3470     myMesh->SetIsModified( true );
3471   }
3472
3473   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3474 }
3475
3476 //=======================================================================
3477 //function : Rotate
3478 //purpose  :
3479 //=======================================================================
3480
3481 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
3482                                 const SMESH::AxisStruct & theAxis,
3483                                 CORBA::Double             theAngle,
3484                                 CORBA::Boolean            theCopy)
3485 {
3486   if (!myPreviewMode) {
3487     TPythonDump() << this << ".Rotate( "
3488                   << theIDsOfElements << ", "
3489                   << theAxis << ", "
3490                   << theAngle << ", "
3491                   << theCopy << " )";
3492   }
3493   if (theIDsOfElements.length() > 0)
3494   {
3495     TIDSortedElemSet elements;
3496     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3497     rotate(elements,theAxis,theAngle,theCopy,false);
3498   }
3499 }
3500
3501 //=======================================================================
3502 //function : RotateObject
3503 //purpose  :
3504 //=======================================================================
3505
3506 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
3507                                       const SMESH::AxisStruct & theAxis,
3508                                       CORBA::Double             theAngle,
3509                                       CORBA::Boolean            theCopy)
3510 {
3511   if ( !myPreviewMode ) {
3512     TPythonDump() << this << ".RotateObject( "
3513                   << theObject << ", "
3514                   << theAxis << ", "
3515                   << theAngle << ", "
3516                   << theCopy << " )";
3517   }
3518   TIDSortedElemSet elements;
3519   bool emptyIfIsMesh = myPreviewMode ? false : true;
3520   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3521     rotate(elements,theAxis,theAngle,theCopy,false);
3522 }
3523
3524 //=======================================================================
3525 //function : RotateMakeGroups
3526 //purpose  :
3527 //=======================================================================
3528
3529 SMESH::ListOfGroups*
3530 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
3531                                      const SMESH::AxisStruct& theAxis,
3532                                      CORBA::Double            theAngle)
3533 {
3534   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3535
3536   SMESH::ListOfGroups * aGroups = 0;
3537   if (theIDsOfElements.length() > 0)
3538   {
3539     TIDSortedElemSet elements;
3540     arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3541     aGroups = rotate(elements,theAxis,theAngle,true,true);
3542   }
3543   if (!myPreviewMode) {
3544     DumpGroupsList(aPythonDump, aGroups);
3545     aPythonDump << this << ".RotateMakeGroups( "
3546                 << theIDsOfElements << ", "
3547                 << theAxis << ", "
3548                 << theAngle << " )";
3549   }
3550   return aGroups;
3551 }
3552
3553 //=======================================================================
3554 //function : RotateObjectMakeGroups
3555 //purpose  :
3556 //=======================================================================
3557
3558 SMESH::ListOfGroups*
3559 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
3560                                            const SMESH::AxisStruct&  theAxis,
3561                                            CORBA::Double             theAngle)
3562 {
3563   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3564
3565   SMESH::ListOfGroups * aGroups = 0;
3566   TIDSortedElemSet elements;
3567   if (idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3568     aGroups = rotate(elements, theAxis, theAngle, true, true);
3569
3570   if (!myPreviewMode) {
3571     DumpGroupsList(aPythonDump, aGroups);
3572     aPythonDump << this << ".RotateObjectMakeGroups( "
3573                 << theObject << ", "
3574                 << theAxis << ", "
3575                 << theAngle << " )";
3576   }
3577   return aGroups;
3578 }
3579
3580 //=======================================================================
3581 //function : RotateMakeMesh
3582 //purpose  :
3583 //=======================================================================
3584
3585 SMESH::SMESH_Mesh_ptr
3586 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
3587                                    const SMESH::AxisStruct& theAxis,
3588                                    CORBA::Double            theAngleInRadians,
3589                                    CORBA::Boolean           theCopyGroups,
3590                                    const char*              theMeshName)
3591 {
3592   SMESH::SMESH_Mesh_var mesh;
3593   SMESH_Mesh_i* mesh_i;
3594
3595   { // open new scope to dump "MakeMesh" command
3596     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3597
3598     TPythonDump pydump; // to prevent dump at mesh creation
3599
3600     mesh = makeMesh( theMeshName );
3601     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3602
3603     if ( mesh_i && theIDsOfElements.length() > 0 )
3604     {
3605       TIDSortedElemSet elements;
3606       arrayToSet(theIDsOfElements, GetMeshDS(), elements);
3607       rotate(elements, theAxis, theAngleInRadians,
3608              false, theCopyGroups, & mesh_i->GetImpl());
3609       mesh_i->CreateGroupServants();
3610     }
3611     if ( !myPreviewMode ) {
3612       pydump << mesh << " = " << this << ".RotateMakeMesh( "
3613              << theIDsOfElements << ", "
3614              << theAxis << ", "
3615              << theAngleInRadians   << ", "
3616              << theCopyGroups << ", '"
3617              << theMeshName << "' )";
3618     }
3619   }
3620
3621   // dump "GetGroups"
3622   if (!myPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
3623     mesh_i->GetGroups();
3624
3625   return mesh._retn();
3626 }
3627
3628 //=======================================================================
3629 //function : RotateObjectMakeMesh
3630 //purpose  :
3631 //=======================================================================
3632
3633 SMESH::SMESH_Mesh_ptr
3634 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
3635                                          const SMESH::AxisStruct&  theAxis,
3636                                          CORBA::Double             theAngleInRadians,
3637                                          CORBA::Boolean            theCopyGroups,
3638                                          const char*               theMeshName)
3639 {
3640   SMESH::SMESH_Mesh_var mesh;
3641   SMESH_Mesh_i* mesh_i;
3642
3643   {// open new scope to dump "MakeMesh" command
3644    // and then "GetGroups" using SMESH_Mesh::GetGroups()
3645
3646     TPythonDump pydump; // to prevent dump at mesh creation
3647     mesh = makeMesh( theMeshName );
3648     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3649
3650     TIDSortedElemSet elements;
3651     if (mesh_i &&
3652         idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3653     {
3654       rotate(elements, theAxis, theAngleInRadians,
3655              false, theCopyGroups, & mesh_i->GetImpl());
3656       mesh_i->CreateGroupServants();
3657     }
3658     if ( !myPreviewMode ) {
3659       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
3660              << theObject << ", "
3661              << theAxis << ", "
3662              << theAngleInRadians   << ", "
3663              << theCopyGroups << ", '"
3664              << theMeshName << "' )";
3665     }
3666   }
3667
3668   // dump "GetGroups"
3669   if (!myPreviewMode && mesh_i)
3670     mesh_i->GetGroups();
3671
3672   return mesh._retn();
3673 }
3674
3675 //=======================================================================
3676 //function : scale
3677 //purpose  :
3678 //=======================================================================
3679
3680 SMESH::ListOfGroups*
3681 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
3682                           const SMESH::PointStruct&  thePoint,
3683                           const SMESH::double_array& theScaleFact,
3684                           CORBA::Boolean             theCopy,
3685                           bool                       theMakeGroups,
3686                           ::SMESH_Mesh*              theTargetMesh)
3687 {
3688   initData();
3689   if ( theScaleFact.length() < 1 )
3690     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
3691   if ( theScaleFact.length() == 2 )
3692     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
3693
3694   TIDSortedElemSet elements;
3695   bool emptyIfIsMesh = myPreviewMode ? false : true;
3696   if ( !idSourceToSet(theObject, GetMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3697     return 0;
3698
3699   double S[3] = {
3700     theScaleFact[0],
3701     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
3702     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
3703   };
3704   double tol = std::numeric_limits<double>::max();
3705   gp_Trsf aTrsf;
3706   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
3707                    0,    S[1], 0,    thePoint.y * (1-S[1]),
3708                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
3709
3710   TIDSortedElemSet  copyElements;
3711   TPreviewMesh      tmpMesh;
3712   TIDSortedElemSet* workElements = &elements;
3713   SMESH_Mesh*       mesh = myMesh;
3714   
3715   if ( myPreviewMode )
3716   {
3717     tmpMesh.Copy( elements, copyElements);
3718     if ( !theCopy )
3719     {
3720       TIDSortedElemSet elemsAround, elemsAroundCopy;
3721       getElementsAround( elements, GetMeshDS(), elemsAround );
3722       tmpMesh.Copy( elemsAround, elemsAroundCopy);
3723     }
3724     mesh = &tmpMesh;
3725     workElements = & copyElements;
3726     theMakeGroups = false;
3727   }
3728
3729   ::SMESH_MeshEditor anEditor( mesh );
3730   ::SMESH_MeshEditor::PGroupIDs groupIds =
3731       anEditor.Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3732
3733   if(theCopy || myPreviewMode )
3734     storeResult(anEditor);
3735   else
3736   {
3737     myMesh->GetMeshDS()->Modified();
3738     myMesh->SetIsModified( true );
3739   }
3740   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3741 }
3742
3743 //=======================================================================
3744 //function : Scale
3745 //purpose  :
3746 //=======================================================================
3747
3748 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
3749                                const SMESH::PointStruct&  thePoint,
3750                                const SMESH::double_array& theScaleFact,
3751                                CORBA::Boolean             theCopy)
3752 {
3753   if ( !myPreviewMode ) {
3754     TPythonDump() << this << ".Scale( "
3755                   << theObject << ", "
3756                   << "SMESH.PointStruct( "  << thePoint.x << ", "
3757                   << thePoint.y << ", " << thePoint.z << " ) ,"
3758                   << theScaleFact << ", "
3759                   << theCopy << " )";
3760   }
3761   scale(theObject, thePoint, theScaleFact, theCopy, false);
3762 }
3763
3764
3765 //=======================================================================
3766 //function : ScaleMakeGroups
3767 //purpose  :
3768 //=======================================================================
3769
3770 SMESH::ListOfGroups*
3771 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3772                                     const SMESH::PointStruct&  thePoint,
3773                                     const SMESH::double_array& theScaleFact)
3774 {
3775   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3776
3777   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
3778   if (!myPreviewMode) {
3779     DumpGroupsList(aPythonDump, aGroups);
3780     aPythonDump << this << ".Scale("
3781                 << theObject << ","
3782                 << "SMESH.PointStruct(" <<thePoint.x << ","
3783                 << thePoint.y << "," << thePoint.z << "),"
3784                 << theScaleFact << ",True,True)";
3785   }
3786   return aGroups;
3787 }
3788
3789
3790 //=======================================================================
3791 //function : ScaleMakeMesh
3792 //purpose  :
3793 //=======================================================================
3794
3795 SMESH::SMESH_Mesh_ptr
3796 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
3797                                   const SMESH::PointStruct&  thePoint,
3798                                   const SMESH::double_array& theScaleFact,
3799                                   CORBA::Boolean             theCopyGroups,
3800                                   const char*                theMeshName)
3801 {
3802   SMESH_Mesh_i* mesh_i;
3803   SMESH::SMESH_Mesh_var mesh;
3804   { // open new scope to dump "MakeMesh" command
3805     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3806
3807     TPythonDump pydump; // to prevent dump at mesh creation
3808     mesh = makeMesh( theMeshName );
3809     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3810
3811     if ( mesh_i )
3812     {
3813       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
3814       mesh_i->CreateGroupServants();
3815     }
3816     if ( !myPreviewMode )
3817       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
3818              << theObject << ", "
3819              << "SMESH.PointStruct( "  << thePoint.x << ", "
3820              << thePoint.y << ", " << thePoint.z << " ) ,"
3821              << theScaleFact << ", "
3822              << theCopyGroups << ", '"
3823              << theMeshName << "' )";
3824   }
3825
3826   // dump "GetGroups"
3827   if (!myPreviewMode && mesh_i)
3828     mesh_i->GetGroups();
3829
3830   return mesh._retn();
3831 }
3832
3833
3834 //=======================================================================
3835 //function : FindCoincidentNodes
3836 //purpose  :
3837 //=======================================================================
3838
3839 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
3840                                               SMESH::array_of_long_array_out GroupsOfNodes)
3841 {
3842   initData();
3843
3844   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3845   ::SMESH_MeshEditor anEditor( myMesh );
3846   TIDSortedNodeSet nodes; // no input nodes
3847   anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3848
3849   GroupsOfNodes = new SMESH::array_of_long_array;
3850   GroupsOfNodes->length( aListOfListOfNodes.size() );
3851   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3852   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
3853     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3854     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3855     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3856     aGroup.length( aListOfNodes.size() );
3857     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3858       aGroup[ j ] = (*lIt)->GetID();
3859   }
3860   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
3861                 << Tolerance << " )";
3862 }
3863
3864 //=======================================================================
3865 //function : FindCoincidentNodesOnPart
3866 //purpose  :
3867 //=======================================================================
3868 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
3869                                                    CORBA::Double                  Tolerance,
3870                                                    SMESH::array_of_long_array_out GroupsOfNodes)
3871 {
3872   initData();
3873
3874   TIDSortedNodeSet nodes;
3875   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3876
3877   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3878   ::SMESH_MeshEditor anEditor( myMesh );
3879   if(!nodes.empty())
3880     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
3881
3882   GroupsOfNodes = new SMESH::array_of_long_array;
3883   GroupsOfNodes->length( aListOfListOfNodes.size() );
3884   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3885   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3886   {
3887     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3888     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3889     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
3890     aGroup.length( aListOfNodes.size() );
3891     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3892       aGroup[ j ] = (*lIt)->GetID();
3893   }
3894   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
3895                 <<theObject<<", "
3896                 << Tolerance << " )";
3897 }
3898
3899 //================================================================================
3900 /*!
3901  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
3902  *        ExceptSubMeshOrGroups
3903  */
3904 //================================================================================
3905
3906 void SMESH_MeshEditor_i::
3907 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
3908                              CORBA::Double                  theTolerance,
3909                              SMESH::array_of_long_array_out theGroupsOfNodes,
3910                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
3911 {
3912   initData();
3913
3914   TIDSortedNodeSet nodes;
3915   idSourceToNodeSet( theObject, GetMeshDS(), nodes );
3916
3917   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
3918   {
3919     TIDSortedNodeSet exceptNodes;
3920     idSourceToNodeSet( theExceptSubMeshOrGroups[i], GetMeshDS(), exceptNodes );
3921     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
3922     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
3923       nodes.erase( *avoidNode );
3924   }
3925   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3926   ::SMESH_MeshEditor anEditor( myMesh );
3927   if(!nodes.empty())
3928     anEditor.FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
3929
3930   theGroupsOfNodes = new SMESH::array_of_long_array;
3931   theGroupsOfNodes->length( aListOfListOfNodes.size() );
3932   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
3933   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
3934   {
3935     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
3936     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
3937     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
3938     aGroup.length( aListOfNodes.size() );
3939     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
3940       aGroup[ j ] = (*lIt)->GetID();
3941   }
3942   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
3943                 << theObject<<", "
3944                 << theTolerance << ", "
3945                 << theExceptSubMeshOrGroups << " )";
3946 }
3947
3948 //=======================================================================
3949 //function : MergeNodes
3950 //purpose  :
3951 //=======================================================================
3952
3953 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
3954 {
3955   initData();
3956
3957   SMESHDS_Mesh* aMesh = GetMeshDS();
3958
3959   TPythonDump aTPythonDump;
3960   aTPythonDump << this << ".MergeNodes([";
3961   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
3962   for (int i = 0; i < GroupsOfNodes.length(); i++)
3963   {
3964     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
3965     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
3966     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
3967     for ( int j = 0; j < aNodeGroup.length(); j++ )
3968     {
3969       CORBA::Long index = aNodeGroup[ j ];
3970       const SMDS_MeshNode * node = aMesh->FindNode(index);
3971       if ( node )
3972         aListOfNodes.push_back( node );
3973     }
3974     if ( aListOfNodes.size() < 2 )
3975       aListOfListOfNodes.pop_back();
3976
3977     if ( i > 0 ) aTPythonDump << ", ";
3978     aTPythonDump << aNodeGroup;
3979   }
3980   ::SMESH_MeshEditor anEditor( myMesh );
3981   anEditor.MergeNodes( aListOfListOfNodes );
3982
3983   aTPythonDump <<  "])";
3984   myMesh->GetMeshDS()->Modified();
3985   myMesh->SetIsModified( true );
3986 }
3987
3988 //=======================================================================
3989 //function : FindEqualElements
3990 //purpose  :
3991 //=======================================================================
3992 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
3993                                            SMESH::array_of_long_array_out GroupsOfElementsID)
3994 {
3995   initData();
3996
3997   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
3998   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
3999   {
4000     typedef list<int> TListOfIDs;
4001     set<const SMDS_MeshElement*> elems;
4002     SMESH::long_array_var aElementsId = theObject->GetIDs();
4003     SMESHDS_Mesh* aMesh = GetMeshDS();
4004
4005     for(int i = 0; i < aElementsId->length(); i++) {
4006       CORBA::Long anID = aElementsId[i];
4007       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
4008       if (elem) {
4009         elems.insert(elem);
4010       }
4011     }
4012
4013     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4014     ::SMESH_MeshEditor anEditor( myMesh );
4015     anEditor.FindEqualElements( elems, aListOfListOfElementsID );
4016
4017     GroupsOfElementsID = new SMESH::array_of_long_array;
4018     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4019
4020     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt = aListOfListOfElementsID.begin();
4021     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j) {
4022       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4023       TListOfIDs& listOfIDs = *arraysIt;
4024       aGroup.length( listOfIDs.size() );
4025       TListOfIDs::iterator idIt = listOfIDs.begin();
4026       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
4027         aGroup[ k ] = *idIt;
4028       }
4029     }
4030
4031     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4032                   <<theObject<<" )";
4033   }
4034 }
4035
4036 //=======================================================================
4037 //function : MergeElements
4038 //purpose  :
4039 //=======================================================================
4040
4041 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4042 {
4043   initData();
4044
4045   TPythonDump aTPythonDump;
4046   aTPythonDump << this << ".MergeElements( [";
4047
4048   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4049
4050   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4051     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4052     aListOfListOfElementsID.push_back( list< int >() );
4053     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4054     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4055       CORBA::Long id = anElemsIDGroup[ j ];
4056       aListOfElemsID.push_back( id );
4057     }
4058     if ( aListOfElemsID.size() < 2 )
4059       aListOfListOfElementsID.pop_back();
4060     if ( i > 0 ) aTPythonDump << ", ";
4061     aTPythonDump << anElemsIDGroup;
4062   }
4063
4064   ::SMESH_MeshEditor anEditor( myMesh );
4065   anEditor.MergeElements(aListOfListOfElementsID);
4066   myMesh->GetMeshDS()->Modified();
4067   myMesh->SetIsModified( true );
4068
4069   aTPythonDump << "] )";
4070 }
4071
4072 //=======================================================================
4073 //function : MergeEqualElements
4074 //purpose  :
4075 //=======================================================================
4076
4077 void SMESH_MeshEditor_i::MergeEqualElements()
4078 {
4079   initData();
4080
4081   ::SMESH_MeshEditor anEditor( myMesh );
4082   anEditor.MergeEqualElements();
4083
4084   TPythonDump() << this << ".MergeEqualElements()";
4085 }
4086
4087 //=============================================================================
4088 /*!
4089  * Move the node to a given point
4090  */
4091 //=============================================================================
4092
4093 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
4094                                             CORBA::Double x,
4095                                             CORBA::Double y,
4096                                             CORBA::Double z)
4097 {
4098   initData(/*deleteSearchers=*/false);
4099
4100   const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
4101   if ( !node )
4102     return false;
4103
4104   if ( theNodeSearcher )
4105     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4106
4107   if ( myPreviewMode ) // make preview data
4108   {
4109     // in a preview mesh, make edges linked to a node
4110     TPreviewMesh tmpMesh;
4111     TIDSortedElemSet linkedNodes;
4112     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4113     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4114     SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
4115     for ( ; nIt != linkedNodes.end(); ++nIt )
4116     {
4117       SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
4118       tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
4119     }
4120     // move copied node
4121     if ( nodeCpy1 )
4122       tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
4123     // fill preview data
4124     ::SMESH_MeshEditor anEditor( & tmpMesh );
4125     storeResult( anEditor );
4126   }
4127   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4128     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4129   else
4130     GetMeshDS()->MoveNode(node, x, y, z);
4131
4132   if ( !myPreviewMode )
4133   {
4134     // Update Python script
4135     TPythonDump() << "isDone = " << this << ".MoveNode( "
4136                   << NodeID << ", " << x << ", " << y << ", " << z << " )";
4137     myMesh->GetMeshDS()->Modified();
4138     myMesh->SetIsModified( true );
4139   }
4140
4141   return true;
4142 }
4143
4144 //================================================================================
4145 /*!
4146  * \brief Return ID of node closest to a given point
4147  */
4148 //================================================================================
4149
4150 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
4151                                                   CORBA::Double y,
4152                                                   CORBA::Double z)
4153 {
4154   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4155
4156   if ( !theNodeSearcher ) {
4157     ::SMESH_MeshEditor anEditor( myMesh );
4158     theNodeSearcher = anEditor.GetNodeSearcher();
4159   }
4160   gp_Pnt p( x,y,z );
4161   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
4162     return node->GetID();
4163
4164   return 0;
4165 }
4166
4167 //================================================================================
4168 /*!
4169  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
4170  * move the node closest to the point to point's location and return ID of the node
4171  */
4172 //================================================================================
4173
4174 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
4175                                                        CORBA::Double y,
4176                                                        CORBA::Double z,
4177                                                        CORBA::Long   theNodeID)
4178 {
4179   // We keep theNodeSearcher until any mesh modification:
4180   // 1) initData() deletes theNodeSearcher at any edition,
4181   // 2) TSearchersDeleter - at any mesh compute event and mesh change
4182
4183   initData(/*deleteSearchers=*/false);
4184
4185   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
4186
4187   int nodeID = theNodeID;
4188   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
4189   if ( !node ) // preview moving node
4190   {
4191     if ( !theNodeSearcher ) {
4192       ::SMESH_MeshEditor anEditor( myMesh );
4193       theNodeSearcher = anEditor.GetNodeSearcher();
4194     }
4195     gp_Pnt p( x,y,z );
4196     node = theNodeSearcher->FindClosestTo( p );
4197   }
4198   if ( node ) {
4199     nodeID = node->GetID();
4200     if ( myPreviewMode ) // make preview data
4201     {
4202       // in a preview mesh, make edges linked to a node
4203       TPreviewMesh tmpMesh;
4204       TIDSortedElemSet linkedNodes;
4205       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
4206       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
4207       for ( ; nIt != linkedNodes.end(); ++nIt )
4208       {
4209         SMDS_LinearEdge edge( node, cast2Node( *nIt ));
4210         tmpMesh.Copy( &edge );
4211       }
4212       // move copied node
4213       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
4214       if ( node )
4215         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
4216       // fill preview data
4217       ::SMESH_MeshEditor anEditor( & tmpMesh );
4218       storeResult( anEditor );
4219     }
4220     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
4221     {
4222       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
4223     }
4224     else
4225     {
4226       GetMeshDS()->MoveNode(node, x, y, z);
4227     }
4228   }
4229
4230   if ( !myPreviewMode )
4231   {
4232     TPythonDump() << "nodeID = " << this
4233                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
4234                   << ", " << nodeID << " )";
4235
4236     myMesh->GetMeshDS()->Modified();
4237     myMesh->SetIsModified( true );
4238   }
4239
4240   return nodeID;
4241 }
4242
4243 //=======================================================================
4244 /*!
4245  * Return elements of given type where the given point is IN or ON.
4246  *
4247  * 'ALL' type means elements of any type excluding nodes
4248  */
4249 //=======================================================================
4250
4251 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
4252                                                            CORBA::Double      y,
4253                                                            CORBA::Double      z,
4254                                                            SMESH::ElementType type)
4255 {
4256   SMESH::long_array_var res = new SMESH::long_array;
4257   vector< const SMDS_MeshElement* > foundElems;
4258
4259   theSearchersDeleter.Set( myMesh );
4260   if ( !theElementSearcher ) {
4261     ::SMESH_MeshEditor anEditor( myMesh );
4262     theElementSearcher = anEditor.GetElementSearcher();
4263   }
4264   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
4265                                            SMDSAbs_ElementType( type ),
4266                                            foundElems);
4267   res->length( foundElems.size() );
4268   for ( int i = 0; i < foundElems.size(); ++i )
4269     res[i] = foundElems[i]->GetID();
4270
4271   if ( !myPreviewMode ) // call from tui
4272     TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
4273                   << x << ", "
4274                   << y << ", "
4275                   << z << ", "
4276                   << type << " )";
4277
4278   return res._retn();
4279 }
4280
4281 //=======================================================================
4282 //function : GetPointState
4283 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
4284 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
4285 //=======================================================================
4286
4287 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
4288                                                CORBA::Double y,
4289                                                CORBA::Double z)
4290 {
4291   theSearchersDeleter.Set( myMesh );
4292   if ( !theElementSearcher ) {
4293     ::SMESH_MeshEditor anEditor( myMesh );
4294     theElementSearcher = anEditor.GetElementSearcher();
4295   }
4296   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
4297 }
4298
4299 //=======================================================================
4300 //function : convError
4301 //purpose  :
4302 //=======================================================================
4303
4304 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
4305
4306 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
4307 {
4308   switch ( e ) {
4309     RETCASE( SEW_OK );
4310     RETCASE( SEW_BORDER1_NOT_FOUND );
4311     RETCASE( SEW_BORDER2_NOT_FOUND );
4312     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
4313     RETCASE( SEW_BAD_SIDE_NODES );
4314     RETCASE( SEW_VOLUMES_TO_SPLIT );
4315     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
4316     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
4317     RETCASE( SEW_BAD_SIDE1_NODES );
4318     RETCASE( SEW_BAD_SIDE2_NODES );
4319   }
4320   return SMESH::SMESH_MeshEditor::SEW_OK;
4321 }
4322
4323 //=======================================================================
4324 //function : SewFreeBorders
4325 //purpose  :
4326 //=======================================================================
4327
4328 SMESH::SMESH_MeshEditor::Sew_Error
4329 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
4330                                    CORBA::Long SecondNodeID1,
4331                                    CORBA::Long LastNodeID1,
4332                                    CORBA::Long FirstNodeID2,
4333                                    CORBA::Long SecondNodeID2,
4334                                    CORBA::Long LastNodeID2,
4335                                    CORBA::Boolean CreatePolygons,
4336                                    CORBA::Boolean CreatePolyedrs)
4337 {
4338   initData();
4339
4340   SMESHDS_Mesh* aMesh = GetMeshDS();
4341
4342   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4343   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4344   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4345   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4346   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4347   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
4348
4349   if (!aBorderFirstNode ||
4350       !aBorderSecondNode||
4351       !aBorderLastNode)
4352     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4353   if (!aSide2FirstNode  ||
4354       !aSide2SecondNode ||
4355       !aSide2ThirdNode)
4356     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4357
4358   TPythonDump() << "error = " << this << ".SewFreeBorders( "
4359                 << FirstNodeID1  << ", "
4360                 << SecondNodeID1 << ", "
4361                 << LastNodeID1   << ", "
4362                 << FirstNodeID2  << ", "
4363                 << SecondNodeID2 << ", "
4364                 << LastNodeID2   << ", "
4365                 << CreatePolygons<< ", "
4366                 << CreatePolyedrs<< " )";
4367
4368   ::SMESH_MeshEditor anEditor( myMesh );
4369   SMESH::SMESH_MeshEditor::Sew_Error error =
4370     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4371                                        aBorderSecondNode,
4372                                        aBorderLastNode,
4373                                        aSide2FirstNode,
4374                                        aSide2SecondNode,
4375                                        aSide2ThirdNode,
4376                                        true,
4377                                        CreatePolygons,
4378                                        CreatePolyedrs) );
4379
4380   storeResult(anEditor);
4381
4382   myMesh->GetMeshDS()->Modified();
4383   myMesh->SetIsModified( true );
4384
4385   return error;
4386 }
4387
4388
4389 //=======================================================================
4390 //function : SewConformFreeBorders
4391 //purpose  :
4392 //=======================================================================
4393
4394 SMESH::SMESH_MeshEditor::Sew_Error
4395 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
4396                                           CORBA::Long SecondNodeID1,
4397                                           CORBA::Long LastNodeID1,
4398                                           CORBA::Long FirstNodeID2,
4399                                           CORBA::Long SecondNodeID2)
4400 {
4401   initData();
4402
4403   SMESHDS_Mesh* aMesh = GetMeshDS();
4404
4405   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
4406   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
4407   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
4408   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
4409   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
4410   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4411
4412   if (!aBorderFirstNode ||
4413       !aBorderSecondNode||
4414       !aBorderLastNode )
4415     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4416   if (!aSide2FirstNode  ||
4417       !aSide2SecondNode)
4418     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
4419
4420   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
4421                 << FirstNodeID1  << ", "
4422                 << SecondNodeID1 << ", "
4423                 << LastNodeID1   << ", "
4424                 << FirstNodeID2  << ", "
4425                 << SecondNodeID2 << " )";
4426
4427   ::SMESH_MeshEditor anEditor( myMesh );
4428   SMESH::SMESH_MeshEditor::Sew_Error error =
4429     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4430                                        aBorderSecondNode,
4431                                        aBorderLastNode,
4432                                        aSide2FirstNode,
4433                                        aSide2SecondNode,
4434                                        aSide2ThirdNode,
4435                                        true,
4436                                        false, false) );
4437
4438   storeResult(anEditor);
4439
4440   myMesh->GetMeshDS()->Modified();
4441   myMesh->SetIsModified( true );
4442
4443   return error;
4444 }
4445
4446
4447 //=======================================================================
4448 //function : SewBorderToSide
4449 //purpose  :
4450 //=======================================================================
4451
4452 SMESH::SMESH_MeshEditor::Sew_Error
4453 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
4454                                     CORBA::Long SecondNodeIDOnFreeBorder,
4455                                     CORBA::Long LastNodeIDOnFreeBorder,
4456                                     CORBA::Long FirstNodeIDOnSide,
4457                                     CORBA::Long LastNodeIDOnSide,
4458                                     CORBA::Boolean CreatePolygons,
4459                                     CORBA::Boolean CreatePolyedrs)
4460 {
4461   initData();
4462
4463   SMESHDS_Mesh* aMesh = GetMeshDS();
4464
4465   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
4466   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
4467   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
4468   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
4469   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
4470   const SMDS_MeshNode* aSide2ThirdNode   = 0;
4471
4472   if (!aBorderFirstNode ||
4473       !aBorderSecondNode||
4474       !aBorderLastNode  )
4475     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
4476   if (!aSide2FirstNode  ||
4477       !aSide2SecondNode)
4478     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
4479
4480   TPythonDump() << "error = " << this << ".SewBorderToSide( "
4481                 << FirstNodeIDOnFreeBorder  << ", "
4482                 << SecondNodeIDOnFreeBorder << ", "
4483                 << LastNodeIDOnFreeBorder   << ", "
4484                 << FirstNodeIDOnSide        << ", "
4485                 << LastNodeIDOnSide         << ", "
4486                 << CreatePolygons           << ", "
4487                 << CreatePolyedrs           << ") ";
4488
4489   ::SMESH_MeshEditor anEditor( myMesh );
4490   SMESH::SMESH_MeshEditor::Sew_Error error =
4491     convError( anEditor.SewFreeBorder (aBorderFirstNode,
4492                                        aBorderSecondNode,
4493                                        aBorderLastNode,
4494                                        aSide2FirstNode,
4495                                        aSide2SecondNode,
4496                                        aSide2ThirdNode,
4497                                        false,
4498                                        CreatePolygons,
4499                                        CreatePolyedrs) );
4500
4501   storeResult(anEditor);
4502
4503   myMesh->GetMeshDS()->Modified();
4504   myMesh->SetIsModified( true );
4505
4506   return error;
4507 }
4508
4509
4510 //=======================================================================
4511 //function : SewSideElements
4512 //purpose  :
4513 //=======================================================================
4514
4515 SMESH::SMESH_MeshEditor::Sew_Error
4516 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
4517                                     const SMESH::long_array& IDsOfSide2Elements,
4518                                     CORBA::Long NodeID1OfSide1ToMerge,
4519                                     CORBA::Long NodeID1OfSide2ToMerge,
4520                                     CORBA::Long NodeID2OfSide1ToMerge,
4521                                     CORBA::Long NodeID2OfSide2ToMerge)
4522 {
4523   initData();
4524
4525   SMESHDS_Mesh* aMesh = GetMeshDS();
4526
4527   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
4528   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
4529   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
4530   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
4531
4532   if (!aFirstNode1ToMerge ||
4533       !aFirstNode2ToMerge )
4534     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
4535   if (!aSecondNode1ToMerge||
4536       !aSecondNode2ToMerge)
4537     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
4538
4539   TIDSortedElemSet aSide1Elems, aSide2Elems;
4540   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
4541   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
4542
4543   TPythonDump() << "error = " << this << ".SewSideElements( "
4544                 << IDsOfSide1Elements << ", "
4545                 << IDsOfSide2Elements << ", "
4546                 << NodeID1OfSide1ToMerge << ", "
4547                 << NodeID1OfSide2ToMerge << ", "
4548                 << NodeID2OfSide1ToMerge << ", "
4549                 << NodeID2OfSide2ToMerge << ")";
4550
4551   ::SMESH_MeshEditor anEditor( myMesh );
4552   SMESH::SMESH_MeshEditor::Sew_Error error =
4553     convError( anEditor.SewSideElements (aSide1Elems, aSide2Elems,
4554                                          aFirstNode1ToMerge,
4555                                          aFirstNode2ToMerge,
4556                                          aSecondNode1ToMerge,
4557                                          aSecondNode2ToMerge));
4558
4559   storeResult(anEditor);
4560
4561   myMesh->GetMeshDS()->Modified();
4562   myMesh->SetIsModified( true );
4563
4564   return error;
4565 }
4566
4567 //================================================================================
4568 /*!
4569  * \brief Set new nodes for given element
4570  * \param ide - element id
4571  * \param newIDs - new node ids
4572  * \retval CORBA::Boolean - true if result is OK
4573  */
4574 //================================================================================
4575
4576 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
4577                                                    const SMESH::long_array& newIDs)
4578 {
4579   initData();
4580
4581   const SMDS_MeshElement* elem = GetMeshDS()->FindElement(ide);
4582   if(!elem) return false;
4583
4584   int nbn = newIDs.length();
4585   int i=0;
4586   vector<const SMDS_MeshNode*> aNodes(nbn);
4587   int nbn1=-1;
4588   for(; i<nbn; i++) {
4589     const SMDS_MeshNode* aNode = GetMeshDS()->FindNode(newIDs[i]);
4590     if(aNode) {
4591       nbn1++;
4592       aNodes[nbn1] = aNode;
4593     }
4594   }
4595   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
4596                 << ide << ", " << newIDs << " )";
4597
4598   MESSAGE("ChangeElementNodes");
4599   bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
4600
4601   myMesh->GetMeshDS()->Modified();
4602   if ( res )
4603     myMesh->SetIsModified( true );
4604
4605   return res;
4606 }
4607
4608 //================================================================================
4609 /*!
4610  * \brief Update myLastCreated* or myPreviewData
4611  * \param anEditor - it contains last modification results
4612  */
4613 //================================================================================
4614
4615 void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
4616 {
4617   if ( myPreviewMode ) { // --- MeshPreviewStruct filling ---
4618
4619     list<int> aNodesConnectivity;
4620     typedef map<int, int> TNodesMap;
4621     TNodesMap nodesMap;
4622
4623     TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( anEditor.GetMesh() );
4624     SMDSAbs_ElementType previewType = aPreviewMesh->myPreviewType;
4625
4626     SMESHDS_Mesh* aMeshDS = anEditor.GetMeshDS();
4627     int nbEdges = aMeshDS->NbEdges();
4628     int nbFaces = aMeshDS->NbFaces();
4629     int nbVolum = aMeshDS->NbVolumes();
4630     switch ( previewType ) {
4631     case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
4632     case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
4633     case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
4634     default:;
4635     }
4636     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
4637     myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
4638     int i = 0, j = 0;
4639     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator();
4640
4641     while ( itMeshElems->more() ) {
4642       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
4643       if ( previewType != SMDSAbs_All && aMeshElem->GetType() != previewType )
4644         continue;
4645
4646       SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
4647       while ( itElemNodes->more() ) {
4648         const SMDS_MeshNode* aMeshNode =
4649           static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
4650         int aNodeID = aMeshNode->GetID();
4651         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
4652         if ( anIter == nodesMap.end() ) {
4653           // filling the nodes coordinates
4654           myPreviewData->nodesXYZ[j].x = aMeshNode->X();
4655           myPreviewData->nodesXYZ[j].y = aMeshNode->Y();
4656           myPreviewData->nodesXYZ[j].z = aMeshNode->Z();
4657           anIter = nodesMap.insert( make_pair(aNodeID, j) ).first;
4658           j++;
4659         }
4660         aNodesConnectivity.push_back(anIter->second);
4661       }
4662
4663       // filling the elements types
4664       SMDSAbs_ElementType aType;
4665       bool isPoly;
4666       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
4667         aType = SMDSAbs_Node;
4668         isPoly = false;
4669         }
4670         else*/ {
4671         aType = aMeshElem->GetType();
4672         isPoly = aMeshElem->IsPoly();
4673       }
4674
4675       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
4676       myPreviewData->elementTypes[i].isPoly = isPoly;
4677       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
4678       i++;
4679
4680     }
4681     myPreviewData->nodesXYZ.length( j );
4682
4683     // filling the elements connectivities
4684     list<int>::iterator aConnIter = aNodesConnectivity.begin();
4685     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
4686     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
4687       myPreviewData->elementConnectivities[i] = *aConnIter;
4688
4689     return;
4690   }
4691
4692   {
4693     // append new nodes into myLastCreatedNodes
4694     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedNodes();
4695     int j = myLastCreatedNodes->length();
4696     int newLen = j + aSeq.Length();
4697     myLastCreatedNodes->length( newLen );
4698     for(int i=0; j<newLen; i++,j++)
4699       myLastCreatedNodes[j] = aSeq.Value(i+1)->GetID();
4700   }
4701   {
4702     // append new elements into myLastCreatedElems
4703     const SMESH_SequenceOfElemPtr& aSeq = anEditor.GetLastCreatedElems();
4704     int j = myLastCreatedElems->length();
4705     int newLen = j + aSeq.Length();
4706     myLastCreatedElems->length( newLen );
4707     for(int i=0; j<newLen; i++,j++)
4708       myLastCreatedElems[j] = aSeq.Value(i+1)->GetID();
4709   }
4710 }
4711
4712 //================================================================================
4713 /*!
4714  * Return data of mesh edition preview
4715  */
4716 //================================================================================
4717
4718 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
4719 {
4720   return myPreviewData._retn();
4721 }
4722
4723 //================================================================================
4724 /*!
4725  * \brief Returns list of it's IDs of created nodes
4726  * \retval SMESH::long_array* - list of node ID
4727  */
4728 //================================================================================
4729
4730 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
4731 {
4732   return myLastCreatedNodes._retn();
4733 }
4734
4735 //================================================================================
4736 /*!
4737  * \brief Returns list of it's IDs of created elements
4738  * \retval SMESH::long_array* - list of elements' ID
4739  */
4740 //================================================================================
4741
4742 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
4743 {
4744   return myLastCreatedElems._retn();
4745 }
4746
4747 //=======================================================================
4748 //function : ConvertToQuadratic
4749 //purpose  :
4750 //=======================================================================
4751
4752 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
4753 {
4754   ::SMESH_MeshEditor anEditor( myMesh );
4755   anEditor.ConvertToQuadratic(theForce3d);
4756   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
4757   myMesh->GetMeshDS()->Modified();
4758   myMesh->SetIsModified( true );
4759 }
4760
4761 //=======================================================================
4762 //function : ConvertFromQuadratic
4763 //purpose  :
4764 //=======================================================================
4765
4766 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
4767 {
4768   ::SMESH_MeshEditor anEditor( myMesh );
4769   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
4770   TPythonDump() << this << ".ConvertFromQuadratic()";
4771   myMesh->GetMeshDS()->Modified();
4772   if ( isDone )
4773     myMesh->SetIsModified( true );
4774   return isDone;
4775 }
4776
4777 //=======================================================================
4778 //function : makeMesh
4779 //purpose  : create a named imported mesh
4780 //=======================================================================
4781
4782 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
4783 {
4784   SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
4785   SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
4786   SALOMEDS::Study_var study = gen->GetCurrentStudy();
4787   SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
4788   gen->SetName( meshSO, theMeshName, "Mesh" );
4789   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
4790
4791   return mesh._retn();
4792 }
4793
4794 //=======================================================================
4795 //function : DumpGroupsList
4796 //purpose  :
4797 //=======================================================================
4798 void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython,
4799                                         const SMESH::ListOfGroups * theGroupList)
4800 {
4801   bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
4802   if(isDumpGroupList) {
4803     theDumpPython << theGroupList << " = ";
4804   }
4805 }
4806
4807 //================================================================================
4808 /*!
4809   \brief Generates the unique group name.
4810   \param thePrefix name prefix
4811   \return unique name
4812 */
4813 //================================================================================
4814 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
4815 {
4816   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
4817   set<string> groupNames;
4818
4819   // Get existing group names
4820   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
4821     SMESH::SMESH_GroupBase_var aGroup = groups[i];
4822     if (CORBA::is_nil(aGroup))
4823       continue;
4824
4825     groupNames.insert(aGroup->GetName());
4826   }
4827
4828   // Find new name
4829   string name = thePrefix;
4830   int index = 0;
4831
4832   while (!groupNames.insert(name).second) {
4833     if (index == 0) {
4834       name += "_1";
4835     }
4836     else {
4837       TCollection_AsciiString nbStr(index+1);
4838       name.resize( name.rfind('_')+1 );
4839       name += nbStr.ToCString();
4840     }
4841     ++index;
4842   }
4843
4844   return name;
4845 }
4846
4847 //================================================================================
4848 /*!
4849   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4850   \param theNodes - identifiers of nodes to be doubled
4851   \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
4852          nodes. If list of element identifiers is empty then nodes are doubled but
4853          they not assigned to elements
4854   \return TRUE if operation has been completed successfully, FALSE otherwise
4855   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
4856 */
4857 //================================================================================
4858
4859 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
4860                                                 const SMESH::long_array& theModifiedElems )
4861 {
4862   initData();
4863
4864   ::SMESH_MeshEditor aMeshEditor( myMesh );
4865   list< int > aListOfNodes;
4866   int i, n;
4867   for ( i = 0, n = theNodes.length(); i < n; i++ )
4868     aListOfNodes.push_back( theNodes[ i ] );
4869
4870   list< int > aListOfElems;
4871   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
4872     aListOfElems.push_back( theModifiedElems[ i ] );
4873
4874   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
4875
4876   myMesh->GetMeshDS()->Modified();
4877   storeResult( aMeshEditor) ;
4878   if ( aResult )
4879     myMesh->SetIsModified( true );
4880
4881   // Update Python script
4882   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
4883
4884   return aResult;
4885 }
4886
4887 //================================================================================
4888 /*!
4889   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4890   This method provided for convenience works as DoubleNodes() described above.
4891   \param theNodeId - identifier of node to be doubled.
4892   \param theModifiedElems - identifiers of elements to be updated.
4893   \return TRUE if operation has been completed successfully, FALSE otherwise
4894   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
4895 */
4896 //================================================================================
4897
4898 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
4899                                                const SMESH::long_array& theModifiedElems )
4900 {
4901   SMESH::long_array_var aNodes = new SMESH::long_array;
4902   aNodes->length( 1 );
4903   aNodes[ 0 ] = theNodeId;
4904
4905   TPythonDump pyDump; // suppress dump by the next line
4906
4907   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
4908
4909   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
4910
4911   return done;
4912 }
4913
4914 //================================================================================
4915 /*!
4916   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
4917   This method provided for convenience works as DoubleNodes() described above.
4918   \param theNodes - group of nodes to be doubled.
4919   \param theModifiedElems - group of elements to be updated.
4920   \return TRUE if operation has been completed successfully, FALSE otherwise
4921   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
4922 */
4923 //================================================================================
4924
4925 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
4926                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
4927 {
4928   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4929     return false;
4930
4931   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4932   SMESH::long_array_var aModifiedElems;
4933   if ( !CORBA::is_nil( theModifiedElems ) )
4934     aModifiedElems = theModifiedElems->GetListOfID();
4935   else
4936   {
4937     aModifiedElems = new SMESH::long_array;
4938     aModifiedElems->length( 0 );
4939   }
4940
4941   TPythonDump pyDump; // suppress dump by the next line
4942
4943   bool done = DoubleNodes( aNodes, aModifiedElems );
4944
4945   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
4946
4947   return done;
4948 }
4949
4950 /*!
4951  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
4952  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
4953  * \param theNodes - group of nodes to be doubled.
4954  * \param theModifiedElems - group of elements to be updated.
4955  * \return a new group with newly created nodes
4956  * \sa DoubleNodeGroup()
4957  */
4958 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
4959                                                                SMESH::SMESH_GroupBase_ptr theModifiedElems )
4960 {
4961   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
4962     return false;
4963
4964   SMESH::SMESH_Group_var aNewGroup;
4965
4966   // Duplicate nodes
4967   SMESH::long_array_var aNodes = theNodes->GetListOfID();
4968   SMESH::long_array_var aModifiedElems;
4969   if ( !CORBA::is_nil( theModifiedElems ) )
4970     aModifiedElems = theModifiedElems->GetListOfID();
4971   else {
4972     aModifiedElems = new SMESH::long_array;
4973     aModifiedElems->length( 0 );
4974   }
4975
4976   TPythonDump pyDump; // suppress dump by the next line
4977
4978   bool aResult = DoubleNodes( aNodes, aModifiedElems );
4979
4980   if ( aResult )
4981   {
4982     // Create group with newly created nodes
4983     SMESH::long_array_var anIds = GetLastCreatedNodes();
4984     if (anIds->length() > 0) {
4985       string anUnindexedName (theNodes->GetName());
4986       string aNewName = generateGroupName(anUnindexedName + "_double");
4987       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
4988       aNewGroup->Add(anIds);
4989     }
4990   }
4991
4992   pyDump << "createdNodes = " << this << ".DoubleNodeGroupNew( " << theNodes << ", "
4993     << theModifiedElems << " )";
4994
4995   return aNewGroup._retn();
4996 }
4997
4998 //================================================================================
4999 /*!
5000   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5001   This method provided for convenience works as DoubleNodes() described above.
5002   \param theNodes - list of groups of nodes to be doubled
5003   \param theModifiedElems - list of groups of elements to be updated.
5004   \return TRUE if operation has been completed successfully, FALSE otherwise
5005   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
5006 */
5007 //================================================================================
5008
5009 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
5010                                                     const SMESH::ListOfGroups& theModifiedElems )
5011 {
5012   initData();
5013
5014   ::SMESH_MeshEditor aMeshEditor( myMesh );
5015
5016   std::list< int > aNodes;
5017   int i, n, j, m;
5018   for ( i = 0, n = theNodes.length(); i < n; i++ )
5019   {
5020     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
5021     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
5022     {
5023       SMESH::long_array_var aCurr = aGrp->GetListOfID();
5024       for ( j = 0, m = aCurr->length(); j < m; j++ )
5025         aNodes.push_back( aCurr[ j ] );
5026     }
5027   }
5028
5029   std::list< int > anElems;
5030   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5031   {
5032     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ 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         anElems.push_back( aCurr[ j ] );
5038     }
5039   }
5040
5041   bool aResult = aMeshEditor.DoubleNodes( aNodes, anElems );
5042
5043   storeResult( aMeshEditor) ;
5044
5045   myMesh->GetMeshDS()->Modified();
5046   if ( aResult )
5047     myMesh->SetIsModified( true );
5048
5049
5050   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
5051
5052   return aResult;
5053 }
5054
5055 //================================================================================
5056 /*!
5057  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
5058  * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
5059  * \param theNodes - group of nodes to be doubled.
5060  * \param theModifiedElems - group of elements to be updated.
5061  * \return a new group with newly created nodes
5062  * \sa DoubleNodeGroups()
5063  */
5064 //================================================================================
5065
5066 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
5067                                                                 const SMESH::ListOfGroups& theModifiedElems )
5068 {
5069   SMESH::SMESH_Group_var aNewGroup;
5070
5071   TPythonDump pyDump; // suppress dump by the next line
5072
5073   bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
5074
5075   if ( aResult )
5076   {
5077     // Create group with newly created nodes
5078     SMESH::long_array_var anIds = GetLastCreatedNodes();
5079     if (anIds->length() > 0) {
5080       string anUnindexedName (theNodes[0]->GetName());
5081       string aNewName = generateGroupName(anUnindexedName + "_double");
5082       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
5083       aNewGroup->Add(anIds);
5084     }
5085   }
5086
5087   pyDump << "createdNodes = " << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
5088     << theModifiedElems << " )";
5089
5090   return aNewGroup._retn();
5091 }
5092
5093
5094 //================================================================================
5095 /*!
5096   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5097   \param theElems - the list of elements (edges or faces) to be replicated
5098   The nodes for duplication could be found from these elements
5099   \param theNodesNot - list of nodes to NOT replicate
5100   \param theAffectedElems - the list of elements (cells and edges) to which the
5101   replicated nodes should be associated to.
5102   \return TRUE if operation has been completed successfully, FALSE otherwise
5103   \sa DoubleNodeGroup(), DoubleNodeGroups()
5104 */
5105 //================================================================================
5106
5107 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
5108                                                    const SMESH::long_array& theNodesNot,
5109                                                    const SMESH::long_array& theAffectedElems )
5110
5111 {
5112   initData();
5113
5114   ::SMESH_MeshEditor aMeshEditor( myMesh );
5115
5116   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5117   TIDSortedElemSet anElems, aNodes, anAffected;
5118   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5119   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5120   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
5121
5122   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5123
5124   storeResult( aMeshEditor) ;
5125
5126   myMesh->GetMeshDS()->Modified();
5127   if ( aResult )
5128     myMesh->SetIsModified( true );
5129
5130   // Update Python script
5131   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
5132                 << theNodesNot << ", " << theAffectedElems << " )";
5133   return aResult;
5134 }
5135
5136 //================================================================================
5137 /*!
5138   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5139   \param theElems - the list of elements (edges or faces) to be replicated
5140   The nodes for duplication could be found from these elements
5141   \param theNodesNot - list of nodes to NOT replicate
5142   \param theShape - shape to detect affected elements (element which geometric center
5143   located on or inside shape).
5144   The replicated nodes should be associated to affected elements.
5145   \return TRUE if operation has been completed successfully, FALSE otherwise
5146   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
5147 */
5148 //================================================================================
5149
5150 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
5151                                                             const SMESH::long_array& theNodesNot,
5152                                                             GEOM::GEOM_Object_ptr    theShape )
5153
5154 {
5155   initData();
5156
5157   ::SMESH_MeshEditor aMeshEditor( myMesh );
5158
5159   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5160   TIDSortedElemSet anElems, aNodes;
5161   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
5162   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
5163
5164   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5165   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5166
5167   storeResult( aMeshEditor) ;
5168
5169   myMesh->GetMeshDS()->Modified();
5170   if ( aResult )
5171     myMesh->SetIsModified( true );
5172
5173   // Update Python script
5174   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
5175                 << theNodesNot << ", " << theShape << " )";
5176   return aResult;
5177 }
5178
5179 //================================================================================
5180 /*!
5181   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5182   \param theElems - group of of elements (edges or faces) to be replicated
5183   \param theNodesNot - group of nodes not to replicated
5184   \param theAffectedElems - group of elements to which the replicated nodes
5185   should be associated to.
5186   \return TRUE if operation has been completed successfully, FALSE otherwise
5187   \sa DoubleNodes(), DoubleNodeGroups()
5188 */
5189 //================================================================================
5190
5191 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
5192                                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
5193                                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
5194 {
5195   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5196     return false;
5197
5198   initData();
5199
5200   ::SMESH_MeshEditor aMeshEditor( myMesh );
5201
5202   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5203   TIDSortedElemSet anElems, aNodes, anAffected;
5204   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5205   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5206   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5207
5208   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5209
5210   storeResult( aMeshEditor) ;
5211
5212   myMesh->GetMeshDS()->Modified();
5213   if ( aResult )
5214     myMesh->SetIsModified( true );
5215
5216   // Update Python script
5217   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
5218                 << theNodesNot << ", " << theAffectedElems << " )";
5219   return aResult;
5220 }
5221
5222 /*!
5223  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5224  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
5225  * \param theElems - group of of elements (edges or faces) to be replicated
5226  * \param theNodesNot - group of nodes not to replicated
5227  * \param theAffectedElems - group of elements to which the replicated nodes
5228  *        should be associated to.
5229  * \return a new group with newly created elements
5230  * \sa DoubleNodeElemGroup()
5231  */
5232 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
5233                                                                   SMESH::SMESH_GroupBase_ptr theNodesNot,
5234                                                                   SMESH::SMESH_GroupBase_ptr theAffectedElems)
5235 {
5236   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5237     return false;
5238
5239   SMESH::SMESH_Group_var aNewGroup;
5240
5241   initData();
5242
5243   ::SMESH_MeshEditor aMeshEditor( myMesh );
5244
5245   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5246   TIDSortedElemSet anElems, aNodes, anAffected;
5247   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5248   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5249   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
5250
5251
5252   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5253
5254   storeResult( aMeshEditor) ;
5255
5256   if ( aResult ) {
5257     myMesh->SetIsModified( true );
5258
5259     // Create group with newly created elements
5260     SMESH::long_array_var anIds = GetLastCreatedElems();
5261     if (anIds->length() > 0) {
5262       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5263       string anUnindexedName (theElems->GetName());
5264       string aNewName = generateGroupName(anUnindexedName + "_double");
5265       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5266       aNewGroup->Add(anIds);
5267     }
5268   }
5269
5270   // Update Python script
5271   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupNew( " << theElems << ", "
5272     << theNodesNot << ", " << theAffectedElems << " )";
5273   return aNewGroup._retn();
5274 }
5275
5276 //================================================================================
5277 /*!
5278   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5279   \param theElems - group of of elements (edges or faces) to be replicated
5280   \param theNodesNot - group of nodes not to replicated
5281   \param theShape - shape to detect affected elements (element which geometric center
5282   located on or inside shape).
5283   The replicated nodes should be associated to affected elements.
5284   \return TRUE if operation has been completed successfully, FALSE otherwise
5285   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
5286 */
5287 //================================================================================
5288
5289 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
5290                                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
5291                                                                GEOM::GEOM_Object_ptr      theShape )
5292
5293 {
5294   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
5295     return false;
5296
5297   initData();
5298
5299   ::SMESH_MeshEditor aMeshEditor( myMesh );
5300
5301   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5302   TIDSortedElemSet anElems, aNodes, anAffected;
5303   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
5304   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
5305
5306   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5307   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5308
5309   storeResult( aMeshEditor) ;
5310
5311   myMesh->GetMeshDS()->Modified();
5312   if ( aResult )
5313     myMesh->SetIsModified( true );
5314
5315   // Update Python script
5316   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
5317                 << theNodesNot << ", " << theShape << " )";
5318   return aResult;
5319 }
5320
5321 //================================================================================
5322 /*!
5323   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5324   This method provided for convenience works as DoubleNodes() described above.
5325   \param theElems - list of groups of elements (edges or faces) to be replicated
5326   \param theNodesNot - list of groups of nodes not to replicated
5327   \param theAffectedElems - group of elements to which the replicated nodes
5328   should be associated to.
5329   \return TRUE if operation has been completed successfully, FALSE otherwise
5330   \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
5331 */
5332 //================================================================================
5333
5334 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
5335                              SMESHDS_Mesh*              theMeshDS,
5336                              TIDSortedElemSet&          theElemSet,
5337                              const bool                 theIsNodeGrp)
5338 {
5339   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
5340   {
5341     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
5342     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
5343                                     : aGrp->GetType() != SMESH::NODE ) )
5344     {
5345       SMESH::long_array_var anIDs = aGrp->GetIDs();
5346       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
5347     }
5348   }
5349 }
5350
5351 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
5352                                                         const SMESH::ListOfGroups& theNodesNot,
5353                                                         const SMESH::ListOfGroups& theAffectedElems)
5354 {
5355   initData();
5356
5357   ::SMESH_MeshEditor aMeshEditor( myMesh );
5358
5359   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5360   TIDSortedElemSet anElems, aNodes, anAffected;
5361   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5362   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5363   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5364
5365   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5366
5367   storeResult( aMeshEditor) ;
5368
5369   myMesh->GetMeshDS()->Modified();
5370   if ( aResult )
5371     myMesh->SetIsModified( true );
5372
5373   // Update Python script
5374   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
5375                 << &theNodesNot << ", " << &theAffectedElems << " )";
5376   return aResult;
5377 }
5378
5379 //================================================================================
5380 /*!
5381  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5382  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
5383   \param theElems - list of groups of elements (edges or faces) to be replicated
5384   \param theNodesNot - list of groups of nodes not to replicated
5385   \param theAffectedElems - group of elements to which the replicated nodes
5386   should be associated to.
5387  * \return a new group with newly created elements
5388  * \sa DoubleNodeElemGroups()
5389  */
5390 //================================================================================
5391
5392 SMESH::SMESH_Group_ptr SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
5393                                                                    const SMESH::ListOfGroups& theNodesNot,
5394                                                                    const SMESH::ListOfGroups& theAffectedElems)
5395 {
5396   SMESH::SMESH_Group_var aNewGroup;
5397   
5398   initData();
5399
5400   ::SMESH_MeshEditor aMeshEditor( myMesh );
5401
5402   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5403   TIDSortedElemSet anElems, aNodes, anAffected;
5404   listOfGroupToSet(theElems, aMeshDS, anElems, false );
5405   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5406   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
5407
5408   bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
5409
5410   storeResult( aMeshEditor) ;
5411
5412   myMesh->GetMeshDS()->Modified();
5413   if ( aResult ) {
5414     myMesh->SetIsModified( true );
5415
5416     // Create group with newly created elements
5417     SMESH::long_array_var anIds = GetLastCreatedElems();
5418     if (anIds->length() > 0) {
5419       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
5420       string anUnindexedName (theElems[0]->GetName());
5421       string aNewName = generateGroupName(anUnindexedName + "_double");
5422       aNewGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
5423       aNewGroup->Add(anIds);
5424     }
5425   }
5426
5427   // Update Python script
5428   TPythonDump() << "createdElems = " << this << ".DoubleNodeElemGroupsNew( " << &theElems << ", "
5429                 << &theNodesNot << ", " << &theAffectedElems << " )";
5430   return aNewGroup._retn();
5431 }
5432
5433 //================================================================================
5434 /*!
5435   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5436   This method provided for convenience works as DoubleNodes() described above.
5437   \param theElems - list of groups of elements (edges or faces) to be replicated
5438   \param theNodesNot - list of groups of nodes not to replicated
5439   \param theShape - shape to detect affected elements (element which geometric center
5440   located on or inside shape).
5441   The replicated nodes should be associated to affected elements.
5442   \return TRUE if operation has been completed successfully, FALSE otherwise
5443   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
5444 */
5445 //================================================================================
5446
5447 CORBA::Boolean
5448 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
5449                                                  const SMESH::ListOfGroups& theNodesNot,
5450                                                  GEOM::GEOM_Object_ptr      theShape )
5451 {
5452   initData();
5453
5454   ::SMESH_MeshEditor aMeshEditor( myMesh );
5455
5456   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5457   TIDSortedElemSet anElems, aNodes;
5458   listOfGroupToSet(theElems, aMeshDS, anElems,false );
5459   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
5460
5461   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
5462   bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
5463
5464   storeResult( aMeshEditor) ;
5465
5466   myMesh->GetMeshDS()->Modified();
5467   if ( aResult )
5468     myMesh->SetIsModified( true );
5469
5470   // Update Python script
5471   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
5472                 << &theNodesNot << ", " << theShape << " )";
5473   return aResult;
5474 }
5475
5476 //================================================================================
5477 /*!
5478   \brief Generated skin mesh (containing 2D cells) from 3D mesh
5479    The created 2D mesh elements based on nodes of free faces of boundary volumes
5480   \return TRUE if operation has been completed successfully, FALSE otherwise
5481 */
5482 //================================================================================
5483
5484 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
5485 {
5486   initData();
5487
5488   ::SMESH_MeshEditor aMeshEditor( myMesh );
5489   bool aResult = aMeshEditor.Make2DMeshFrom3D();
5490   storeResult( aMeshEditor) ;
5491   myMesh->GetMeshDS()->Modified();
5492   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
5493   return aResult;
5494 }
5495
5496 //================================================================================
5497 /*!
5498  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
5499  * The list of groups must describe a partition of the mesh volumes.
5500  * The nodes of the internal faces at the boundaries of the groups are doubled.
5501  * In option, the internal faces are replaced by flat elements.
5502  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
5503  * @param theDomains - list of groups of volumes
5504  * @param createJointElems - if TRUE, create the elements
5505  * @return TRUE if operation has been completed successfully, FALSE otherwise
5506  */
5507 //================================================================================
5508
5509 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
5510                                                                  CORBA::Boolean createJointElems )
5511 {
5512   initData();
5513
5514   ::SMESH_MeshEditor aMeshEditor( myMesh );
5515
5516   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5517
5518   vector<TIDSortedElemSet> domains;
5519   domains.clear();
5520
5521   for ( int i = 0, n = theDomains.length(); i < n; i++ )
5522   {
5523     SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
5524     if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
5525     {
5526       TIDSortedElemSet domain;
5527       domain.clear();
5528       domains.push_back(domain);
5529       SMESH::long_array_var anIDs = aGrp->GetIDs();
5530       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
5531     }
5532   }
5533
5534   bool aResult = aMeshEditor.DoubleNodesOnGroupBoundaries( domains, createJointElems );
5535
5536   storeResult( aMeshEditor) ;
5537   myMesh->GetMeshDS()->Modified();
5538
5539   // Update Python script
5540   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
5541       << ", " << createJointElems << " )";
5542   return aResult;
5543 }
5544
5545 // issue 20749 ===================================================================
5546 /*!
5547  * \brief Creates missing boundary elements
5548  *  \param elements - elements whose boundary is to be checked
5549  *  \param dimension - defines type of boundary elements to create
5550  *  \param groupName - a name of group to store created boundary elements in,
5551  *                     "" means not to create the group
5552  *  \param meshName - a name of new mesh to store created boundary elements in,
5553  *                     "" means not to create the new mesh
5554  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
5555  *  \param toCopyExistingBondary - if true, not only new but also pre-existing
5556  *                                boundary elements will be copied into the new mesh
5557  *  \param group - returns the create group, if any
5558  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
5559  */
5560 // ================================================================================
5561
5562 SMESH::SMESH_Mesh_ptr
5563 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
5564                                      SMESH::Bnd_Dimension      dim,
5565                                      const char*               groupName,
5566                                      const char*               meshName,
5567                                      CORBA::Boolean            toCopyElements,
5568                                      CORBA::Boolean            toCopyExistingBondary,
5569                                      SMESH::SMESH_Group_out    group)
5570 {
5571   initData();
5572
5573   if ( dim > SMESH::BND_1DFROM2D )
5574     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
5575
5576   SMESHDS_Mesh* aMeshDS = GetMeshDS();
5577
5578   SMESH::SMESH_Mesh_var mesh_var;
5579   SMESH::SMESH_Group_var group_var;
5580
5581   TPythonDump pyDump;
5582
5583   TIDSortedElemSet elements;
5584   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
5585   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
5586   {
5587     // mesh to fill in
5588     mesh_var =
5589       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
5590     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
5591     // other mesh
5592     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
5593
5594     // group of new boundary elements
5595     SMESH_Group* smesh_group = 0;
5596     if ( strlen(groupName) )
5597     {
5598       group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
5599       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
5600         smesh_group = group_i->GetSmeshGroup();
5601     }
5602
5603     // do it
5604     ::SMESH_MeshEditor aMeshEditor( myMesh );
5605     aMeshEditor.MakeBoundaryMesh( elements,
5606                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
5607                                   smesh_group,
5608                                   smesh_mesh,
5609                                   toCopyElements,
5610                                   toCopyExistingBondary);
5611     storeResult( aMeshEditor );
5612
5613     if ( smesh_mesh )
5614       smesh_mesh->GetMeshDS()->Modified();
5615   }
5616
5617   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
5618
5619   // result of MakeBoundaryMesh() is a tuple (mesh, group)
5620   if ( mesh_var->_is_nil() )
5621     pyDump << myMesh_i->_this() << ", ";
5622   else
5623     pyDump << mesh_var << ", ";
5624   if ( group_var->_is_nil() )
5625     pyDump << "_NoneGroup = "; // assignment to None is forbiden
5626   else
5627     pyDump << group_var << " = ";
5628   pyDump << this << ".MakeBoundaryMesh( "
5629          << idSource << ", "
5630          << "SMESH." << dimName[int(dim)] << ", "
5631          << "'" << groupName << "', "
5632          << "'" << meshName<< "', "
5633          << toCopyElements << ", "
5634          << toCopyExistingBondary << ")";
5635
5636   group = group_var._retn();
5637   return mesh_var._retn();
5638 }
5639
5640 //================================================================================
5641 /*!
5642  * \brief Creates missing boundary elements
5643  *  \param dimension - defines type of boundary elements to create
5644  *  \param groupName - a name of group to store all boundary elements in,
5645  *    "" means not to create the group
5646  *  \param meshName - a name of a new mesh, which is a copy of the initial 
5647  *    mesh + created boundary elements; "" means not to create the new mesh
5648  *  \param toCopyAll - if true, the whole initial mesh will be copied into
5649  *    the new mesh else only boundary elements will be copied into the new mesh
5650  *  \param groups - optional groups of elements to make boundary around
5651  *  \param mesh - returns the mesh where elements were added to
5652  *  \param group - returns the created group, if any
5653  *  \retval long - number of added boundary elements
5654  */
5655 //================================================================================
5656
5657 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
5658                                                      const char* groupName,
5659                                                      const char* meshName,
5660                                                      CORBA::Boolean toCopyAll,
5661                                                      const SMESH::ListOfIDSources& groups,
5662                                                      SMESH::SMESH_Mesh_out mesh,
5663                                                      SMESH::SMESH_Group_out group)
5664   throw (SALOME::SALOME_Exception)
5665 {
5666   Unexpect aCatch(SALOME_SalomeException);
5667
5668   initData();
5669
5670   if ( dim > SMESH::BND_1DFROM2D )
5671     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
5672
5673   // check that groups belongs to to this mesh and is not this mesh
5674   const int nbGroups = groups.length();
5675   for ( int i = 0; i < nbGroups; ++i )
5676   {
5677     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
5678     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
5679       THROW_SALOME_CORBA_EXCEPTION("group does not belong to this mesh", SALOME::BAD_PARAM);
5680     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
5681       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
5682   }
5683
5684   TPythonDump pyDump;
5685
5686   int nbAdded = 0;
5687   SMESH::SMESH_Mesh_var mesh_var;
5688   SMESH::SMESH_Group_var group_var;
5689
5690   // get mesh to fill
5691   mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
5692   const bool toCopyMesh = ( strlen( meshName ) > 0 );
5693   if ( toCopyMesh )
5694   {
5695     if ( toCopyAll )
5696       mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
5697                                                       meshName,
5698                                                       /*toCopyGroups=*/false,
5699                                                       /*toKeepIDs=*/true);
5700     else
5701       mesh_var = makeMesh(meshName);
5702   }
5703   SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
5704   SMESH_Mesh*  tgtMesh = &mesh_i->GetImpl();
5705
5706   // source mesh
5707   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
5708   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
5709
5710   // group of boundary elements
5711   SMESH_Group* smesh_group = 0;
5712   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
5713   if ( strlen(groupName) )
5714   {
5715     SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
5716     group_var = mesh_i->CreateGroup( groupType, groupName );
5717     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
5718       smesh_group = group_i->GetSmeshGroup();
5719   }
5720
5721   TIDSortedElemSet elements;
5722
5723   if ( nbGroups > 0 )
5724   {
5725     for ( int i = 0; i < nbGroups; ++i )
5726     {
5727       elements.clear();
5728       if ( idSourceToSet( groups[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/false ))
5729       {
5730         SMESH::Bnd_Dimension bdim = 
5731           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
5732         ::SMESH_MeshEditor aMeshEditor( srcMesh );
5733         nbAdded += aMeshEditor.MakeBoundaryMesh( elements,
5734                                                  ::SMESH_MeshEditor::Bnd_Dimension(bdim),
5735                                                  smesh_group,
5736                                                  tgtMesh,
5737                                                  /*toCopyElements=*/false,
5738                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
5739                                                  /*toAddExistingBondary=*/true,
5740                                                  /*aroundElements=*/true);
5741         storeResult( aMeshEditor );
5742       }
5743     }
5744   }
5745   else
5746   {
5747     ::SMESH_MeshEditor aMeshEditor( srcMesh );
5748     nbAdded += aMeshEditor.MakeBoundaryMesh( elements,
5749                                              ::SMESH_MeshEditor::Bnd_Dimension(dim),
5750                                              smesh_group,
5751                                              tgtMesh,
5752                                              /*toCopyElements=*/false,
5753                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
5754                                              /*toAddExistingBondary=*/true);
5755     storeResult( aMeshEditor );
5756   }
5757   tgtMesh->GetMeshDS()->Modified();
5758
5759   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
5760
5761   // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
5762   pyDump << "nbAdded, ";
5763   if ( mesh_var->_is_nil() )
5764     pyDump << myMesh_i->_this() << ", ";
5765   else
5766     pyDump << mesh_var << ", ";
5767   if ( group_var->_is_nil() )
5768     pyDump << "_NoneGroup = "; // assignment to None is forbiden
5769   else
5770     pyDump << group_var << " = ";
5771   pyDump << this << ".MakeBoundaryElements( "
5772          << "SMESH." << dimName[int(dim)] << ", "
5773          << "'" << groupName << "', "
5774          << "'" << meshName<< "', "
5775          << toCopyAll << ", "
5776          << groups << ")";
5777
5778   mesh  = mesh_var._retn();
5779   group = group_var._retn();
5780   return nbAdded;
5781 }