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