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