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