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