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