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