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