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