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