Salome HOME
PPGP
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_MeshEditor_i.cxx
23 //  Author : Nicolas REJNERI
24 //  Module : SMESH
25
26 #ifdef 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     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 /*!
1715  * \brief Fuse neighbour triangles into quadrangles.
1716  */
1717 //=============================================================================
1718
1719 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
1720                                               SMESH::NumericalFunctor_ptr Criterion,
1721                                               CORBA::Double               MaxAngle)
1722   throw (SALOME::SALOME_Exception)
1723 {
1724   SMESH_TRY;
1725   initData();
1726
1727   SMESHDS_Mesh* aMesh = getMeshDS();
1728   TIDSortedElemSet faces,copyFaces;
1729   SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
1730   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
1731   TIDSortedElemSet* workElements = & faces;
1732
1733   if ( myIsPreviewMode ) {
1734     SMDSAbs_ElementType select =  SMDSAbs_Face;
1735     getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
1736     workElements = & copyFaces;
1737   }
1738
1739   SMESH::NumericalFunctor_i* aNumericalFunctor =
1740     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1741   SMESH::Controls::NumericalFunctorPtr aCrit;
1742   if ( !aNumericalFunctor )
1743     aCrit.reset( new SMESH::Controls::MaxElementLength2D() );
1744   else
1745     aCrit = aNumericalFunctor->GetNumericalFunctor();
1746
1747   if ( !myIsPreviewMode ) {
1748     // Update Python script
1749     TPythonDump() << "isDone = " << this << ".TriToQuad( "
1750                   << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1751   }
1752
1753   bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
1754
1755   declareMeshModified( /*isReComputeSafe=*/!stat );
1756   return stat;
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::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
1769                                                     SMESH::NumericalFunctor_ptr Criterion,
1770                                                     CORBA::Double               MaxAngle)
1771   throw (SALOME::SALOME_Exception)
1772 {
1773   SMESH_TRY;
1774   initData();
1775
1776   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
1777
1778   prepareIdSource( theObject );
1779   SMESH::long_array_var anElementsId = theObject->GetIDs();
1780   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
1781
1782   if ( !myIsPreviewMode ) {
1783     SMESH::NumericalFunctor_i* aNumericalFunctor =
1784       SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1785
1786     // Update Python script
1787     aTPythonDump << "isDone = " << this << ".TriToQuadObject("
1788                  << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
1789   }
1790
1791   return isDone;
1792
1793   SMESH_CATCH( SMESH::throwCorbaException );
1794   return 0;
1795 }
1796
1797 //=============================================================================
1798 /*!
1799  * \brief Split quadrangles into triangles.
1800  */
1801 //=============================================================================
1802
1803 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
1804                                               SMESH::NumericalFunctor_ptr Criterion)
1805   throw (SALOME::SALOME_Exception)
1806 {
1807   SMESH_TRY;
1808   initData();
1809
1810   SMESHDS_Mesh* aMesh = getMeshDS();
1811   TIDSortedElemSet faces;
1812   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1813
1814   SMESH::NumericalFunctor_i* aNumericalFunctor =
1815     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
1816   SMESH::Controls::NumericalFunctorPtr aCrit;
1817   if ( !aNumericalFunctor )
1818     aCrit.reset( new SMESH::Controls::AspectRatio() );
1819   else
1820     aCrit = aNumericalFunctor->GetNumericalFunctor();
1821
1822
1823   // Update Python script
1824   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
1825
1826   CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
1827
1828   declareMeshModified( /*isReComputeSafe=*/false );
1829   return stat;
1830
1831   SMESH_CATCH( SMESH::throwCorbaException );
1832   return 0;
1833 }
1834
1835 //=============================================================================
1836 /*!
1837  * \brief Split quadrangles into triangles.
1838  */
1839 //=============================================================================
1840
1841 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
1842                                                     SMESH::NumericalFunctor_ptr Criterion)
1843   throw (SALOME::SALOME_Exception)
1844 {
1845   SMESH_TRY;
1846   initData();
1847
1848   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
1849
1850   prepareIdSource( theObject );
1851   SMESH::long_array_var anElementsId = theObject->GetIDs();
1852   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
1853
1854   SMESH::NumericalFunctor_i* aNumericalFunctor =
1855     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
1856
1857   // Update Python script
1858   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
1859
1860   declareMeshModified( /*isReComputeSafe=*/false );
1861   return isDone;
1862
1863   SMESH_CATCH( SMESH::throwCorbaException );
1864   return 0;
1865 }
1866
1867 //================================================================================
1868 /*!
1869  * \brief Split each of quadrangles into 4 triangles.
1870  *  \param [in] theObject - theQuads Container of quadrangles to split.
1871  */
1872 //================================================================================
1873
1874 void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
1875   throw (SALOME::SALOME_Exception)
1876 {
1877   SMESH_TRY;
1878   initData();
1879
1880   TIDSortedElemSet faces;
1881   prepareIdSource( theObject );
1882   if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
1883        faces.empty() )
1884     THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
1885
1886   getEditor().QuadTo4Tri( faces );
1887   TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
1888
1889   SMESH_CATCH( SMESH::throwCorbaException );
1890 }
1891
1892 //=============================================================================
1893 /*!
1894  * \brief Split quadrangles into triangles.
1895  */
1896 //=============================================================================
1897
1898 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
1899                                               CORBA::Boolean            Diag13)
1900   throw (SALOME::SALOME_Exception)
1901 {
1902   SMESH_TRY;
1903   initData();
1904
1905   SMESHDS_Mesh* aMesh = getMeshDS();
1906   TIDSortedElemSet faces;
1907   arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
1908
1909   // Update Python script
1910   TPythonDump() << "isDone = " << this << ".SplitQuad( "
1911                 << IDsOfElements << ", " << Diag13 << " )";
1912
1913   CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
1914
1915   declareMeshModified( /*isReComputeSafe=*/ !stat );
1916   return stat;
1917
1918   SMESH_CATCH( SMESH::throwCorbaException );
1919   return 0;
1920 }
1921
1922 //=============================================================================
1923 /*!
1924  * \brief Split quadrangles into triangles.
1925  */
1926 //=============================================================================
1927
1928 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
1929                                                     CORBA::Boolean            Diag13)
1930   throw (SALOME::SALOME_Exception)
1931 {
1932   SMESH_TRY;
1933   initData();
1934
1935   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
1936
1937   prepareIdSource( theObject );
1938   SMESH::long_array_var anElementsId = theObject->GetIDs();
1939   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
1940
1941   // Update Python script
1942   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
1943                << theObject << ", " << Diag13 << " )";
1944
1945   declareMeshModified( /*isReComputeSafe=*/!isDone );
1946   return isDone;
1947
1948   SMESH_CATCH( SMESH::throwCorbaException );
1949   return 0;
1950 }
1951
1952
1953 //=============================================================================
1954 /*!
1955  * Find better splitting of the given quadrangle.
1956  *  \param IDOfQuad  ID of the quadrangle to be splitted.
1957  *  \param Criterion A criterion to choose a diagonal for splitting.
1958  *  \return 1 if 1-3 diagonal is better, 2 if 2-4
1959  *          diagonal is better, 0 if error occurs.
1960  */
1961 //=============================================================================
1962
1963 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
1964                                            SMESH::NumericalFunctor_ptr Criterion)
1965   throw (SALOME::SALOME_Exception)
1966 {
1967   SMESH_TRY;
1968   initData();
1969
1970   const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
1971   if (quad && quad->GetType() == SMDSAbs_Face && quad->NbNodes() == 4)
1972   {
1973     SMESH::NumericalFunctor_i* aNumericalFunctor =
1974       dynamic_cast<SMESH::NumericalFunctor_i*>(SMESH_Gen_i::GetServant(Criterion).in());
1975     SMESH::Controls::NumericalFunctorPtr aCrit;
1976     if (aNumericalFunctor)
1977       aCrit = aNumericalFunctor->GetNumericalFunctor();
1978     else
1979       aCrit.reset(new SMESH::Controls::AspectRatio());
1980
1981     int id = getEditor().BestSplit(quad, aCrit);
1982     declareMeshModified( /*isReComputeSafe=*/ id < 1 );
1983     return id;
1984   }
1985
1986   SMESH_CATCH( SMESH::throwCorbaException );
1987   return 0;
1988 }
1989
1990 //================================================================================
1991 /*!
1992  * \brief Split volumic elements into tetrahedrons
1993  */
1994 //================================================================================
1995
1996 void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
1997                                                 CORBA::Short              methodFlags)
1998   throw (SALOME::SALOME_Exception)
1999 {
2000   SMESH_TRY;
2001   initData();
2002
2003   prepareIdSource( elems );
2004   SMESH::long_array_var anElementsId = elems->GetIDs();
2005   TIDSortedElemSet elemSet;
2006   arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume );
2007
2008   getEditor().SplitVolumesIntoTetra( elemSet, int( methodFlags ));
2009   declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
2010
2011   TPythonDump() << this << ".SplitVolumesIntoTetra( "
2012                 << elems << ", " << methodFlags << " )";
2013
2014   SMESH_CATCH( SMESH::throwCorbaException );
2015 }
2016
2017 //=======================================================================
2018 //function : Smooth
2019 //purpose  :
2020 //=======================================================================
2021
2022 CORBA::Boolean
2023 SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
2024                            const SMESH::long_array &              IDsOfFixedNodes,
2025                            CORBA::Long                            MaxNbOfIterations,
2026                            CORBA::Double                          MaxAspectRatio,
2027                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
2028   throw (SALOME::SALOME_Exception)
2029 {
2030   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2031                  MaxAspectRatio, Method, false );
2032 }
2033
2034
2035 //=======================================================================
2036 //function : SmoothParametric
2037 //purpose  :
2038 //=======================================================================
2039
2040 CORBA::Boolean
2041 SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
2042                                      const SMESH::long_array &              IDsOfFixedNodes,
2043                                      CORBA::Long                            MaxNbOfIterations,
2044                                      CORBA::Double                          MaxAspectRatio,
2045                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
2046   throw (SALOME::SALOME_Exception)
2047 {
2048   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
2049                  MaxAspectRatio, Method, true );
2050 }
2051
2052
2053 //=======================================================================
2054 //function : SmoothObject
2055 //purpose  :
2056 //=======================================================================
2057
2058 CORBA::Boolean
2059 SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
2060                                  const SMESH::long_array &              IDsOfFixedNodes,
2061                                  CORBA::Long                            MaxNbOfIterations,
2062                                  CORBA::Double                          MaxAspectRatio,
2063                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
2064   throw (SALOME::SALOME_Exception)
2065 {
2066   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2067                        MaxAspectRatio, Method, false);
2068 }
2069
2070
2071 //=======================================================================
2072 //function : SmoothParametricObject
2073 //purpose  :
2074 //=======================================================================
2075
2076 CORBA::Boolean
2077 SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
2078                                            const SMESH::long_array &              IDsOfFixedNodes,
2079                                            CORBA::Long                            MaxNbOfIterations,
2080                                            CORBA::Double                          MaxAspectRatio,
2081                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
2082   throw (SALOME::SALOME_Exception)
2083 {
2084   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
2085                        MaxAspectRatio, Method, true);
2086 }
2087
2088
2089 //=============================================================================
2090 /*!
2091  *
2092  */
2093 //=============================================================================
2094
2095 CORBA::Boolean
2096 SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
2097                            const SMESH::long_array &              IDsOfFixedNodes,
2098                            CORBA::Long                            MaxNbOfIterations,
2099                            CORBA::Double                          MaxAspectRatio,
2100                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
2101                            bool                                   IsParametric)
2102   throw (SALOME::SALOME_Exception)
2103 {
2104   SMESH_TRY;
2105   initData();
2106
2107   SMESHDS_Mesh* aMesh = getMeshDS();
2108
2109   TIDSortedElemSet elements;
2110   arrayToSet(IDsOfElements, aMesh, elements, SMDSAbs_Face);
2111
2112   set<const SMDS_MeshNode*> fixedNodes;
2113   for (int i = 0; i < IDsOfFixedNodes.length(); i++) {
2114     CORBA::Long index = IDsOfFixedNodes[i];
2115     const SMDS_MeshNode * node = aMesh->FindNode(index);
2116     if ( node )
2117       fixedNodes.insert( node );
2118   }
2119   ::SMESH_MeshEditor::SmoothMethod method = ::SMESH_MeshEditor::LAPLACIAN;
2120   if ( Method != SMESH::SMESH_MeshEditor::LAPLACIAN_SMOOTH )
2121     method = ::SMESH_MeshEditor::CENTROIDAL;
2122
2123   getEditor().Smooth(elements, fixedNodes, method,
2124                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
2125
2126   declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
2127
2128   // Update Python script
2129   TPythonDump() << "isDone = " << this << "."
2130                 << (IsParametric ? "SmoothParametric( " : "Smooth( ")
2131                 << IDsOfElements << ", "     << IDsOfFixedNodes << ", "
2132                 << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2133                 << "SMESH.SMESH_MeshEditor."
2134                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2135                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2136
2137   return true;
2138
2139   SMESH_CATCH( SMESH::throwCorbaException );
2140   return 0;
2141 }
2142
2143 //=============================================================================
2144 /*!
2145  *
2146  */
2147 //=============================================================================
2148
2149 CORBA::Boolean
2150 SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObject,
2151                                  const SMESH::long_array &              IDsOfFixedNodes,
2152                                  CORBA::Long                            MaxNbOfIterations,
2153                                  CORBA::Double                          MaxAspectRatio,
2154                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
2155                                  bool                                   IsParametric)
2156   throw (SALOME::SALOME_Exception)
2157 {
2158   SMESH_TRY;
2159   initData();
2160
2161   TPythonDump aTPythonDump;  // suppress dump in smooth()
2162
2163   prepareIdSource( theObject );
2164   SMESH::long_array_var anElementsId = theObject->GetIDs();
2165   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
2166                                   MaxAspectRatio, Method, IsParametric);
2167
2168   // Update Python script
2169   aTPythonDump << "isDone = " << this << "."
2170                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
2171                << theObject << ", " << IDsOfFixedNodes << ", "
2172                << TVar( MaxNbOfIterations ) << ", " << TVar( MaxAspectRatio ) << ", "
2173                << "SMESH.SMESH_MeshEditor."
2174                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
2175                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
2176
2177   return isDone;
2178
2179   SMESH_CATCH( SMESH::throwCorbaException );
2180   return 0;
2181 }
2182
2183 //=============================================================================
2184 /*!
2185  *
2186  */
2187 //=============================================================================
2188
2189 void SMESH_MeshEditor_i::RenumberNodes()
2190   throw (SALOME::SALOME_Exception)
2191 {
2192   SMESH_TRY;
2193   // Update Python script
2194   TPythonDump() << this << ".RenumberNodes()";
2195
2196   getMeshDS()->Renumber( true );
2197
2198   SMESH_CATCH( SMESH::throwCorbaException );
2199 }
2200
2201 //=============================================================================
2202 /*!
2203  *
2204  */
2205 //=============================================================================
2206
2207 void SMESH_MeshEditor_i::RenumberElements()
2208   throw (SALOME::SALOME_Exception)
2209 {
2210   SMESH_TRY;
2211   // Update Python script
2212   TPythonDump() << this << ".RenumberElements()";
2213
2214   getMeshDS()->Renumber( false );
2215
2216   SMESH_CATCH( SMESH::throwCorbaException );
2217 }
2218
2219 //=======================================================================
2220 /*!
2221  * \brief Return groups by their IDs
2222  */
2223 //=======================================================================
2224
2225 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
2226   throw (SALOME::SALOME_Exception)
2227 {
2228   SMESH_TRY;
2229   if ( !groupIDs )
2230     return 0;
2231   myMesh_i->CreateGroupServants();
2232   return myMesh_i->GetGroups( *groupIDs );
2233
2234   SMESH_CATCH( SMESH::throwCorbaException );
2235   return 0;
2236 }
2237
2238 //=======================================================================
2239 //function : rotationSweep
2240 //purpose  :
2241 //=======================================================================
2242
2243 SMESH::ListOfGroups*
2244 SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
2245                                   const SMESH::AxisStruct & theAxis,
2246                                   CORBA::Double             theAngleInRadians,
2247                                   CORBA::Long               theNbOfSteps,
2248                                   CORBA::Double             theTolerance,
2249                                   const bool                theMakeGroups,
2250                                   const SMDSAbs_ElementType theElementType)
2251   throw (SALOME::SALOME_Exception)
2252 {
2253   SMESH_TRY;
2254   initData();
2255
2256   TIDSortedElemSet inElements, copyElements;
2257   arrayToSet(theIDsOfElements, getMeshDS(), inElements, theElementType);
2258
2259   TIDSortedElemSet* workElements = & inElements;
2260   bool              makeWalls=true;
2261   if ( myIsPreviewMode )
2262   {
2263     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2264     getPreviewMesh( SMDSAbs_Face )->Copy( inElements, copyElements, select, avoid );
2265     workElements = & copyElements;
2266     //makeWalls = false;
2267   }
2268
2269   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
2270               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
2271
2272   ::SMESH_MeshEditor::PGroupIDs groupIds =
2273       getEditor().RotationSweep (*workElements, Ax1, theAngleInRadians,
2274                                  theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
2275
2276   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2277
2278   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2279
2280   SMESH_CATCH( SMESH::throwCorbaException );
2281   return 0;
2282 }
2283
2284 //=======================================================================
2285 //function : RotationSweep
2286 //purpose  :
2287 //=======================================================================
2288
2289 void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
2290                                        const SMESH::AxisStruct & theAxis,
2291                                        CORBA::Double             theAngleInRadians,
2292                                        CORBA::Long               theNbOfSteps,
2293                                        CORBA::Double             theTolerance)
2294   throw (SALOME::SALOME_Exception)
2295 {
2296   if ( !myIsPreviewMode ) {
2297     TPythonDump() << this << ".RotationSweep( "
2298                   << theIDsOfElements          << ", "
2299                   << theAxis                   << ", "
2300                   << TVar( theAngleInRadians ) << ", "
2301                   << TVar( theNbOfSteps      ) << ", "
2302                   << TVar( theTolerance      ) << " )";
2303   }
2304   rotationSweep(theIDsOfElements,
2305                 theAxis,
2306                 theAngleInRadians,
2307                 theNbOfSteps,
2308                 theTolerance,
2309                 false);
2310 }
2311
2312 //=======================================================================
2313 //function : RotationSweepMakeGroups
2314 //purpose  :
2315 //=======================================================================
2316
2317 SMESH::ListOfGroups*
2318 SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2319                                             const SMESH::AxisStruct& theAxis,
2320                                             CORBA::Double            theAngleInRadians,
2321                                             CORBA::Long              theNbOfSteps,
2322                                             CORBA::Double            theTolerance)
2323   throw (SALOME::SALOME_Exception)
2324 {
2325   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2326
2327   SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
2328                                                theAxis,
2329                                                theAngleInRadians,
2330                                                theNbOfSteps,
2331                                                theTolerance,
2332                                                true);
2333   if (!myIsPreviewMode) {
2334     dumpGroupsList(aPythonDump, aGroups);
2335     aPythonDump << this << ".RotationSweepMakeGroups( "
2336                 << theIDsOfElements        << ", "
2337                 << theAxis                   << ", "
2338                 << TVar( theAngleInRadians ) << ", "
2339                 << TVar( theNbOfSteps      ) << ", "
2340                 << TVar( theTolerance      ) << " )";
2341   }
2342   return aGroups;
2343 }
2344
2345 //=======================================================================
2346 //function : RotationSweepObject
2347 //purpose  :
2348 //=======================================================================
2349
2350 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2351                                              const SMESH::AxisStruct & theAxis,
2352                                              CORBA::Double             theAngleInRadians,
2353                                              CORBA::Long               theNbOfSteps,
2354                                              CORBA::Double             theTolerance)
2355   throw (SALOME::SALOME_Exception)
2356 {
2357   if ( !myIsPreviewMode ) {
2358     TPythonDump() << this << ".RotationSweepObject( "
2359                   << theObject << ", "
2360                   << theAxis << ", "
2361                   << theAngleInRadians << ", "
2362                   << theNbOfSteps << ", "
2363                   << theTolerance << " )";
2364   }
2365   prepareIdSource( theObject );
2366   SMESH::long_array_var anElementsId = theObject->GetIDs();
2367   rotationSweep(anElementsId,
2368                 theAxis,
2369                 theAngleInRadians,
2370                 theNbOfSteps,
2371                 theTolerance,
2372                 false);
2373 }
2374
2375 //=======================================================================
2376 //function : RotationSweepObject1D
2377 //purpose  :
2378 //=======================================================================
2379
2380 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2381                                                const SMESH::AxisStruct & theAxis,
2382                                                CORBA::Double             theAngleInRadians,
2383                                                CORBA::Long               theNbOfSteps,
2384                                                CORBA::Double             theTolerance)
2385   throw (SALOME::SALOME_Exception)
2386 {
2387   if ( !myIsPreviewMode ) {
2388     TPythonDump() << this << ".RotationSweepObject1D( "
2389                   << theObject                 << ", "
2390                   << theAxis                   << ", "
2391                   << TVar( theAngleInRadians ) << ", "
2392                   << TVar( theNbOfSteps      ) << ", "
2393                   << TVar( theTolerance      ) << " )";
2394   }
2395   prepareIdSource( theObject );
2396   SMESH::long_array_var anElementsId = theObject->GetIDs();
2397   rotationSweep(anElementsId,
2398                 theAxis,
2399                 theAngleInRadians,
2400                 theNbOfSteps,
2401                 theTolerance,
2402                 false,
2403                 SMDSAbs_Edge);
2404 }
2405
2406 //=======================================================================
2407 //function : RotationSweepObject2D
2408 //purpose  :
2409 //=======================================================================
2410
2411 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2412                                                const SMESH::AxisStruct & theAxis,
2413                                                CORBA::Double             theAngleInRadians,
2414                                                CORBA::Long               theNbOfSteps,
2415                                                CORBA::Double             theTolerance)
2416   throw (SALOME::SALOME_Exception)
2417 {
2418   if ( !myIsPreviewMode ) {
2419     TPythonDump() << this << ".RotationSweepObject2D( "
2420                   << theObject                 << ", "
2421                   << theAxis                   << ", "
2422                   << TVar( theAngleInRadians ) << ", "
2423                   << TVar( theNbOfSteps      ) << ", "
2424                   << TVar( theTolerance      ) << " )";
2425   }
2426   prepareIdSource( theObject );
2427   SMESH::long_array_var anElementsId = theObject->GetIDs();
2428   rotationSweep(anElementsId,
2429                 theAxis,
2430                 theAngleInRadians,
2431                 theNbOfSteps,
2432                 theTolerance,
2433                 false,
2434                 SMDSAbs_Face);
2435 }
2436
2437 //=======================================================================
2438 //function : RotationSweepObjectMakeGroups
2439 //purpose  :
2440 //=======================================================================
2441
2442 SMESH::ListOfGroups*
2443 SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2444                                                   const SMESH::AxisStruct&  theAxis,
2445                                                   CORBA::Double             theAngleInRadians,
2446                                                   CORBA::Long               theNbOfSteps,
2447                                                   CORBA::Double             theTolerance)
2448   throw (SALOME::SALOME_Exception)
2449 {
2450   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2451
2452   prepareIdSource( theObject );
2453   SMESH::long_array_var anElementsId = theObject->GetIDs();
2454   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2455                                                theAxis,
2456                                                theAngleInRadians,
2457                                                theNbOfSteps,
2458                                                theTolerance,
2459                                                true);
2460   if (!myIsPreviewMode) {
2461     dumpGroupsList(aPythonDump, aGroups);
2462     aPythonDump << this << ".RotationSweepObjectMakeGroups( "
2463                 << theObject << ", "
2464                 << theAxis << ", "
2465                 << theAngleInRadians << ", "
2466                 << theNbOfSteps << ", "
2467                 << theTolerance << " )";
2468   }
2469   return aGroups;
2470 }
2471
2472 //=======================================================================
2473 //function : RotationSweepObject1DMakeGroups
2474 //purpose  :
2475 //=======================================================================
2476
2477 SMESH::ListOfGroups*
2478 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2479                                                     const SMESH::AxisStruct&  theAxis,
2480                                                     CORBA::Double             theAngleInRadians,
2481                                                     CORBA::Long               theNbOfSteps,
2482                                                     CORBA::Double             theTolerance)
2483   throw (SALOME::SALOME_Exception)
2484 {
2485   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2486
2487   prepareIdSource( theObject );
2488   SMESH::long_array_var anElementsId = theObject->GetIDs();
2489   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2490                                                theAxis,
2491                                                theAngleInRadians,
2492                                                theNbOfSteps,
2493                                                theTolerance,
2494                                                true,
2495                                                SMDSAbs_Edge);
2496   if (!myIsPreviewMode) {
2497     dumpGroupsList(aPythonDump, aGroups);
2498     aPythonDump << this << ".RotationSweepObject1DMakeGroups( "
2499                 << theObject                 << ", "
2500                 << theAxis                   << ", "
2501                 << TVar( theAngleInRadians ) << ", "
2502                 << TVar( theNbOfSteps )      << ", "
2503                 << TVar( theTolerance )      << " )";
2504   }
2505   return aGroups;
2506 }
2507
2508 //=======================================================================
2509 //function : RotationSweepObject2DMakeGroups
2510 //purpose  :
2511 //=======================================================================
2512
2513 SMESH::ListOfGroups*
2514 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2515                                                     const SMESH::AxisStruct&  theAxis,
2516                                                     CORBA::Double             theAngleInRadians,
2517                                                     CORBA::Long               theNbOfSteps,
2518                                                     CORBA::Double             theTolerance)
2519   throw (SALOME::SALOME_Exception)
2520 {
2521   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2522
2523   prepareIdSource( theObject );
2524   SMESH::long_array_var anElementsId = theObject->GetIDs();
2525   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
2526                                                theAxis,
2527                                                theAngleInRadians,
2528                                                theNbOfSteps,
2529                                                theTolerance,
2530                                                true,
2531                                                SMDSAbs_Face);
2532   if (!myIsPreviewMode) {
2533     dumpGroupsList(aPythonDump, aGroups);
2534     aPythonDump << this << ".RotationSweepObject2DMakeGroups( "
2535                 << theObject                 << ", "
2536                 << theAxis                   << ", "
2537                 << TVar( theAngleInRadians ) << ", "
2538                 << TVar( theNbOfSteps      ) << ", "
2539                 << TVar( theTolerance      ) << " )";
2540   }
2541   return aGroups;
2542 }
2543
2544
2545 //=======================================================================
2546 //function : extrusionSweep
2547 //purpose  :
2548 //=======================================================================
2549
2550 SMESH::ListOfGroups*
2551 SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
2552                                    const SMESH::DirStruct &  theStepVector,
2553                                    CORBA::Long               theNbOfSteps,
2554                                    bool                      theMakeGroups,
2555                                    const SMDSAbs_ElementType theElementType)
2556   throw (SALOME::SALOME_Exception)
2557 {
2558   SMESH_TRY;
2559   initData();
2560
2561   TIDSortedElemSet elements, copyElements;
2562   arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
2563
2564   const SMESH::PointStruct * P = &theStepVector.PS;
2565   gp_Vec stepVec( P->x, P->y, P->z );
2566
2567   TIDSortedElemSet* workElements = & elements;
2568
2569   SMDSAbs_ElementType aType = SMDSAbs_Face;
2570   if (theElementType == SMDSAbs_Node)
2571   {
2572     aType = SMDSAbs_Edge;
2573   }
2574   if ( myIsPreviewMode ) {
2575     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
2576     getPreviewMesh( aType )->Copy( elements, copyElements, select, avoid );
2577     workElements = & copyElements;
2578     theMakeGroups = false;
2579   }
2580
2581   ::SMESH_MeshEditor::TTElemOfElemListMap aHystory;
2582   ::SMESH_MeshEditor::PGroupIDs groupIds = 
2583       getEditor().ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
2584
2585   declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
2586
2587   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2588
2589   SMESH_CATCH( SMESH::throwCorbaException );
2590   return 0;
2591 }
2592
2593 //=======================================================================
2594 //function : ExtrusionSweep
2595 //purpose  :
2596 //=======================================================================
2597
2598 void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
2599                                         const SMESH::DirStruct &  theStepVector,
2600                                         CORBA::Long               theNbOfSteps)
2601   throw (SALOME::SALOME_Exception)
2602 {
2603   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
2604   if (!myIsPreviewMode) {
2605     TPythonDump() << this << ".ExtrusionSweep( "
2606                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps) << " )";
2607   }
2608 }
2609
2610 //=======================================================================
2611 //function : ExtrusionSweep0D
2612 //purpose  :
2613 //=======================================================================
2614
2615 void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElements,
2616                                           const SMESH::DirStruct &  theStepVector,
2617                                           CORBA::Long               theNbOfSteps)
2618   throw (SALOME::SALOME_Exception)
2619 {
2620   extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
2621   if (!myIsPreviewMode) {
2622     TPythonDump() << this << ".ExtrusionSweep0D( "
2623                   << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps)<< " )";
2624   }
2625 }
2626
2627 //=======================================================================
2628 //function : ExtrusionSweepObject
2629 //purpose  :
2630 //=======================================================================
2631
2632 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
2633                                               const SMESH::DirStruct &  theStepVector,
2634                                               CORBA::Long               theNbOfSteps)
2635   throw (SALOME::SALOME_Exception)
2636 {
2637   prepareIdSource( theObject );
2638   SMESH::long_array_var anElementsId = theObject->GetIDs();
2639   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
2640   if (!myIsPreviewMode) {
2641     TPythonDump() << this << ".ExtrusionSweepObject( "
2642                   << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
2643   }
2644 }
2645
2646 //=======================================================================
2647 //function : ExtrusionSweepObject0D
2648 //purpose  :
2649 //=======================================================================
2650
2651 void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObject,
2652                                                 const SMESH::DirStruct &  theStepVector,
2653                                                 CORBA::Long               theNbOfSteps)
2654   throw (SALOME::SALOME_Exception)
2655 {
2656   prepareIdSource( theObject );
2657   SMESH::long_array_var anElementsId = theObject->GetIDs();
2658   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
2659   if ( !myIsPreviewMode ) {
2660     TPythonDump() << this << ".ExtrusionSweepObject0D( "
2661                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2662   }
2663 }
2664
2665 //=======================================================================
2666 //function : ExtrusionSweepObject1D
2667 //purpose  :
2668 //=======================================================================
2669
2670 void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
2671                                                 const SMESH::DirStruct &  theStepVector,
2672                                                 CORBA::Long               theNbOfSteps)
2673   throw (SALOME::SALOME_Exception)
2674 {
2675   prepareIdSource( theObject );
2676   SMESH::long_array_var anElementsId = theObject->GetIDs();
2677   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
2678   if ( !myIsPreviewMode ) {
2679     TPythonDump() << this << ".ExtrusionSweepObject1D( "
2680                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2681   }
2682 }
2683
2684 //=======================================================================
2685 //function : ExtrusionSweepObject2D
2686 //purpose  :
2687 //=======================================================================
2688
2689 void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
2690                                                 const SMESH::DirStruct &  theStepVector,
2691                                                 CORBA::Long               theNbOfSteps)
2692   throw (SALOME::SALOME_Exception)
2693 {
2694   prepareIdSource( theObject );
2695   SMESH::long_array_var anElementsId = theObject->GetIDs();
2696   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
2697   if ( !myIsPreviewMode ) {
2698     TPythonDump() << this << ".ExtrusionSweepObject2D( "
2699                   << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2700   }
2701 }
2702
2703 //=======================================================================
2704 //function : ExtrusionSweepMakeGroups
2705 //purpose  :
2706 //=======================================================================
2707
2708 SMESH::ListOfGroups*
2709 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
2710                                              const SMESH::DirStruct&  theStepVector,
2711                                              CORBA::Long              theNbOfSteps)
2712   throw (SALOME::SALOME_Exception)
2713 {
2714   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2715
2716   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true);
2717
2718   if (!myIsPreviewMode) {
2719     dumpGroupsList(aPythonDump, aGroups);
2720     aPythonDump << this << ".ExtrusionSweepMakeGroups( " << theIDsOfElements
2721                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2722   }
2723   return aGroups;
2724 }
2725
2726 //=======================================================================
2727 //function : ExtrusionSweepMakeGroups0D
2728 //purpose  :
2729 //=======================================================================
2730
2731 SMESH::ListOfGroups*
2732 SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOfElements,
2733                                                const SMESH::DirStruct&  theStepVector,
2734                                                CORBA::Long              theNbOfSteps)
2735   throw (SALOME::SALOME_Exception)
2736 {
2737   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2738
2739   SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true,SMDSAbs_Node);
2740
2741   if (!myIsPreviewMode) {
2742     dumpGroupsList(aPythonDump, aGroups);
2743     aPythonDump << this << ".ExtrusionSweepMakeGroups0D( " << theIDsOfElements
2744                 << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
2745   }
2746   return aGroups;
2747 }
2748
2749 //=======================================================================
2750 //function : ExtrusionSweepObjectMakeGroups
2751 //purpose  :
2752 //=======================================================================
2753
2754 SMESH::ListOfGroups*
2755 SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2756                                                    const SMESH::DirStruct&   theStepVector,
2757                                                    CORBA::Long               theNbOfSteps)
2758   throw (SALOME::SALOME_Exception)
2759 {
2760   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2761
2762   prepareIdSource( theObject );
2763   SMESH::long_array_var anElementsId = theObject->GetIDs();
2764   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector, theNbOfSteps, true);
2765
2766   if (!myIsPreviewMode) {
2767     dumpGroupsList(aPythonDump, aGroups);
2768     aPythonDump << this << ".ExtrusionSweepObjectMakeGroups( " << theObject
2769                 << ", " << theStepVector << ", " << theNbOfSteps << " )";
2770   }
2771   return aGroups;
2772 }
2773
2774 //=======================================================================
2775 //function : ExtrusionSweepObject0DMakeGroups
2776 //purpose  :
2777 //=======================================================================
2778
2779 SMESH::ListOfGroups*
2780 SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2781                                                      const SMESH::DirStruct&   theStepVector,
2782                                                      CORBA::Long               theNbOfSteps)
2783   throw (SALOME::SALOME_Exception)
2784 {
2785   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2786
2787   prepareIdSource( theObject );
2788   SMESH::long_array_var anElementsId = theObject->GetIDs();
2789   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2790                                                  theNbOfSteps, true, SMDSAbs_Node);
2791   if (!myIsPreviewMode) {
2792     dumpGroupsList(aPythonDump, aGroups);
2793     aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
2794                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2795   }
2796   return aGroups;
2797 }
2798
2799 //=======================================================================
2800 //function : ExtrusionSweepObject1DMakeGroups
2801 //purpose  :
2802 //=======================================================================
2803
2804 SMESH::ListOfGroups*
2805 SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2806                                                      const SMESH::DirStruct&   theStepVector,
2807                                                      CORBA::Long               theNbOfSteps)
2808   throw (SALOME::SALOME_Exception)
2809 {
2810   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2811
2812   prepareIdSource( theObject );
2813   SMESH::long_array_var anElementsId = theObject->GetIDs();
2814   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2815                                                  theNbOfSteps, true, SMDSAbs_Edge);
2816   if (!myIsPreviewMode) {
2817     dumpGroupsList(aPythonDump, aGroups);
2818     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
2819                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2820   }
2821   return aGroups;
2822 }
2823
2824 //=======================================================================
2825 //function : ExtrusionSweepObject2DMakeGroups
2826 //purpose  :
2827 //=======================================================================
2828
2829 SMESH::ListOfGroups*
2830 SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
2831                                                      const SMESH::DirStruct&   theStepVector,
2832                                                      CORBA::Long               theNbOfSteps)
2833   throw (SALOME::SALOME_Exception)
2834 {
2835   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2836
2837   prepareIdSource( theObject );
2838   SMESH::long_array_var anElementsId = theObject->GetIDs();
2839   SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
2840                                                  theNbOfSteps, true, SMDSAbs_Face);
2841   if (!myIsPreviewMode) {
2842     dumpGroupsList(aPythonDump, aGroups);
2843     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
2844                 << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
2845   }
2846   return aGroups;
2847 }
2848
2849
2850 //=======================================================================
2851 //function : advancedExtrusion
2852 //purpose  :
2853 //=======================================================================
2854
2855 SMESH::ListOfGroups*
2856 SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
2857                                       const SMESH::DirStruct &  theStepVector,
2858                                       CORBA::Long               theNbOfSteps,
2859                                       CORBA::Long               theExtrFlags,
2860                                       CORBA::Double             theSewTolerance,
2861                                       const bool                theMakeGroups)
2862   throw (SALOME::SALOME_Exception)
2863 {
2864   SMESH_TRY;
2865   initData();
2866
2867   TIDSortedElemSet elements;
2868   arrayToSet(theIDsOfElements, getMeshDS(), elements);
2869
2870   const SMESH::PointStruct * P = &theStepVector.PS;
2871   gp_Vec stepVec( P->x, P->y, P->z );
2872
2873   ::SMESH_MeshEditor::TTElemOfElemListMap aHystory;
2874   ::SMESH_MeshEditor::PGroupIDs groupIds =
2875       getEditor().ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
2876                                   theMakeGroups, theExtrFlags, theSewTolerance);
2877
2878   declareMeshModified( /*isReComputeSafe=*/true );
2879
2880   return theMakeGroups ? getGroups(groupIds.get()) : 0;
2881
2882   SMESH_CATCH( SMESH::throwCorbaException );
2883   return 0;
2884 }
2885
2886 //=======================================================================
2887 //function : AdvancedExtrusion
2888 //purpose  :
2889 //=======================================================================
2890
2891 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
2892                                            const SMESH::DirStruct &  theStepVector,
2893                                            CORBA::Long               theNbOfSteps,
2894                                            CORBA::Long               theExtrFlags,
2895                                            CORBA::Double             theSewTolerance)
2896   throw (SALOME::SALOME_Exception)
2897 {
2898   if ( !myIsPreviewMode ) {
2899     TPythonDump() << "stepVector = " << theStepVector;
2900     TPythonDump() << this << ".AdvancedExtrusion("
2901                   << theIDsOfElements
2902                   << ", stepVector, "
2903                   << theNbOfSteps << ","
2904                   << theExtrFlags << ", "
2905                   << theSewTolerance <<  " )";
2906   }
2907   advancedExtrusion( theIDsOfElements,
2908                      theStepVector,
2909                      theNbOfSteps,
2910                      theExtrFlags,
2911                      theSewTolerance,
2912                      false);
2913 }
2914
2915 //=======================================================================
2916 //function : AdvancedExtrusionMakeGroups
2917 //purpose  :
2918 //=======================================================================
2919 SMESH::ListOfGroups*
2920 SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
2921                                                 const SMESH::DirStruct&  theStepVector,
2922                                                 CORBA::Long              theNbOfSteps,
2923                                                 CORBA::Long              theExtrFlags,
2924                                                 CORBA::Double            theSewTolerance)
2925   throw (SALOME::SALOME_Exception)
2926 {
2927   if (!myIsPreviewMode) {
2928     TPythonDump() << "stepVector = " << theStepVector;
2929   }
2930   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
2931
2932   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
2933                                                      theStepVector,
2934                                                      theNbOfSteps,
2935                                                      theExtrFlags,
2936                                                      theSewTolerance,
2937                                                      true);
2938
2939   if (!myIsPreviewMode) {
2940     dumpGroupsList(aPythonDump, aGroups);
2941     aPythonDump << this << ".AdvancedExtrusionMakeGroups("
2942                 << theIDsOfElements
2943                 << ", stepVector, "
2944                 << theNbOfSteps << ","
2945                 << theExtrFlags << ", "
2946                 << theSewTolerance <<  " )";
2947   }
2948   return aGroups;
2949 }
2950
2951
2952 //================================================================================
2953 /*!
2954  * \brief Convert extrusion error to IDL enum
2955  */
2956 //================================================================================
2957
2958 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
2959
2960 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
2961 {
2962   switch ( e ) {
2963     RETCASE( EXTR_OK );
2964     RETCASE( EXTR_NO_ELEMENTS );
2965     RETCASE( EXTR_PATH_NOT_EDGE );
2966     RETCASE( EXTR_BAD_PATH_SHAPE );
2967     RETCASE( EXTR_BAD_STARTING_NODE );
2968     RETCASE( EXTR_BAD_ANGLES_NUMBER );
2969     RETCASE( EXTR_CANT_GET_TANGENT );
2970   }
2971   return SMESH::SMESH_MeshEditor::EXTR_OK;
2972 }
2973
2974
2975 //=======================================================================
2976 //function : extrusionAlongPath
2977 //purpose  :
2978 //=======================================================================
2979 SMESH::ListOfGroups*
2980 SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
2981                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
2982                                        GEOM::GEOM_Object_ptr       thePathShape,
2983                                        CORBA::Long                 theNodeStart,
2984                                        CORBA::Boolean              theHasAngles,
2985                                        const SMESH::double_array & theAngles,
2986                                        CORBA::Boolean              theHasRefPoint,
2987                                        const SMESH::PointStruct &  theRefPoint,
2988                                        const bool                  theMakeGroups,
2989                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
2990                                        const SMDSAbs_ElementType   theElementType)
2991   throw (SALOME::SALOME_Exception)
2992 {
2993   SMESH_TRY;
2994   MESSAGE("extrusionAlongPath");
2995   initData();
2996
2997   if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
2998     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
2999     return 0;
3000   }
3001   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3002
3003   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3004   SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3005
3006   if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
3007     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3008     return 0;
3009   }
3010
3011   SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
3012   if ( !nodeStart ) {
3013     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3014     return 0;
3015   }
3016
3017   TIDSortedElemSet elements;
3018   arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
3019
3020   list<double> angles;
3021   for (int i = 0; i < theAngles.length(); i++) {
3022     angles.push_back( theAngles[i] );
3023   }
3024
3025   gp_Pnt refPnt( theRefPoint.x, theRefPoint.y, theRefPoint.z );
3026
3027   int nbOldGroups = myMesh->NbGroup();
3028
3029   ::SMESH_MeshEditor::Extrusion_Error error =
3030       getEditor().ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
3031                                     theHasAngles, angles, false,
3032                                     theHasRefPoint, refPnt, theMakeGroups );
3033
3034   declareMeshModified( /*isReComputeSafe=*/true );
3035   theError = convExtrError( error );
3036
3037   if ( theMakeGroups ) {
3038     list<int> groupIDs = myMesh->GetGroupIds();
3039     list<int>::iterator newBegin = groupIDs.begin();
3040     std::advance( newBegin, nbOldGroups ); // skip old groups
3041     groupIDs.erase( groupIDs.begin(), newBegin );
3042     return getGroups( & groupIDs );
3043   }
3044   return 0;
3045
3046   SMESH_CATCH( SMESH::throwCorbaException );
3047   return 0;
3048 }
3049
3050 //=======================================================================
3051 //function : extrusionAlongPathX
3052 //purpose  :
3053 //=======================================================================
3054
3055 SMESH::ListOfGroups*
3056 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
3057                                         SMESH::SMESH_IDSource_ptr  Path,
3058                                         CORBA::Long                NodeStart,
3059                                         CORBA::Boolean             HasAngles,
3060                                         const SMESH::double_array& Angles,
3061                                         CORBA::Boolean             LinearVariation,
3062                                         CORBA::Boolean             HasRefPoint,
3063                                         const SMESH::PointStruct&  RefPoint,
3064                                         bool                       MakeGroups,
3065                                         const SMDSAbs_ElementType  ElementType,
3066                                         SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
3067   throw (SALOME::SALOME_Exception)
3068 {
3069   SMESH_TRY;
3070   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
3071
3072   initData();
3073
3074   list<double> angles;
3075   for (int i = 0; i < Angles.length(); i++) {
3076     angles.push_back( Angles[i] );
3077   }
3078   gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
3079   int nbOldGroups = myMesh->NbGroup();
3080
3081   if ( Path->_is_nil() ) {
3082     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3083     return EmptyGr;
3084   }
3085
3086   TIDSortedElemSet elements, copyElements;
3087   arrayToSet(IDsOfElements, getMeshDS(), elements, ElementType);
3088
3089   TIDSortedElemSet* workElements = &elements;
3090
3091   if ( myIsPreviewMode )
3092   {
3093     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
3094     getPreviewMesh( SMDSAbs_Face )->Copy( elements, copyElements, select, avoid );
3095     workElements = & copyElements;
3096     MakeGroups = false;
3097   }
3098
3099   ::SMESH_MeshEditor::Extrusion_Error error;
3100
3101   if ( SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path ))
3102   {
3103     // path as mesh
3104     SMDS_MeshNode* aNodeStart =
3105       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
3106     if ( !aNodeStart ) {
3107       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3108       return EmptyGr;
3109     }
3110     error = getEditor().ExtrusionAlongTrack( *workElements, &(aMeshImp->GetImpl()), aNodeStart,
3111                                              HasAngles, angles, LinearVariation,
3112                                              HasRefPoint, refPnt, MakeGroups );
3113     declareMeshModified( /*isReComputeSafe=*/true );
3114   }
3115   else if ( SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path ))
3116   {
3117     // path as submesh
3118     SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
3119     aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
3120     SMDS_MeshNode* aNodeStart =
3121       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
3122     if ( !aNodeStart ) {
3123       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
3124       return EmptyGr;
3125     }
3126     SMESH_subMesh* aSubMesh =
3127       aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
3128     error = getEditor().ExtrusionAlongTrack( *workElements, aSubMesh, aNodeStart,
3129                                              HasAngles, angles, LinearVariation,
3130                                              HasRefPoint, refPnt, MakeGroups );
3131     declareMeshModified( /*isReComputeSafe=*/true );
3132   }
3133   else if ( SMESH::DownCast<SMESH_Group_i*>( Path ))
3134   {
3135     // path as group of 1D elements
3136     // ????????
3137   }
3138   else
3139   {
3140     // invalid path
3141     Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
3142     return EmptyGr;
3143   }
3144
3145   Error = convExtrError( error );
3146
3147   if ( MakeGroups ) {
3148     list<int> groupIDs = myMesh->GetGroupIds();
3149     list<int>::iterator newBegin = groupIDs.begin();
3150     std::advance( newBegin, nbOldGroups ); // skip old groups
3151     groupIDs.erase( groupIDs.begin(), newBegin );
3152     return getGroups( & groupIDs );
3153   }
3154   return EmptyGr;
3155
3156   SMESH_CATCH( SMESH::throwCorbaException );
3157   return 0;
3158 }
3159
3160 //=======================================================================
3161 //function : ExtrusionAlongPath
3162 //purpose  :
3163 //=======================================================================
3164
3165 SMESH::SMESH_MeshEditor::Extrusion_Error
3166 SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
3167                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
3168                                        GEOM::GEOM_Object_ptr       thePathShape,
3169                                        CORBA::Long                 theNodeStart,
3170                                        CORBA::Boolean              theHasAngles,
3171                                        const SMESH::double_array & theAngles,
3172                                        CORBA::Boolean              theHasRefPoint,
3173                                        const SMESH::PointStruct &  theRefPoint)
3174   throw (SALOME::SALOME_Exception)
3175 {
3176   MESSAGE("ExtrusionAlongPath");
3177   if ( !myIsPreviewMode ) {
3178     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
3179                   << theIDsOfElements << ", "
3180                   << thePathMesh      << ", "
3181                   << thePathShape     << ", "
3182                   << theNodeStart     << ", "
3183                   << theHasAngles     << ", "
3184                   << theAngles        << ", "
3185                   << theHasRefPoint   << ", "
3186                   << "SMESH.PointStruct( "
3187                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3188                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3189                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3190   }
3191   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3192   extrusionAlongPath( theIDsOfElements,
3193                       thePathMesh,
3194                       thePathShape,
3195                       theNodeStart,
3196                       theHasAngles,
3197                       theAngles,
3198                       theHasRefPoint,
3199                       theRefPoint,
3200                       false,
3201                       anError);
3202   return anError;
3203 }
3204
3205 //=======================================================================
3206 //function : ExtrusionAlongPathObject
3207 //purpose  :
3208 //=======================================================================
3209
3210 SMESH::SMESH_MeshEditor::Extrusion_Error
3211 SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObject,
3212                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
3213                                              GEOM::GEOM_Object_ptr       thePathShape,
3214                                              CORBA::Long                 theNodeStart,
3215                                              CORBA::Boolean              theHasAngles,
3216                                              const SMESH::double_array & theAngles,
3217                                              CORBA::Boolean              theHasRefPoint,
3218                                              const SMESH::PointStruct &  theRefPoint)
3219   throw (SALOME::SALOME_Exception)
3220 {
3221   if ( !myIsPreviewMode ) {
3222     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
3223                   << theObject        << ", "
3224                   << thePathMesh      << ", "
3225                   << thePathShape     << ", "
3226                   << theNodeStart     << ", "
3227                   << theHasAngles     << ", "
3228                   << theAngles        << ", "
3229                   << theHasRefPoint   << ", "
3230                   << "SMESH.PointStruct( "
3231                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3232                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3233                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3234   }
3235   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3236   prepareIdSource( theObject );
3237   SMESH::long_array_var anElementsId = theObject->GetIDs();
3238   extrusionAlongPath( anElementsId,
3239                       thePathMesh,
3240                       thePathShape,
3241                       theNodeStart,
3242                       theHasAngles,
3243                       theAngles,
3244                       theHasRefPoint,
3245                       theRefPoint,
3246                       false,
3247                       anError);
3248   return anError;
3249 }
3250
3251 //=======================================================================
3252 //function : ExtrusionAlongPathObject1D
3253 //purpose  :
3254 //=======================================================================
3255
3256 SMESH::SMESH_MeshEditor::Extrusion_Error
3257 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
3258                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
3259                                                GEOM::GEOM_Object_ptr       thePathShape,
3260                                                CORBA::Long                 theNodeStart,
3261                                                CORBA::Boolean              theHasAngles,
3262                                                const SMESH::double_array & theAngles,
3263                                                CORBA::Boolean              theHasRefPoint,
3264                                                const SMESH::PointStruct &  theRefPoint)
3265   throw (SALOME::SALOME_Exception)
3266 {
3267   if ( !myIsPreviewMode ) {
3268     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
3269                   << theObject        << ", "
3270                   << thePathMesh      << ", "
3271                   << thePathShape     << ", "
3272                   << theNodeStart     << ", "
3273                   << theHasAngles     << ", "
3274                   << theAngles        << ", "
3275                   << theHasRefPoint   << ", "
3276                   << "SMESH.PointStruct( "
3277                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3278                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3279                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3280   }
3281   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3282   prepareIdSource( theObject );
3283   SMESH::long_array_var anElementsId = theObject->GetIDs();
3284   extrusionAlongPath( anElementsId,
3285                       thePathMesh,
3286                       thePathShape,
3287                       theNodeStart,
3288                       theHasAngles,
3289                       theAngles,
3290                       theHasRefPoint,
3291                       theRefPoint,
3292                       false,
3293                       anError,
3294                       SMDSAbs_Edge);
3295   return anError;
3296 }
3297
3298 //=======================================================================
3299 //function : ExtrusionAlongPathObject2D
3300 //purpose  :
3301 //=======================================================================
3302
3303 SMESH::SMESH_MeshEditor::Extrusion_Error
3304 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
3305                                                SMESH::SMESH_Mesh_ptr       thePathMesh,
3306                                                GEOM::GEOM_Object_ptr       thePathShape,
3307                                                CORBA::Long                 theNodeStart,
3308                                                CORBA::Boolean              theHasAngles,
3309                                                const SMESH::double_array & theAngles,
3310                                                CORBA::Boolean              theHasRefPoint,
3311                                                const SMESH::PointStruct &  theRefPoint)
3312   throw (SALOME::SALOME_Exception)
3313 {
3314   if ( !myIsPreviewMode ) {
3315     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
3316                   << theObject        << ", "
3317                   << thePathMesh      << ", "
3318                   << thePathShape     << ", "
3319                   << theNodeStart     << ", "
3320                   << theHasAngles     << ", "
3321                   << theAngles        << ", "
3322                   << theHasRefPoint   << ", "
3323                   << "SMESH.PointStruct( "
3324                   << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3325                   << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3326                   << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3327   }
3328   SMESH::SMESH_MeshEditor::Extrusion_Error anError;
3329   prepareIdSource( theObject );
3330   SMESH::long_array_var anElementsId = theObject->GetIDs();
3331   extrusionAlongPath( anElementsId,
3332                       thePathMesh,
3333                       thePathShape,
3334                       theNodeStart,
3335                       theHasAngles,
3336                       theAngles,
3337                       theHasRefPoint,
3338                       theRefPoint,
3339                       false,
3340                       anError,
3341                       SMDSAbs_Face);
3342   return anError;
3343 }
3344
3345
3346 //=======================================================================
3347 //function : ExtrusionAlongPathMakeGroups
3348 //purpose  :
3349 //=======================================================================
3350
3351 SMESH::ListOfGroups*
3352 SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theIDsOfElements,
3353                                                  SMESH::SMESH_Mesh_ptr      thePathMesh,
3354                                                  GEOM::GEOM_Object_ptr      thePathShape,
3355                                                  CORBA::Long                theNodeStart,
3356                                                  CORBA::Boolean             theHasAngles,
3357                                                  const SMESH::double_array& theAngles,
3358                                                  CORBA::Boolean             theHasRefPoint,
3359                                                  const SMESH::PointStruct&  theRefPoint,
3360                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3361   throw (SALOME::SALOME_Exception)
3362 {
3363   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3364
3365   SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
3366                                                        thePathMesh,
3367                                                        thePathShape,
3368                                                        theNodeStart,
3369                                                        theHasAngles,
3370                                                        theAngles,
3371                                                        theHasRefPoint,
3372                                                        theRefPoint,
3373                                                        true,
3374                                                        Error);
3375   if (!myIsPreviewMode) {
3376     bool isDumpGroups = aGroups && aGroups->length() > 0;
3377     if (isDumpGroups)
3378       aPythonDump << "(" << aGroups << ", error)";
3379     else
3380       aPythonDump <<"error";
3381
3382     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
3383                << theIDsOfElements << ", "
3384                << thePathMesh      << ", "
3385                << thePathShape     << ", "
3386                << theNodeStart     << ", "
3387                << theHasAngles     << ", "
3388                << theAngles        << ", "
3389                << theHasRefPoint   << ", "
3390                << "SMESH.PointStruct( "
3391                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3392                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3393                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3394   }
3395   return aGroups;
3396 }
3397
3398 //=======================================================================
3399 //function : ExtrusionAlongPathObjectMakeGroups
3400 //purpose  :
3401 //=======================================================================
3402
3403 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3404 ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3405                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
3406                                    GEOM::GEOM_Object_ptr      thePathShape,
3407                                    CORBA::Long                theNodeStart,
3408                                    CORBA::Boolean             theHasAngles,
3409                                    const SMESH::double_array& theAngles,
3410                                    CORBA::Boolean             theHasRefPoint,
3411                                    const SMESH::PointStruct&  theRefPoint,
3412                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3413   throw (SALOME::SALOME_Exception)
3414 {
3415   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3416
3417   prepareIdSource( theObject );
3418   SMESH::long_array_var anElementsId = theObject->GetIDs();
3419   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3420                                                       thePathMesh,
3421                                                       thePathShape,
3422                                                       theNodeStart,
3423                                                       theHasAngles,
3424                                                       theAngles,
3425                                                       theHasRefPoint,
3426                                                       theRefPoint,
3427                                                       true,
3428                                                       Error);
3429
3430   if (!myIsPreviewMode) {
3431     bool isDumpGroups = aGroups && aGroups->length() > 0;
3432     if (isDumpGroups)
3433       aPythonDump << "(" << aGroups << ", error)";
3434     else
3435       aPythonDump <<"error";
3436
3437     aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
3438                 << theObject << ", "
3439                 << thePathMesh      << ", "
3440                 << thePathShape     << ", "
3441                 << theNodeStart     << ", "
3442                 << theHasAngles     << ", "
3443                 << theAngles        << ", "
3444                 << theHasRefPoint   << ", "
3445                 << "SMESH.PointStruct( "
3446                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3447                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3448                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3449   }
3450   return aGroups;
3451 }
3452
3453 //=======================================================================
3454 //function : ExtrusionAlongPathObject1DMakeGroups
3455 //purpose  :
3456 //=======================================================================
3457
3458 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3459 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3460                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
3461                                      GEOM::GEOM_Object_ptr      thePathShape,
3462                                      CORBA::Long                theNodeStart,
3463                                      CORBA::Boolean             theHasAngles,
3464                                      const SMESH::double_array& theAngles,
3465                                      CORBA::Boolean             theHasRefPoint,
3466                                      const SMESH::PointStruct&  theRefPoint,
3467                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3468   throw (SALOME::SALOME_Exception)
3469 {
3470   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3471
3472   prepareIdSource( theObject );
3473   SMESH::long_array_var anElementsId = theObject->GetIDs();
3474   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3475                                                       thePathMesh,
3476                                                       thePathShape,
3477                                                       theNodeStart,
3478                                                       theHasAngles,
3479                                                       theAngles,
3480                                                       theHasRefPoint,
3481                                                       theRefPoint,
3482                                                       true,
3483                                                       Error,
3484                                                       SMDSAbs_Edge);
3485
3486   if (!myIsPreviewMode) {
3487     bool isDumpGroups = aGroups && aGroups->length() > 0;
3488     if (isDumpGroups)
3489       aPythonDump << "(" << aGroups << ", error)";
3490     else
3491       aPythonDump << "error";
3492
3493     aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
3494                 << theObject << ", "
3495                 << thePathMesh      << ", "
3496                 << thePathShape     << ", "
3497                 << theNodeStart     << ", "
3498                 << theHasAngles     << ", "
3499                 << theAngles        << ", "
3500                 << theHasRefPoint   << ", "
3501                 << "SMESH.PointStruct( "
3502                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3503                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3504                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3505   }
3506   return aGroups;
3507 }
3508
3509 //=======================================================================
3510 //function : ExtrusionAlongPathObject2DMakeGroups
3511 //purpose  :
3512 //=======================================================================
3513
3514 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3515 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
3516                                      SMESH::SMESH_Mesh_ptr      thePathMesh,
3517                                      GEOM::GEOM_Object_ptr      thePathShape,
3518                                      CORBA::Long                theNodeStart,
3519                                      CORBA::Boolean             theHasAngles,
3520                                      const SMESH::double_array& theAngles,
3521                                      CORBA::Boolean             theHasRefPoint,
3522                                      const SMESH::PointStruct&  theRefPoint,
3523                                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3524   throw (SALOME::SALOME_Exception)
3525 {
3526   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3527
3528   prepareIdSource( theObject );
3529   SMESH::long_array_var anElementsId = theObject->GetIDs();
3530   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
3531                                                       thePathMesh,
3532                                                       thePathShape,
3533                                                       theNodeStart,
3534                                                       theHasAngles,
3535                                                       theAngles,
3536                                                       theHasRefPoint,
3537                                                       theRefPoint,
3538                                                       true,
3539                                                       Error,
3540                                                       SMDSAbs_Face);
3541
3542   if (!myIsPreviewMode) {
3543     bool isDumpGroups = aGroups && aGroups->length() > 0;
3544     if (isDumpGroups)
3545       aPythonDump << "(" << aGroups << ", error)";
3546     else
3547       aPythonDump << "error";
3548
3549     aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
3550                 << theObject << ", "
3551                 << thePathMesh      << ", "
3552                 << thePathShape     << ", "
3553                 << theNodeStart     << ", "
3554                 << theHasAngles     << ", "
3555                 << theAngles        << ", "
3556                 << theHasRefPoint   << ", "
3557                 << "SMESH.PointStruct( "
3558                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
3559                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
3560                 << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
3561   }
3562   return aGroups;
3563 }
3564
3565 //=======================================================================
3566 //function : ExtrusionAlongPathObjX
3567 //purpose  :
3568 //=======================================================================
3569
3570 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3571 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
3572                        SMESH::SMESH_IDSource_ptr  Path,
3573                        CORBA::Long                NodeStart,
3574                        CORBA::Boolean             HasAngles,
3575                        const SMESH::double_array& Angles,
3576                        CORBA::Boolean             LinearVariation,
3577                        CORBA::Boolean             HasRefPoint,
3578                        const SMESH::PointStruct&  RefPoint,
3579                        CORBA::Boolean             MakeGroups,
3580                        SMESH::ElementType         ElemType,
3581                        SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3582   throw (SALOME::SALOME_Exception)
3583 {
3584   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3585
3586   prepareIdSource( Object );
3587   SMESH::long_array_var anElementsId = Object->GetIDs();
3588   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
3589                                                       Path,
3590                                                       NodeStart,
3591                                                       HasAngles,
3592                                                       Angles,
3593                                                       LinearVariation,
3594                                                       HasRefPoint,
3595                                                       RefPoint,
3596                                                       MakeGroups,
3597                                                       (SMDSAbs_ElementType)ElemType,
3598                                                       Error);
3599
3600   if (!myIsPreviewMode) {
3601     bool isDumpGroups = aGroups && aGroups->length() > 0;
3602     if (isDumpGroups)
3603       aPythonDump << "(" << *aGroups << ", error)";
3604     else
3605       aPythonDump << "error";
3606
3607     aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
3608                 << Object          << ", "
3609                 << Path            << ", "
3610                 << NodeStart       << ", "
3611                 << HasAngles       << ", "
3612                 << TVar( Angles )  << ", "
3613                 << LinearVariation << ", "
3614                 << HasRefPoint     << ", "
3615                 << "SMESH.PointStruct( "
3616                 << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
3617                 << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
3618                 << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
3619                 << MakeGroups << ", "
3620                 << ElemType << " )";
3621   }
3622   return aGroups;
3623 }
3624
3625 //=======================================================================
3626 //function : ExtrusionAlongPathX
3627 //purpose  :
3628 //=======================================================================
3629
3630 SMESH::ListOfGroups* SMESH_MeshEditor_i::
3631 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
3632                     SMESH::SMESH_IDSource_ptr  Path,
3633                     CORBA::Long                NodeStart,
3634                     CORBA::Boolean             HasAngles,
3635                     const SMESH::double_array& Angles,
3636                     CORBA::Boolean             LinearVariation,
3637                     CORBA::Boolean             HasRefPoint,
3638                     const SMESH::PointStruct&  RefPoint,
3639                     CORBA::Boolean             MakeGroups,
3640                     SMESH::ElementType         ElemType,
3641                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
3642   throw (SALOME::SALOME_Exception)
3643 {
3644   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3645
3646   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
3647                                                       Path,
3648                                                       NodeStart,
3649                                                       HasAngles,
3650                                                       Angles,
3651                                                       LinearVariation,
3652                                                       HasRefPoint,
3653                                                       RefPoint,
3654                                                       MakeGroups,
3655                                                       (SMDSAbs_ElementType)ElemType,
3656                                                       Error);
3657
3658   if (!myIsPreviewMode) {
3659     bool isDumpGroups = aGroups && aGroups->length() > 0;
3660     if (isDumpGroups)
3661       aPythonDump << "(" << *aGroups << ", error)";
3662     else
3663       aPythonDump <<"error";
3664
3665     aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
3666                 << IDsOfElements   << ", "
3667                 << Path            << ", "
3668                 << NodeStart       << ", "
3669                 << HasAngles       << ", "
3670                 << TVar( Angles )  << ", "
3671                 << LinearVariation << ", "
3672                 << HasRefPoint     << ", "
3673                 << "SMESH.PointStruct( "
3674                 << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
3675                 << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
3676                 << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
3677                 << MakeGroups << ", "
3678                 << ElemType << " )";
3679   }
3680   return aGroups;
3681 }
3682
3683 //================================================================================
3684 /*!
3685  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
3686  * of given angles along path steps
3687  * \param PathMesh mesh containing a 1D sub-mesh on the edge, along
3688  *                which proceeds the extrusion
3689  * \param PathShape is shape(edge); as the mesh can be complex, the edge
3690  *                 is used to define the sub-mesh for the path
3691  */
3692 //================================================================================
3693
3694 SMESH::double_array*
3695 SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMesh,
3696                                           GEOM::GEOM_Object_ptr       thePathShape,
3697                                           const SMESH::double_array & theAngles)
3698 {
3699   SMESH::double_array_var aResult = new SMESH::double_array();
3700   int nbAngles = theAngles.length();
3701   if ( nbAngles > 0 && !thePathMesh->_is_nil() && !thePathShape->_is_nil() )
3702   {
3703     SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
3704     TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
3705     SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
3706     if ( !aSubMesh || !aSubMesh->GetSubMeshDS())
3707       return aResult._retn();
3708     int nbSteps = aSubMesh->GetSubMeshDS()->NbElements();
3709     if ( nbSteps == nbAngles )
3710     {
3711       aResult.inout() = theAngles;
3712     }
3713     else
3714     {
3715       aResult->length( nbSteps );
3716       double rAn2St = double( nbAngles ) / double( nbSteps );
3717       double angPrev = 0, angle;
3718       for ( int iSt = 0; iSt < nbSteps; ++iSt )
3719       {
3720         double angCur = rAn2St * ( iSt+1 );
3721         double angCurFloor  = floor( angCur );
3722         double angPrevFloor = floor( angPrev );
3723         if ( angPrevFloor == angCurFloor )
3724           angle = rAn2St * theAngles[ int( angCurFloor ) ];
3725         else
3726         {
3727           int iP = int( angPrevFloor );
3728           double angPrevCeil = ceil(angPrev);
3729           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
3730
3731           int iC = int( angCurFloor );
3732           if ( iC < nbAngles )
3733             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
3734
3735           iP = int( angPrevCeil );
3736           while ( iC-- > iP )
3737             angle += theAngles[ iC ];
3738         }
3739         aResult[ iSt ] = angle;
3740         angPrev = angCur;
3741       }
3742     }
3743   }
3744   // Update Python script
3745   TPythonDump() << "rotAngles = " << theAngles;
3746   TPythonDump() << "rotAngles = " << this << ".LinearAnglesVariation( "
3747                 << thePathMesh  << ", "
3748                 << thePathShape << ", "
3749                 << "rotAngles )";
3750
3751   return aResult._retn();
3752 }
3753
3754 //=======================================================================
3755 //function : mirror
3756 //purpose  :
3757 //=======================================================================
3758
3759 SMESH::ListOfGroups*
3760 SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
3761                            const SMESH::AxisStruct &           theAxis,
3762                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3763                            CORBA::Boolean                      theCopy,
3764                            bool                                theMakeGroups,
3765                            ::SMESH_Mesh*                       theTargetMesh)
3766   throw (SALOME::SALOME_Exception)
3767 {
3768   SMESH_TRY;
3769   initData();
3770
3771   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
3772   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
3773
3774   if ( theTargetMesh )
3775     theCopy = false;
3776
3777   gp_Trsf aTrsf;
3778   switch ( theMirrorType ) {
3779   case  SMESH::SMESH_MeshEditor::POINT:
3780     aTrsf.SetMirror( P );
3781     break;
3782   case  SMESH::SMESH_MeshEditor::AXIS:
3783     aTrsf.SetMirror( gp_Ax1( P, V ));
3784     break;
3785   default:
3786     aTrsf.SetMirror( gp_Ax2( P, V ));
3787   }
3788
3789   TIDSortedElemSet  copyElements;
3790   TIDSortedElemSet* workElements = & theElements;
3791
3792   if ( myIsPreviewMode )
3793   {
3794     TPreviewMesh * tmpMesh = getPreviewMesh();
3795     tmpMesh->Copy( theElements, copyElements);
3796     if ( !theCopy && !theTargetMesh )
3797     {
3798       TIDSortedElemSet elemsAround, elemsAroundCopy;
3799       getElementsAround( theElements, getMeshDS(), elemsAround );
3800       tmpMesh->Copy( elemsAround, elemsAroundCopy);
3801     }
3802     workElements = & copyElements;
3803     theMakeGroups = false;
3804   }
3805
3806   ::SMESH_MeshEditor::PGroupIDs groupIds =
3807       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
3808
3809   if ( theCopy && !myIsPreviewMode)
3810   {
3811     if ( theTargetMesh )
3812     {
3813       theTargetMesh->GetMeshDS()->Modified();
3814     }
3815     else
3816     {
3817       declareMeshModified( /*isReComputeSafe=*/false );
3818     }
3819   }
3820   return theMakeGroups ? getGroups(groupIds.get()) : 0;
3821
3822   SMESH_CATCH( SMESH::throwCorbaException );
3823   return 0;
3824 }
3825
3826 //=======================================================================
3827 //function : Mirror
3828 //purpose  :
3829 //=======================================================================
3830
3831 void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElements,
3832                                 const SMESH::AxisStruct &           theAxis,
3833                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3834                                 CORBA::Boolean                      theCopy)
3835   throw (SALOME::SALOME_Exception)
3836 {
3837   if ( !myIsPreviewMode ) {
3838     TPythonDump() << this << ".Mirror( "
3839                   << theIDsOfElements              << ", "
3840                   << theAxis                       << ", "
3841                   << mirrorTypeName(theMirrorType) << ", "
3842                   << theCopy                       << " )";
3843   }
3844   if ( theIDsOfElements.length() > 0 )
3845   {
3846     TIDSortedElemSet elements;
3847     arrayToSet(theIDsOfElements, getMeshDS(), elements);
3848     mirror(elements, theAxis, theMirrorType, theCopy, false);
3849   }
3850 }
3851
3852
3853 //=======================================================================
3854 //function : MirrorObject
3855 //purpose  :
3856 //=======================================================================
3857
3858 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
3859                                       const SMESH::AxisStruct &           theAxis,
3860                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3861                                       CORBA::Boolean                      theCopy)
3862   throw (SALOME::SALOME_Exception)
3863 {
3864   if ( !myIsPreviewMode ) {
3865     TPythonDump() << this << ".MirrorObject( "
3866                   << theObject                     << ", "
3867                   << theAxis                       << ", "
3868                   << mirrorTypeName(theMirrorType) << ", "
3869                   << theCopy                       << " )";
3870   }
3871   TIDSortedElemSet elements;
3872
3873   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
3874
3875   prepareIdSource( theObject );
3876   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
3877     mirror(elements, theAxis, theMirrorType, theCopy, false);
3878 }
3879
3880 //=======================================================================
3881 //function : MirrorMakeGroups
3882 //purpose  :
3883 //=======================================================================
3884
3885 SMESH::ListOfGroups*
3886 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
3887                                      const SMESH::AxisStruct&            theMirror,
3888                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3889   throw (SALOME::SALOME_Exception)
3890 {
3891   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3892
3893   SMESH::ListOfGroups * aGroups = 0;
3894   if ( theIDsOfElements.length() > 0 )
3895   {
3896     TIDSortedElemSet elements;
3897     arrayToSet(theIDsOfElements, getMeshDS(), elements);
3898     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3899   }
3900   if (!myIsPreviewMode) {
3901     dumpGroupsList(aPythonDump, aGroups);
3902     aPythonDump << this << ".MirrorMakeGroups( "
3903                 << theIDsOfElements              << ", "
3904                 << theMirror                     << ", "
3905                 << mirrorTypeName(theMirrorType) << " )";
3906   }
3907   return aGroups;
3908 }
3909
3910 //=======================================================================
3911 //function : MirrorObjectMakeGroups
3912 //purpose  :
3913 //=======================================================================
3914
3915 SMESH::ListOfGroups*
3916 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
3917                                            const SMESH::AxisStruct&            theMirror,
3918                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
3919   throw (SALOME::SALOME_Exception)
3920 {
3921   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
3922
3923   SMESH::ListOfGroups * aGroups = 0;
3924   TIDSortedElemSet elements;
3925   prepareIdSource( theObject );
3926   if ( idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
3927     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
3928
3929   if (!myIsPreviewMode)
3930   {
3931     dumpGroupsList(aPythonDump,aGroups);
3932     aPythonDump << this << ".MirrorObjectMakeGroups( "
3933                 << theObject                     << ", "
3934                 << theMirror                     << ", "
3935                 << mirrorTypeName(theMirrorType) << " )";
3936   }
3937   return aGroups;
3938 }
3939
3940 //=======================================================================
3941 //function : MirrorMakeMesh
3942 //purpose  :
3943 //=======================================================================
3944
3945 SMESH::SMESH_Mesh_ptr
3946 SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfElements,
3947                                    const SMESH::AxisStruct&            theMirror,
3948                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3949                                    CORBA::Boolean                      theCopyGroups,
3950                                    const char*                         theMeshName)
3951   throw (SALOME::SALOME_Exception)
3952 {
3953   SMESH_Mesh_i* mesh_i;
3954   SMESH::SMESH_Mesh_var mesh;
3955   { // open new scope to dump "MakeMesh" command
3956     // and then "GetGroups" using SMESH_Mesh::GetGroups()
3957
3958     TPythonDump pydump; // to prevent dump at mesh creation
3959
3960     mesh = makeMesh( theMeshName );
3961     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
3962     if (mesh_i && theIDsOfElements.length() > 0 )
3963     {
3964       TIDSortedElemSet elements;
3965       arrayToSet(theIDsOfElements, getMeshDS(), elements);
3966       mirror(elements, theMirror, theMirrorType,
3967              false, theCopyGroups, & mesh_i->GetImpl());
3968       mesh_i->CreateGroupServants();
3969     }
3970
3971     if (!myIsPreviewMode) {
3972       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
3973              << theIDsOfElements              << ", "
3974              << theMirror                     << ", "
3975              << mirrorTypeName(theMirrorType) << ", "
3976              << theCopyGroups                 << ", '"
3977              << theMeshName                   << "' )";
3978     }
3979   }
3980
3981   //dump "GetGroups"
3982   if (!myIsPreviewMode && mesh_i)
3983     mesh_i->GetGroups();
3984
3985   return mesh._retn();
3986 }
3987
3988 //=======================================================================
3989 //function : MirrorObjectMakeMesh
3990 //purpose  :
3991 //=======================================================================
3992
3993 SMESH::SMESH_Mesh_ptr
3994 SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           theObject,
3995                                          const SMESH::AxisStruct&            theMirror,
3996                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
3997                                          CORBA::Boolean                      theCopyGroups,
3998                                          const char*                         theMeshName)
3999   throw (SALOME::SALOME_Exception)
4000 {
4001   SMESH_Mesh_i* mesh_i;
4002   SMESH::SMESH_Mesh_var mesh;
4003   { // open new scope to dump "MakeMesh" command
4004     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4005
4006     TPythonDump pydump; // to prevent dump at mesh creation
4007
4008     mesh = makeMesh( theMeshName );
4009     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4010     TIDSortedElemSet elements;
4011     prepareIdSource( theObject );
4012     if ( mesh_i &&
4013          idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4014     {
4015       mirror(elements, theMirror, theMirrorType,
4016              false, theCopyGroups, & mesh_i->GetImpl());
4017       mesh_i->CreateGroupServants();
4018     }
4019     if (!myIsPreviewMode) {
4020       pydump << mesh << " = " << this << ".MirrorObjectMakeMesh( "
4021              << theObject                     << ", "
4022              << theMirror                     << ", "
4023              << mirrorTypeName(theMirrorType) << ", "
4024              << theCopyGroups                 << ", '"
4025              << theMeshName                   << "' )";
4026     }
4027   }
4028
4029   //dump "GetGroups"
4030   if (!myIsPreviewMode && mesh_i)
4031     mesh_i->GetGroups();
4032
4033   return mesh._retn();
4034 }
4035
4036 //=======================================================================
4037 //function : translate
4038 //purpose  :
4039 //=======================================================================
4040
4041 SMESH::ListOfGroups*
4042 SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
4043                               const SMESH::DirStruct &  theVector,
4044                               CORBA::Boolean            theCopy,
4045                               bool                      theMakeGroups,
4046                               ::SMESH_Mesh*             theTargetMesh)
4047   throw (SALOME::SALOME_Exception)
4048 {
4049   SMESH_TRY;
4050   initData();
4051
4052   if ( theTargetMesh )
4053     theCopy = false;
4054
4055   gp_Trsf aTrsf;
4056   const SMESH::PointStruct * P = &theVector.PS;
4057   aTrsf.SetTranslation( gp_Vec( P->x, P->y, P->z ));
4058
4059   TIDSortedElemSet  copyElements;
4060   TIDSortedElemSet* workElements = &theElements;
4061
4062   if ( myIsPreviewMode )
4063   {
4064     TPreviewMesh * tmpMesh = getPreviewMesh();
4065     tmpMesh->Copy( theElements, copyElements);
4066     if ( !theCopy && !theTargetMesh )
4067     {
4068       TIDSortedElemSet elemsAround, elemsAroundCopy;
4069       getElementsAround( theElements, getMeshDS(), elemsAround );
4070       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4071     }
4072     workElements = & copyElements;
4073     theMakeGroups = false;
4074   }
4075
4076   ::SMESH_MeshEditor::PGroupIDs groupIds =
4077       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4078
4079   if ( theCopy && !myIsPreviewMode )
4080   {
4081     if ( theTargetMesh )
4082     {
4083       theTargetMesh->GetMeshDS()->Modified();
4084     }
4085     else
4086     {
4087       declareMeshModified( /*isReComputeSafe=*/false );
4088     }
4089   }
4090
4091   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4092
4093   SMESH_CATCH( SMESH::throwCorbaException );
4094   return 0;
4095 }
4096
4097 //=======================================================================
4098 //function : Translate
4099 //purpose  :
4100 //=======================================================================
4101
4102 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
4103                                    const SMESH::DirStruct &  theVector,
4104                                    CORBA::Boolean            theCopy)
4105   throw (SALOME::SALOME_Exception)
4106 {
4107   if (!myIsPreviewMode) {
4108     TPythonDump() << this << ".Translate( "
4109                   << theIDsOfElements << ", "
4110                   << theVector        << ", "
4111                   << theCopy          << " )";
4112   }
4113   if (theIDsOfElements.length()) {
4114     TIDSortedElemSet elements;
4115     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4116     translate(elements, theVector, theCopy, false);
4117   }
4118 }
4119
4120 //=======================================================================
4121 //function : TranslateObject
4122 //purpose  :
4123 //=======================================================================
4124
4125 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
4126                                          const SMESH::DirStruct &  theVector,
4127                                          CORBA::Boolean            theCopy)
4128   throw (SALOME::SALOME_Exception)
4129 {
4130   if (!myIsPreviewMode) {
4131     TPythonDump() << this << ".TranslateObject( "
4132                   << theObject << ", "
4133                   << theVector << ", "
4134                   << theCopy   << " )";
4135   }
4136   TIDSortedElemSet elements;
4137
4138   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4139   
4140   prepareIdSource( theObject );
4141   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4142     translate(elements, theVector, theCopy, false);
4143 }
4144
4145 //=======================================================================
4146 //function : TranslateMakeGroups
4147 //purpose  :
4148 //=======================================================================
4149
4150 SMESH::ListOfGroups*
4151 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
4152                                         const SMESH::DirStruct&  theVector)
4153   throw (SALOME::SALOME_Exception)
4154 {
4155   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4156
4157   SMESH::ListOfGroups * aGroups = 0;
4158   if (theIDsOfElements.length()) {
4159     TIDSortedElemSet elements;
4160     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4161     aGroups = translate(elements,theVector,true,true);
4162   }
4163   if (!myIsPreviewMode) {
4164     dumpGroupsList(aPythonDump, aGroups);
4165     aPythonDump << this << ".TranslateMakeGroups( "
4166                 << theIDsOfElements << ", "
4167                 << theVector        << " )";
4168   }
4169   return aGroups;
4170 }
4171
4172 //=======================================================================
4173 //function : TranslateObjectMakeGroups
4174 //purpose  :
4175 //=======================================================================
4176
4177 SMESH::ListOfGroups*
4178 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4179                                               const SMESH::DirStruct&   theVector)
4180   throw (SALOME::SALOME_Exception)
4181 {
4182   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4183
4184   SMESH::ListOfGroups * aGroups = 0;
4185   TIDSortedElemSet elements;
4186   prepareIdSource( theObject );
4187   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4188     aGroups = translate(elements, theVector, true, true);
4189
4190   if (!myIsPreviewMode) {
4191     dumpGroupsList(aPythonDump, aGroups);
4192     aPythonDump << this << ".TranslateObjectMakeGroups( "
4193                 << theObject << ", "
4194                 << theVector << " )";
4195   }
4196   return aGroups;
4197 }
4198
4199 //=======================================================================
4200 //function : TranslateMakeMesh
4201 //purpose  :
4202 //=======================================================================
4203
4204 SMESH::SMESH_Mesh_ptr
4205 SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
4206                                       const SMESH::DirStruct&  theVector,
4207                                       CORBA::Boolean           theCopyGroups,
4208                                       const char*              theMeshName)
4209   throw (SALOME::SALOME_Exception)
4210 {
4211   SMESH_Mesh_i* mesh_i;
4212   SMESH::SMESH_Mesh_var mesh;
4213
4214   { // open new scope to dump "MakeMesh" command
4215     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4216
4217     TPythonDump pydump; // to prevent dump at mesh creation
4218
4219     mesh = makeMesh( theMeshName );
4220     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4221
4222     if ( mesh_i && theIDsOfElements.length() )
4223     {
4224       TIDSortedElemSet elements;
4225       arrayToSet(theIDsOfElements, getMeshDS(), elements);
4226       translate(elements, theVector, false, theCopyGroups, & mesh_i->GetImpl());
4227       mesh_i->CreateGroupServants();
4228     }
4229
4230     if ( !myIsPreviewMode ) {
4231       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
4232              << theIDsOfElements << ", "
4233              << theVector        << ", "
4234              << theCopyGroups    << ", '"
4235              << theMeshName      << "' )";
4236     }
4237   }
4238
4239   //dump "GetGroups"
4240   if (!myIsPreviewMode && mesh_i)
4241     mesh_i->GetGroups();
4242
4243   return mesh._retn();
4244 }
4245
4246 //=======================================================================
4247 //function : TranslateObjectMakeMesh
4248 //purpose  :
4249 //=======================================================================
4250
4251 SMESH::SMESH_Mesh_ptr
4252 SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4253                                             const SMESH::DirStruct&   theVector,
4254                                             CORBA::Boolean            theCopyGroups,
4255                                             const char*               theMeshName)
4256   throw (SALOME::SALOME_Exception)
4257 {
4258   SMESH_TRY;
4259   SMESH_Mesh_i* mesh_i;
4260   SMESH::SMESH_Mesh_var mesh;
4261   { // open new scope to dump "MakeMesh" command
4262     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4263
4264     TPythonDump pydump; // to prevent dump at mesh creation
4265     mesh = makeMesh( theMeshName );
4266     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4267
4268     TIDSortedElemSet elements;
4269     prepareIdSource( theObject );
4270     if ( mesh_i &&
4271       idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4272     {
4273       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
4274       mesh_i->CreateGroupServants();
4275     }
4276     if ( !myIsPreviewMode ) {
4277       pydump << mesh << " = " << this << ".TranslateObjectMakeMesh( "
4278              << theObject     << ", "
4279              << theVector     << ", "
4280              << theCopyGroups << ", '"
4281              << theMeshName   << "' )";
4282     }
4283   }
4284
4285   // dump "GetGroups"
4286   if (!myIsPreviewMode && mesh_i)
4287     mesh_i->GetGroups();
4288
4289   return mesh._retn();
4290
4291   SMESH_CATCH( SMESH::throwCorbaException );
4292   return 0;
4293 }
4294
4295 //=======================================================================
4296 //function : rotate
4297 //purpose  :
4298 //=======================================================================
4299
4300 SMESH::ListOfGroups*
4301 SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
4302                            const SMESH::AxisStruct & theAxis,
4303                            CORBA::Double             theAngle,
4304                            CORBA::Boolean            theCopy,
4305                            bool                      theMakeGroups,
4306                            ::SMESH_Mesh*             theTargetMesh)
4307   throw (SALOME::SALOME_Exception)
4308 {
4309   SMESH_TRY;
4310   initData();
4311
4312   if ( theTargetMesh )
4313     theCopy = false;
4314
4315   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
4316   gp_Vec V ( theAxis.vx, theAxis.vy, theAxis.vz );
4317
4318   gp_Trsf aTrsf;
4319   aTrsf.SetRotation( gp_Ax1( P, V ), theAngle);
4320
4321   TIDSortedElemSet  copyElements;
4322   TIDSortedElemSet* workElements = &theElements;
4323   if ( myIsPreviewMode ) {
4324     TPreviewMesh * tmpMesh = getPreviewMesh();
4325     tmpMesh->Copy( theElements, copyElements );
4326     if ( !theCopy && !theTargetMesh )
4327     {
4328       TIDSortedElemSet elemsAround, elemsAroundCopy;
4329       getElementsAround( theElements, getMeshDS(), elemsAround );
4330       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4331     }
4332     workElements = &copyElements;
4333     theMakeGroups = false;
4334   }
4335
4336   ::SMESH_MeshEditor::PGroupIDs groupIds =
4337       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4338
4339   if ( theCopy && !myIsPreviewMode)
4340   {
4341     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
4342     else                 declareMeshModified( /*isReComputeSafe=*/false );
4343   }
4344
4345   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4346
4347   SMESH_CATCH( SMESH::throwCorbaException );
4348   return 0;
4349 }
4350
4351 //=======================================================================
4352 //function : Rotate
4353 //purpose  :
4354 //=======================================================================
4355
4356 void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
4357                                 const SMESH::AxisStruct & theAxis,
4358                                 CORBA::Double             theAngle,
4359                                 CORBA::Boolean            theCopy)
4360   throw (SALOME::SALOME_Exception)
4361 {
4362   if (!myIsPreviewMode) {
4363     TPythonDump() << this << ".Rotate( "
4364                   << theIDsOfElements << ", "
4365                   << theAxis          << ", "
4366                   << TVar( theAngle ) << ", "
4367                   << theCopy          << " )";
4368   }
4369   if (theIDsOfElements.length() > 0)
4370   {
4371     TIDSortedElemSet elements;
4372     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4373     rotate(elements,theAxis,theAngle,theCopy,false);
4374   }
4375 }
4376
4377 //=======================================================================
4378 //function : RotateObject
4379 //purpose  :
4380 //=======================================================================
4381
4382 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
4383                                       const SMESH::AxisStruct & theAxis,
4384                                       CORBA::Double             theAngle,
4385                                       CORBA::Boolean            theCopy)
4386   throw (SALOME::SALOME_Exception)
4387 {
4388   if ( !myIsPreviewMode ) {
4389     TPythonDump() << this << ".RotateObject( "
4390                   << theObject        << ", "
4391                   << theAxis          << ", "
4392                   << TVar( theAngle ) << ", "
4393                   << theCopy          << " )";
4394   }
4395   TIDSortedElemSet elements;
4396   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4397   prepareIdSource( theObject );
4398   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4399     rotate(elements,theAxis,theAngle,theCopy,false);
4400 }
4401
4402 //=======================================================================
4403 //function : RotateMakeGroups
4404 //purpose  :
4405 //=======================================================================
4406
4407 SMESH::ListOfGroups*
4408 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
4409                                      const SMESH::AxisStruct& theAxis,
4410                                      CORBA::Double            theAngle)
4411   throw (SALOME::SALOME_Exception)
4412 {
4413   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4414
4415   SMESH::ListOfGroups * aGroups = 0;
4416   if (theIDsOfElements.length() > 0)
4417   {
4418     TIDSortedElemSet elements;
4419     arrayToSet(theIDsOfElements, getMeshDS(), elements);
4420     aGroups = rotate(elements,theAxis,theAngle,true,true);
4421   }
4422   if (!myIsPreviewMode) {
4423     dumpGroupsList(aPythonDump, aGroups);
4424     aPythonDump << this << ".RotateMakeGroups( "
4425                 << theIDsOfElements << ", "
4426                 << theAxis          << ", "
4427                 << TVar( theAngle ) << " )";
4428   }
4429   return aGroups;
4430 }
4431
4432 //=======================================================================
4433 //function : RotateObjectMakeGroups
4434 //purpose  :
4435 //=======================================================================
4436
4437 SMESH::ListOfGroups*
4438 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
4439                                            const SMESH::AxisStruct&  theAxis,
4440                                            CORBA::Double             theAngle)
4441   throw (SALOME::SALOME_Exception)
4442 {
4443   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4444
4445   SMESH::ListOfGroups * aGroups = 0;
4446   TIDSortedElemSet elements;
4447   prepareIdSource( theObject );
4448   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4449     aGroups = rotate(elements, theAxis, theAngle, true, true);
4450
4451   if (!myIsPreviewMode) {
4452     dumpGroupsList(aPythonDump, aGroups);
4453     aPythonDump << this << ".RotateObjectMakeGroups( "
4454                 << theObject        << ", "
4455                 << theAxis          << ", "
4456                 << TVar( theAngle ) << " )";
4457   }
4458   return aGroups;
4459 }
4460
4461 //=======================================================================
4462 //function : RotateMakeMesh
4463 //purpose  :
4464 //=======================================================================
4465
4466 SMESH::SMESH_Mesh_ptr
4467 SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
4468                                    const SMESH::AxisStruct& theAxis,
4469                                    CORBA::Double            theAngleInRadians,
4470                                    CORBA::Boolean           theCopyGroups,
4471                                    const char*              theMeshName)
4472   throw (SALOME::SALOME_Exception)
4473 {
4474   SMESH_TRY;
4475   SMESH::SMESH_Mesh_var mesh;
4476   SMESH_Mesh_i* mesh_i;
4477
4478   { // open new scope to dump "MakeMesh" command
4479     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4480
4481     TPythonDump pydump; // to prevent dump at mesh creation
4482
4483     mesh = makeMesh( theMeshName );
4484     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4485
4486     if ( mesh_i && theIDsOfElements.length() > 0 )
4487     {
4488       TIDSortedElemSet elements;
4489       arrayToSet(theIDsOfElements, getMeshDS(), elements);
4490       rotate(elements, theAxis, theAngleInRadians,
4491              false, theCopyGroups, & mesh_i->GetImpl());
4492       mesh_i->CreateGroupServants();
4493     }
4494     if ( !myIsPreviewMode ) {
4495       pydump << mesh << " = " << this << ".RotateMakeMesh( "
4496              << theIDsOfElements          << ", "
4497              << theAxis                   << ", "
4498              << TVar( theAngleInRadians ) << ", "
4499              << theCopyGroups             << ", '"
4500              << theMeshName               << "' )";
4501     }
4502   }
4503
4504   // dump "GetGroups"
4505   if (!myIsPreviewMode && mesh_i && theIDsOfElements.length() > 0 )
4506     mesh_i->GetGroups();
4507
4508   return mesh._retn();
4509
4510   SMESH_CATCH( SMESH::throwCorbaException );
4511   return 0;
4512 }
4513
4514 //=======================================================================
4515 //function : RotateObjectMakeMesh
4516 //purpose  :
4517 //=======================================================================
4518
4519 SMESH::SMESH_Mesh_ptr
4520 SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
4521                                          const SMESH::AxisStruct&  theAxis,
4522                                          CORBA::Double             theAngleInRadians,
4523                                          CORBA::Boolean            theCopyGroups,
4524                                          const char*               theMeshName)
4525   throw (SALOME::SALOME_Exception)
4526 {
4527   SMESH_TRY;
4528   SMESH::SMESH_Mesh_var mesh;
4529   SMESH_Mesh_i* mesh_i;
4530
4531   {// open new scope to dump "MakeMesh" command
4532    // and then "GetGroups" using SMESH_Mesh::GetGroups()
4533
4534     TPythonDump pydump; // to prevent dump at mesh creation
4535     mesh = makeMesh( theMeshName );
4536     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4537
4538     TIDSortedElemSet elements;
4539     prepareIdSource( theObject );
4540     if (mesh_i &&
4541         idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
4542     {
4543       rotate(elements, theAxis, theAngleInRadians,
4544              false, theCopyGroups, & mesh_i->GetImpl());
4545       mesh_i->CreateGroupServants();
4546     }
4547     if ( !myIsPreviewMode ) {
4548       pydump << mesh << " = " << this << ".RotateObjectMakeMesh( "
4549              << theObject                 << ", "
4550              << theAxis                   << ", "
4551              << TVar( theAngleInRadians ) << ", "
4552              << theCopyGroups             << ", '"
4553              << theMeshName               << "' )";
4554     }
4555   }
4556
4557   // dump "GetGroups"
4558   if (!myIsPreviewMode && mesh_i)
4559     mesh_i->GetGroups();
4560
4561   return mesh._retn();
4562
4563   SMESH_CATCH( SMESH::throwCorbaException );
4564   return 0;
4565 }
4566
4567 //=======================================================================
4568 //function : scale
4569 //purpose  :
4570 //=======================================================================
4571
4572 SMESH::ListOfGroups*
4573 SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
4574                           const SMESH::PointStruct&  thePoint,
4575                           const SMESH::double_array& theScaleFact,
4576                           CORBA::Boolean             theCopy,
4577                           bool                       theMakeGroups,
4578                           ::SMESH_Mesh*              theTargetMesh)
4579   throw (SALOME::SALOME_Exception)
4580 {
4581   SMESH_TRY;
4582   initData();
4583   if ( theScaleFact.length() < 1 )
4584     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
4585   if ( theScaleFact.length() == 2 )
4586     THROW_SALOME_CORBA_EXCEPTION("Invalid nb of scale factors : 2", SALOME::BAD_PARAM);
4587
4588   if ( theTargetMesh )
4589     theCopy = false;
4590
4591   TIDSortedElemSet elements;
4592   prepareIdSource( theObject );
4593   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
4594   if ( !idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
4595     return 0;
4596
4597   double S[3] = {
4598     theScaleFact[0],
4599     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[1],
4600     (theScaleFact.length() == 1) ? theScaleFact[0] : theScaleFact[2],
4601   };
4602   double tol = std::numeric_limits<double>::max();
4603   gp_Trsf aTrsf;
4604   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
4605                    0,    S[1], 0,    thePoint.y * (1-S[1]),
4606                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
4607
4608   TIDSortedElemSet  copyElements;
4609   TIDSortedElemSet* workElements = &elements;
4610   if ( myIsPreviewMode )
4611   {
4612     TPreviewMesh * tmpMesh = getPreviewMesh();
4613     tmpMesh->Copy( elements, copyElements);
4614     if ( !theCopy && !theTargetMesh )
4615     {
4616       TIDSortedElemSet elemsAround, elemsAroundCopy;
4617       getElementsAround( elements, getMeshDS(), elemsAround );
4618       tmpMesh->Copy( elemsAround, elemsAroundCopy);
4619     }
4620     workElements = & copyElements;
4621     theMakeGroups = false;
4622   }
4623
4624   ::SMESH_MeshEditor::PGroupIDs groupIds =
4625       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
4626
4627   if ( theCopy && !myIsPreviewMode )
4628   {
4629     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
4630     else                 declareMeshModified( /*isReComputeSafe=*/false );
4631   }
4632   return theMakeGroups ? getGroups(groupIds.get()) : 0;
4633
4634   SMESH_CATCH( SMESH::throwCorbaException );
4635   return 0;
4636 }
4637
4638 //=======================================================================
4639 //function : Scale
4640 //purpose  :
4641 //=======================================================================
4642
4643 void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
4644                                const SMESH::PointStruct&  thePoint,
4645                                const SMESH::double_array& theScaleFact,
4646                                CORBA::Boolean             theCopy)
4647   throw (SALOME::SALOME_Exception)
4648 {
4649   if ( !myIsPreviewMode ) {
4650     TPythonDump() << this << ".Scale( "
4651                   << theObject            << ", "
4652                   << thePoint             << ", "
4653                   << TVar( theScaleFact ) << ", "
4654                   << theCopy              << " )";
4655   }
4656   scale(theObject, thePoint, theScaleFact, theCopy, false);
4657 }
4658
4659
4660 //=======================================================================
4661 //function : ScaleMakeGroups
4662 //purpose  :
4663 //=======================================================================
4664
4665 SMESH::ListOfGroups*
4666 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
4667                                     const SMESH::PointStruct&  thePoint,
4668                                     const SMESH::double_array& theScaleFact)
4669   throw (SALOME::SALOME_Exception)
4670 {
4671   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
4672
4673   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
4674   if (!myIsPreviewMode) {
4675     dumpGroupsList(aPythonDump, aGroups);
4676     aPythonDump << this << ".Scale("
4677                 << theObject            << ","
4678                 << thePoint             << ","
4679                 << TVar( theScaleFact ) << ",True,True)";
4680   }
4681   return aGroups;
4682 }
4683
4684
4685 //=======================================================================
4686 //function : ScaleMakeMesh
4687 //purpose  :
4688 //=======================================================================
4689
4690 SMESH::SMESH_Mesh_ptr
4691 SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
4692                                   const SMESH::PointStruct&  thePoint,
4693                                   const SMESH::double_array& theScaleFact,
4694                                   CORBA::Boolean             theCopyGroups,
4695                                   const char*                theMeshName)
4696   throw (SALOME::SALOME_Exception)
4697 {
4698   SMESH_Mesh_i* mesh_i;
4699   SMESH::SMESH_Mesh_var mesh;
4700   { // open new scope to dump "MakeMesh" command
4701     // and then "GetGroups" using SMESH_Mesh::GetGroups()
4702
4703     TPythonDump pydump; // to prevent dump at mesh creation
4704     mesh = makeMesh( theMeshName );
4705     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4706
4707     if ( mesh_i )
4708     {
4709       scale(theObject, thePoint, theScaleFact,false, theCopyGroups, & mesh_i->GetImpl());
4710       mesh_i->CreateGroupServants();
4711     }
4712     if ( !myIsPreviewMode )
4713       pydump << mesh << " = " << this << ".ScaleMakeMesh( "
4714              << theObject            << ", "
4715              << thePoint             << ", "
4716              << TVar( theScaleFact ) << ", "
4717              << theCopyGroups        << ", '"
4718              << theMeshName          << "' )";
4719   }
4720
4721   // dump "GetGroups"
4722   if (!myIsPreviewMode && mesh_i)
4723     mesh_i->GetGroups();
4724
4725   return mesh._retn();
4726 }
4727
4728
4729 //=======================================================================
4730 //function : FindCoincidentNodes
4731 //purpose  :
4732 //=======================================================================
4733
4734 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
4735                                               SMESH::array_of_long_array_out GroupsOfNodes)
4736   throw (SALOME::SALOME_Exception)
4737 {
4738   SMESH_TRY;
4739   initData();
4740
4741   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4742   TIDSortedNodeSet nodes; // no input nodes
4743   getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4744
4745   GroupsOfNodes = new SMESH::array_of_long_array;
4746   GroupsOfNodes->length( aListOfListOfNodes.size() );
4747   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4748   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
4749     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4750     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4751     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4752     aGroup.length( aListOfNodes.size() );
4753     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4754       aGroup[ j ] = (*lIt)->GetID();
4755   }
4756   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
4757                 << Tolerance << " )";
4758
4759   SMESH_CATCH( SMESH::throwCorbaException );
4760 }
4761
4762 //=======================================================================
4763 //function : FindCoincidentNodesOnPart
4764 //purpose  :
4765 //=======================================================================
4766
4767 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
4768                                                    CORBA::Double                  Tolerance,
4769                                                    SMESH::array_of_long_array_out GroupsOfNodes)
4770   throw (SALOME::SALOME_Exception)
4771 {
4772   SMESH_TRY;
4773   initData();
4774
4775   TIDSortedNodeSet nodes;
4776   prepareIdSource( theObject );
4777   idSourceToNodeSet( theObject, getMeshDS(), nodes );
4778
4779   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4780   if(!nodes.empty())
4781     getEditor().FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
4782
4783   GroupsOfNodes = new SMESH::array_of_long_array;
4784   GroupsOfNodes->length( aListOfListOfNodes.size() );
4785   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4786   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4787   {
4788     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4789     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4790     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
4791     aGroup.length( aListOfNodes.size() );
4792     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4793       aGroup[ j ] = (*lIt)->GetID();
4794   }
4795   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
4796                 <<theObject<<", "
4797                 << Tolerance << " )";
4798
4799   SMESH_CATCH( SMESH::throwCorbaException );
4800 }
4801
4802 //================================================================================
4803 /*!
4804  * \brief Finds nodes coinsident with Tolerance within Object excluding nodes within
4805  *        ExceptSubMeshOrGroups
4806  */
4807 //================================================================================
4808
4809 void SMESH_MeshEditor_i::
4810 FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
4811                              CORBA::Double                  theTolerance,
4812                              SMESH::array_of_long_array_out theGroupsOfNodes,
4813                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
4814   throw (SALOME::SALOME_Exception)
4815 {
4816   SMESH_TRY;
4817   initData();
4818
4819   TIDSortedNodeSet nodes;
4820   prepareIdSource( theObject );
4821   idSourceToNodeSet( theObject, getMeshDS(), nodes );
4822
4823   for ( int i = 0; i < theExceptSubMeshOrGroups.length(); ++i )
4824   {
4825     TIDSortedNodeSet exceptNodes;
4826     idSourceToNodeSet( theExceptSubMeshOrGroups[i], getMeshDS(), exceptNodes );
4827     TIDSortedNodeSet::iterator avoidNode = exceptNodes.begin();
4828     for ( ; avoidNode != exceptNodes.end(); ++avoidNode)
4829       nodes.erase( *avoidNode );
4830   }
4831   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4832   if(!nodes.empty())
4833     getEditor().FindCoincidentNodes( nodes, theTolerance, aListOfListOfNodes );
4834
4835   theGroupsOfNodes = new SMESH::array_of_long_array;
4836   theGroupsOfNodes->length( aListOfListOfNodes.size() );
4837   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
4838   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
4839   {
4840     list< const SMDS_MeshNode* >& aListOfNodes = *llIt;
4841     list< const SMDS_MeshNode* >::iterator lIt = aListOfNodes.begin();;
4842     SMESH::long_array& aGroup = (*theGroupsOfNodes)[ i ];
4843     aGroup.length( aListOfNodes.size() );
4844     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
4845       aGroup[ j ] = (*lIt)->GetID();
4846   }
4847   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPartBut( "
4848                 << theObject<<", "
4849                 << theTolerance << ", "
4850                 << theExceptSubMeshOrGroups << " )";
4851
4852   SMESH_CATCH( SMESH::throwCorbaException );
4853 }
4854
4855 //=======================================================================
4856 //function : MergeNodes
4857 //purpose  :
4858 //=======================================================================
4859
4860 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
4861   throw (SALOME::SALOME_Exception)
4862 {
4863   SMESH_TRY;
4864   initData();
4865
4866   SMESHDS_Mesh* aMesh = getMeshDS();
4867
4868   TPythonDump aTPythonDump;
4869   aTPythonDump << this << ".MergeNodes([";
4870   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
4871   for (int i = 0; i < GroupsOfNodes.length(); i++)
4872   {
4873     const SMESH::long_array& aNodeGroup = GroupsOfNodes[ i ];
4874     aListOfListOfNodes.push_back( list< const SMDS_MeshNode* >() );
4875     list< const SMDS_MeshNode* >& aListOfNodes = aListOfListOfNodes.back();
4876     for ( int j = 0; j < aNodeGroup.length(); j++ )
4877     {
4878       CORBA::Long index = aNodeGroup[ j ];
4879       const SMDS_MeshNode * node = aMesh->FindNode(index);
4880       if ( node )
4881         aListOfNodes.push_back( node );
4882     }
4883     if ( aListOfNodes.size() < 2 )
4884       aListOfListOfNodes.pop_back();
4885
4886     if ( i > 0 ) aTPythonDump << ", ";
4887     aTPythonDump << aNodeGroup;
4888   }
4889   getEditor().MergeNodes( aListOfListOfNodes );
4890
4891   aTPythonDump <<  "])";
4892
4893   declareMeshModified( /*isReComputeSafe=*/false );
4894
4895   SMESH_CATCH( SMESH::throwCorbaException );
4896 }
4897
4898 //=======================================================================
4899 //function : FindEqualElements
4900 //purpose  :
4901 //=======================================================================
4902
4903 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
4904                                            SMESH::array_of_long_array_out GroupsOfElementsID)
4905   throw (SALOME::SALOME_Exception)
4906 {
4907   SMESH_TRY;
4908   initData();
4909
4910   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
4911   if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
4912   {
4913     TIDSortedElemSet elems;
4914     prepareIdSource( theObject );
4915     idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true);
4916
4917     ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4918     getEditor().FindEqualElements( elems, aListOfListOfElementsID );
4919
4920     GroupsOfElementsID = new SMESH::array_of_long_array;
4921     GroupsOfElementsID->length( aListOfListOfElementsID.size() );
4922
4923     ::SMESH_MeshEditor::TListOfListOfElementsID::iterator arraysIt =
4924         aListOfListOfElementsID.begin();
4925     for (CORBA::Long j = 0; arraysIt != aListOfListOfElementsID.end(); ++arraysIt, ++j)
4926     {
4927       SMESH::long_array& aGroup = (*GroupsOfElementsID)[ j ];
4928       list<int>&      listOfIDs = *arraysIt;
4929       aGroup.length( listOfIDs.size() );
4930       list<int>::iterator idIt = listOfIDs.begin();
4931       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k )
4932         aGroup[ k ] = *idIt;
4933     }
4934
4935     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
4936                   <<theObject<<" )";
4937   }
4938
4939   SMESH_CATCH( SMESH::throwCorbaException );
4940 }
4941
4942 //=======================================================================
4943 //function : MergeElements
4944 //purpose  :
4945 //=======================================================================
4946
4947 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
4948   throw (SALOME::SALOME_Exception)
4949 {
4950   SMESH_TRY;
4951   initData();
4952
4953   TPythonDump aTPythonDump;
4954   aTPythonDump << this << ".MergeElements( [";
4955
4956   ::SMESH_MeshEditor::TListOfListOfElementsID aListOfListOfElementsID;
4957
4958   for (int i = 0; i < GroupsOfElementsID.length(); i++) {
4959     const SMESH::long_array& anElemsIDGroup = GroupsOfElementsID[ i ];
4960     aListOfListOfElementsID.push_back( list< int >() );
4961     list< int >& aListOfElemsID = aListOfListOfElementsID.back();
4962     for ( int j = 0; j < anElemsIDGroup.length(); j++ ) {
4963       CORBA::Long id = anElemsIDGroup[ j ];
4964       aListOfElemsID.push_back( id );
4965     }
4966     if ( aListOfElemsID.size() < 2 )
4967       aListOfListOfElementsID.pop_back();
4968     if ( i > 0 ) aTPythonDump << ", ";
4969     aTPythonDump << anElemsIDGroup;
4970   }
4971
4972   getEditor().MergeElements(aListOfListOfElementsID);
4973
4974   declareMeshModified( /*isReComputeSafe=*/true );
4975
4976   aTPythonDump << "] )";
4977
4978   SMESH_CATCH( SMESH::throwCorbaException );
4979 }
4980
4981 //=======================================================================
4982 //function : MergeEqualElements
4983 //purpose  :
4984 //=======================================================================
4985
4986 void SMESH_MeshEditor_i::MergeEqualElements()
4987   throw (SALOME::SALOME_Exception)
4988 {
4989   SMESH_TRY;
4990   initData();
4991
4992   getEditor().MergeEqualElements();
4993
4994   declareMeshModified( /*isReComputeSafe=*/true );
4995
4996   TPythonDump() << this << ".MergeEqualElements()";
4997
4998   SMESH_CATCH( SMESH::throwCorbaException );
4999 }
5000
5001 //=============================================================================
5002 /*!
5003  * Move the node to a given point
5004  */
5005 //=============================================================================
5006
5007 CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
5008                                             CORBA::Double x,
5009                                             CORBA::Double y,
5010                                             CORBA::Double z)
5011   throw (SALOME::SALOME_Exception)
5012 {
5013   SMESH_TRY;
5014   initData(/*deleteSearchers=*/false);
5015
5016   const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
5017   if ( !node )
5018     return false;
5019
5020   if ( theNodeSearcher )
5021     theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5022
5023   if ( myIsPreviewMode ) // make preview data
5024   {
5025     // in a preview mesh, make edges linked to a node
5026     TPreviewMesh& tmpMesh = *getPreviewMesh();
5027     TIDSortedElemSet linkedNodes;
5028     ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
5029     TIDSortedElemSet::iterator nIt = linkedNodes.begin();
5030     SMDS_MeshNode *nodeCpy1 = tmpMesh.Copy(node);
5031     for ( ; nIt != linkedNodes.end(); ++nIt )
5032     {
5033       SMDS_MeshNode *nodeCpy2 = tmpMesh.Copy ( cast2Node( *nIt ));
5034       tmpMesh.GetMeshDS()->AddEdge(nodeCpy1, nodeCpy2);
5035     }
5036     // move copied node
5037     if ( nodeCpy1 )
5038       tmpMesh.GetMeshDS()->MoveNode(nodeCpy1, x, y, z);
5039     // fill preview data
5040   }
5041   else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
5042     theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
5043   else
5044     getMeshDS()->MoveNode(node, x, y, z);
5045
5046   if ( !myIsPreviewMode )
5047   {
5048     // Update Python script
5049     TPythonDump() << "isDone = " << this << ".MoveNode( "
5050                   << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
5051     declareMeshModified( /*isReComputeSafe=*/false );
5052   }
5053
5054   SMESH_CATCH( SMESH::throwCorbaException );
5055
5056   return true;
5057 }
5058
5059 //================================================================================
5060 /*!
5061  * \brief Return ID of node closest to a given point
5062  */
5063 //================================================================================
5064
5065 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
5066                                                   CORBA::Double y,
5067                                                   CORBA::Double z)
5068   throw (SALOME::SALOME_Exception)
5069 {
5070   SMESH_TRY;
5071   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5072
5073   if ( !theNodeSearcher ) {
5074     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
5075   }
5076   gp_Pnt p( x,y,z );
5077   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
5078     return node->GetID();
5079
5080   SMESH_CATCH( SMESH::throwCorbaException );
5081   return 0;
5082 }
5083
5084 //================================================================================
5085 /*!
5086  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
5087  * move the node closest to the point to point's location and return ID of the node
5088  */
5089 //================================================================================
5090
5091 CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
5092                                                        CORBA::Double y,
5093                                                        CORBA::Double z,
5094                                                        CORBA::Long   theNodeID)
5095   throw (SALOME::SALOME_Exception)
5096 {
5097   SMESH_TRY;
5098   // We keep theNodeSearcher until any mesh modification:
5099   // 1) initData() deletes theNodeSearcher at any edition,
5100   // 2) TSearchersDeleter - at any mesh compute event and mesh change
5101
5102   initData(/*deleteSearchers=*/false);
5103
5104   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
5105
5106   int nodeID = theNodeID;
5107   const SMDS_MeshNode* node = getMeshDS()->FindNode( nodeID );
5108   if ( !node ) // preview moving node
5109   {
5110     if ( !theNodeSearcher ) {
5111       theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
5112     }
5113     gp_Pnt p( x,y,z );
5114     node = theNodeSearcher->FindClosestTo( p );
5115   }
5116   if ( node ) {
5117     nodeID = node->GetID();
5118     if ( myIsPreviewMode ) // make preview data
5119     {
5120       // in a preview mesh, make edges linked to a node
5121       TPreviewMesh tmpMesh = *getPreviewMesh();
5122       TIDSortedElemSet linkedNodes;
5123       ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
5124       TIDSortedElemSet::iterator nIt = linkedNodes.begin();
5125       for ( ; nIt != linkedNodes.end(); ++nIt )
5126       {
5127         SMDS_LinearEdge edge( node, cast2Node( *nIt ));
5128         tmpMesh.Copy( &edge );
5129       }
5130       // move copied node
5131       node = tmpMesh.GetMeshDS()->FindNode( nodeID );
5132       if ( node )
5133         tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
5134       // fill preview data
5135     }
5136     else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
5137     {
5138       theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
5139     }
5140     else
5141     {
5142       getMeshDS()->MoveNode(node, x, y, z);
5143     }
5144   }
5145
5146   if ( !myIsPreviewMode )
5147   {
5148     TPythonDump() << "nodeID = " << this
5149                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
5150                   << ", " << nodeID << " )";
5151
5152     declareMeshModified( /*isReComputeSafe=*/false );
5153   }
5154
5155   return nodeID;
5156
5157   SMESH_CATCH( SMESH::throwCorbaException );
5158   return 0;
5159 }
5160
5161 //=======================================================================
5162 /*!
5163  * Return elements of given type where the given point is IN or ON.
5164  *
5165  * 'ALL' type means elements of any type excluding nodes
5166  */
5167 //=======================================================================
5168
5169 SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
5170                                                            CORBA::Double      y,
5171                                                            CORBA::Double      z,
5172                                                            SMESH::ElementType type)
5173   throw (SALOME::SALOME_Exception)
5174 {
5175   SMESH_TRY;
5176   SMESH::long_array_var res = new SMESH::long_array;
5177   vector< const SMDS_MeshElement* > foundElems;
5178
5179   theSearchersDeleter.Set( myMesh );
5180   if ( !theElementSearcher ) {
5181     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
5182   }
5183   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
5184                                            SMDSAbs_ElementType( type ),
5185                                            foundElems);
5186   res->length( foundElems.size() );
5187   for ( int i = 0; i < foundElems.size(); ++i )
5188     res[i] = foundElems[i]->GetID();
5189
5190   if ( !myIsPreviewMode ) // call from tui
5191     TPythonDump() << "res = " << this << ".FindElementsByPoint( "
5192                   << x << ", "
5193                   << y << ", "
5194                   << z << ", "
5195                   << type << " )";
5196
5197   return res._retn();
5198
5199   SMESH_CATCH( SMESH::throwCorbaException );
5200   return 0;
5201 }
5202
5203 //=======================================================================
5204 //function : FindAmongElementsByPoint
5205 //purpose  : Searching among the given elements, return elements of given type 
5206 //           where the given point is IN or ON.
5207 //           'ALL' type means elements of any type excluding nodes
5208 //=======================================================================
5209
5210 SMESH::long_array*
5211 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
5212                                              CORBA::Double             x,
5213                                              CORBA::Double             y,
5214                                              CORBA::Double             z,
5215                                              SMESH::ElementType        type)
5216   throw (SALOME::SALOME_Exception)
5217 {
5218   SMESH_TRY;
5219   SMESH::long_array_var res = new SMESH::long_array;
5220   
5221   SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
5222   if ( types->length() == 1 && // a part contains only nodes or 0D elements
5223        ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
5224        type != types[0] ) // but search of elements of dim > 0
5225     return res._retn();
5226
5227   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
5228     return FindElementsByPoint( x,y,z, type );
5229
5230   TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
5231
5232   theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
5233   if ( !theElementSearcher )
5234   {
5235     // create a searcher from elementIDs
5236     SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
5237     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
5238
5239     if ( !idSourceToSet( elementIDs, meshDS, elements,
5240                          SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
5241       return res._retn();
5242
5243     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5244     SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
5245
5246     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
5247   }
5248
5249   vector< const SMDS_MeshElement* > foundElems;
5250
5251   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
5252                                            SMDSAbs_ElementType( type ),
5253                                            foundElems);
5254   res->length( foundElems.size() );
5255   for ( int i = 0; i < foundElems.size(); ++i )
5256     res[i] = foundElems[i]->GetID();
5257
5258   if ( !myIsPreviewMode ) // call from tui
5259     TPythonDump() << "res = " << this << ".FindAmongElementsByPoint( "
5260                   << elementIDs << ", "
5261                   << x << ", "
5262                   << y << ", "
5263                   << z << ", "
5264                   << type << " )";
5265
5266   return res._retn();
5267
5268   SMESH_CATCH( SMESH::throwCorbaException );
5269   return 0;
5270 }
5271
5272 //=======================================================================
5273 //function : GetPointState
5274 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
5275 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
5276 //=======================================================================
5277
5278 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
5279                                                CORBA::Double y,
5280                                                CORBA::Double z)
5281   throw (SALOME::SALOME_Exception)
5282 {
5283   SMESH_TRY;
5284   theSearchersDeleter.Set( myMesh );
5285   if ( !theElementSearcher ) {
5286     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
5287   }
5288   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
5289
5290   SMESH_CATCH( SMESH::throwCorbaException );
5291   return 0;
5292 }
5293
5294 //=======================================================================
5295 //function : convError
5296 //purpose  :
5297 //=======================================================================
5298
5299 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5300
5301 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5302 {
5303   switch ( e ) {
5304     RETCASE( SEW_OK );
5305     RETCASE( SEW_BORDER1_NOT_FOUND );
5306     RETCASE( SEW_BORDER2_NOT_FOUND );
5307     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5308     RETCASE( SEW_BAD_SIDE_NODES );
5309     RETCASE( SEW_VOLUMES_TO_SPLIT );
5310     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5311     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5312     RETCASE( SEW_BAD_SIDE1_NODES );
5313     RETCASE( SEW_BAD_SIDE2_NODES );
5314   }
5315   return SMESH::SMESH_MeshEditor::SEW_OK;
5316 }
5317
5318 //=======================================================================
5319 //function : SewFreeBorders
5320 //purpose  :
5321 //=======================================================================
5322
5323 SMESH::SMESH_MeshEditor::Sew_Error
5324 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5325                                    CORBA::Long SecondNodeID1,
5326                                    CORBA::Long LastNodeID1,
5327                                    CORBA::Long FirstNodeID2,
5328                                    CORBA::Long SecondNodeID2,
5329                                    CORBA::Long LastNodeID2,
5330                                    CORBA::Boolean CreatePolygons,
5331                                    CORBA::Boolean CreatePolyedrs)
5332   throw (SALOME::SALOME_Exception)
5333 {
5334   SMESH_TRY;
5335   initData();
5336
5337   SMESHDS_Mesh* aMesh = getMeshDS();
5338
5339   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5340   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5341   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5342   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5343   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5344   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
5345
5346   if (!aBorderFirstNode ||
5347       !aBorderSecondNode||
5348       !aBorderLastNode)
5349     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5350   if (!aSide2FirstNode  ||
5351       !aSide2SecondNode ||
5352       !aSide2ThirdNode)
5353     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5354
5355   TPythonDump() << "error = " << this << ".SewFreeBorders( "
5356                 << FirstNodeID1  << ", "
5357                 << SecondNodeID1 << ", "
5358                 << LastNodeID1   << ", "
5359                 << FirstNodeID2  << ", "
5360                 << SecondNodeID2 << ", "
5361                 << LastNodeID2   << ", "
5362                 << CreatePolygons<< ", "
5363                 << CreatePolyedrs<< " )";
5364
5365   SMESH::SMESH_MeshEditor::Sew_Error error =
5366     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5367                                        aBorderSecondNode,
5368                                        aBorderLastNode,
5369                                        aSide2FirstNode,
5370                                        aSide2SecondNode,
5371                                        aSide2ThirdNode,
5372                                        true,
5373                                        CreatePolygons,
5374                                        CreatePolyedrs) );
5375
5376
5377   declareMeshModified( /*isReComputeSafe=*/false );
5378   return error;
5379
5380   SMESH_CATCH( SMESH::throwCorbaException );
5381   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5382 }
5383
5384
5385 //=======================================================================
5386 //function : SewConformFreeBorders
5387 //purpose  :
5388 //=======================================================================
5389
5390 SMESH::SMESH_MeshEditor::Sew_Error
5391 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5392                                           CORBA::Long SecondNodeID1,
5393                                           CORBA::Long LastNodeID1,
5394                                           CORBA::Long FirstNodeID2,
5395                                           CORBA::Long SecondNodeID2)
5396   throw (SALOME::SALOME_Exception)
5397 {
5398   SMESH_TRY;
5399   initData();
5400
5401   SMESHDS_Mesh* aMesh = getMeshDS();
5402
5403   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5404   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5405   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5406   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5407   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5408   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5409
5410   if (!aBorderFirstNode ||
5411       !aBorderSecondNode||
5412       !aBorderLastNode )
5413     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5414   if (!aSide2FirstNode  ||
5415       !aSide2SecondNode)
5416     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5417
5418   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5419                 << FirstNodeID1  << ", "
5420                 << SecondNodeID1 << ", "
5421                 << LastNodeID1   << ", "
5422                 << FirstNodeID2  << ", "
5423                 << SecondNodeID2 << " )";
5424
5425   SMESH::SMESH_MeshEditor::Sew_Error error =
5426     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5427                                        aBorderSecondNode,
5428                                        aBorderLastNode,
5429                                        aSide2FirstNode,
5430                                        aSide2SecondNode,
5431                                        aSide2ThirdNode,
5432                                        true,
5433                                        false, false) );
5434
5435   declareMeshModified( /*isReComputeSafe=*/false );
5436   return error;
5437
5438   SMESH_CATCH( SMESH::throwCorbaException );
5439   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5440 }
5441
5442
5443 //=======================================================================
5444 //function : SewBorderToSide
5445 //purpose  :
5446 //=======================================================================
5447
5448 SMESH::SMESH_MeshEditor::Sew_Error
5449 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5450                                     CORBA::Long SecondNodeIDOnFreeBorder,
5451                                     CORBA::Long LastNodeIDOnFreeBorder,
5452                                     CORBA::Long FirstNodeIDOnSide,
5453                                     CORBA::Long LastNodeIDOnSide,
5454                                     CORBA::Boolean CreatePolygons,
5455                                     CORBA::Boolean CreatePolyedrs)
5456   throw (SALOME::SALOME_Exception)
5457 {
5458   SMESH_TRY;
5459   initData();
5460
5461   SMESHDS_Mesh* aMesh = getMeshDS();
5462
5463   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
5464   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5465   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
5466   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
5467   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
5468   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5469
5470   if (!aBorderFirstNode ||
5471       !aBorderSecondNode||
5472       !aBorderLastNode  )
5473     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5474   if (!aSide2FirstNode  ||
5475       !aSide2SecondNode)
5476     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5477
5478   TPythonDump() << "error = " << this << ".SewBorderToSide( "
5479                 << FirstNodeIDOnFreeBorder  << ", "
5480                 << SecondNodeIDOnFreeBorder << ", "
5481                 << LastNodeIDOnFreeBorder   << ", "
5482                 << FirstNodeIDOnSide        << ", "
5483                 << LastNodeIDOnSide         << ", "
5484                 << CreatePolygons           << ", "
5485                 << CreatePolyedrs           << ") ";
5486
5487   SMESH::SMESH_MeshEditor::Sew_Error error =
5488     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5489                                        aBorderSecondNode,
5490                                        aBorderLastNode,
5491                                        aSide2FirstNode,
5492                                        aSide2SecondNode,
5493                                        aSide2ThirdNode,
5494                                        false,
5495                                        CreatePolygons,
5496                                        CreatePolyedrs) );
5497
5498   declareMeshModified( /*isReComputeSafe=*/false );
5499   return error;
5500
5501   SMESH_CATCH( SMESH::throwCorbaException );
5502   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5503 }
5504
5505
5506 //=======================================================================
5507 //function : SewSideElements
5508 //purpose  :
5509 //=======================================================================
5510
5511 SMESH::SMESH_MeshEditor::Sew_Error
5512 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5513                                     const SMESH::long_array& IDsOfSide2Elements,
5514                                     CORBA::Long NodeID1OfSide1ToMerge,
5515                                     CORBA::Long NodeID1OfSide2ToMerge,
5516                                     CORBA::Long NodeID2OfSide1ToMerge,
5517                                     CORBA::Long NodeID2OfSide2ToMerge)
5518   throw (SALOME::SALOME_Exception)
5519 {
5520   SMESH_TRY;
5521   initData();
5522
5523   SMESHDS_Mesh* aMesh = getMeshDS();
5524
5525   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
5526   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
5527   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5528   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5529
5530   if (!aFirstNode1ToMerge ||
5531       !aFirstNode2ToMerge )
5532     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5533   if (!aSecondNode1ToMerge||
5534       !aSecondNode2ToMerge)
5535     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5536
5537   TIDSortedElemSet aSide1Elems, aSide2Elems;
5538   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5539   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5540
5541   TPythonDump() << "error = " << this << ".SewSideElements( "
5542                 << IDsOfSide1Elements << ", "
5543                 << IDsOfSide2Elements << ", "
5544                 << NodeID1OfSide1ToMerge << ", "
5545                 << NodeID1OfSide2ToMerge << ", "
5546                 << NodeID2OfSide1ToMerge << ", "
5547                 << NodeID2OfSide2ToMerge << ")";
5548
5549   SMESH::SMESH_MeshEditor::Sew_Error error =
5550     convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5551                                          aFirstNode1ToMerge,
5552                                          aFirstNode2ToMerge,
5553                                          aSecondNode1ToMerge,
5554                                          aSecondNode2ToMerge));
5555
5556   declareMeshModified( /*isReComputeSafe=*/false );
5557   return error;
5558
5559   SMESH_CATCH( SMESH::throwCorbaException );
5560   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5561 }
5562
5563 //================================================================================
5564 /*!
5565  * \brief Set new nodes for given element
5566  * \param ide - element id
5567  * \param newIDs - new node ids
5568  * \retval CORBA::Boolean - true if result is OK
5569  */
5570 //================================================================================
5571
5572 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5573                                                    const SMESH::long_array& newIDs)
5574   throw (SALOME::SALOME_Exception)
5575 {
5576   SMESH_TRY;
5577   initData();
5578
5579   const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5580   if(!elem) return false;
5581
5582   int nbn = newIDs.length();
5583   int i=0;
5584   vector<const SMDS_MeshNode*> aNodes(nbn);
5585   int nbn1=-1;
5586   for(; i<nbn; i++) {
5587     const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5588     if(aNode) {
5589       nbn1++;
5590       aNodes[nbn1] = aNode;
5591     }
5592   }
5593   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5594                 << ide << ", " << newIDs << " )";
5595
5596   MESSAGE("ChangeElementNodes");
5597   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5598
5599   declareMeshModified( /*isReComputeSafe=*/ !res );
5600
5601   return res;
5602
5603   SMESH_CATCH( SMESH::throwCorbaException );
5604   return 0;
5605 }
5606
5607 //=======================================================================
5608 /*!
5609  * \brief Makes a part of the mesh quadratic or bi-quadratic
5610  */
5611 //=======================================================================
5612
5613 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean            theForce3d,
5614                                             CORBA::Boolean            theToBiQuad,
5615                                             SMESH::SMESH_IDSource_ptr theObject)
5616   throw (SALOME::SALOME_Exception)
5617 {
5618   SMESH_TRY;
5619   TIDSortedElemSet elems;
5620   bool elemsOK;
5621   if ( !( elemsOK = CORBA::is_nil( theObject )))
5622   {
5623     prepareIdSource( theObject );
5624     elemsOK =  idSourceToSet( theObject, getMeshDS(), elems,
5625                               SMDSAbs_All, /*emptyIfIsMesh=*/true );
5626   }
5627   if ( elemsOK )
5628   {
5629     if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5630       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5631
5632     if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5633     else                 getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5634
5635     declareMeshModified( /*isReComputeSafe=*/false );
5636   }
5637
5638   SMESH_CATCH( SMESH::throwCorbaException );
5639 }
5640
5641 //=======================================================================
5642 //function : ConvertFromQuadratic
5643 //purpose  :
5644 //=======================================================================
5645
5646 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5647   throw (SALOME::SALOME_Exception)
5648 {
5649   CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5650   TPythonDump() << this << ".ConvertFromQuadratic()";
5651   declareMeshModified( /*isReComputeSafe=*/!isDone );
5652   return isDone;
5653 }
5654
5655 //=======================================================================
5656 //function : ConvertToQuadratic
5657 //purpose  :
5658 //=======================================================================
5659
5660 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5661   throw (SALOME::SALOME_Exception)
5662 {
5663   convertToQuadratic( theForce3d, false );
5664   TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5665 }
5666
5667 //================================================================================
5668 /*!
5669  * \brief Makes a part of the mesh quadratic
5670  */
5671 //================================================================================
5672
5673 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theForce3d,
5674                                                   SMESH::SMESH_IDSource_ptr theObject)
5675   throw (SALOME::SALOME_Exception)
5676 {
5677   convertToQuadratic( theForce3d, false, theObject );
5678   TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5679 }
5680
5681 //================================================================================
5682 /*!
5683  * \brief Makes a part of the mesh bi-quadratic
5684  */
5685 //================================================================================
5686
5687 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean            theForce3d,
5688                                               SMESH::SMESH_IDSource_ptr theObject)
5689   throw (SALOME::SALOME_Exception)
5690 {
5691   convertToQuadratic( theForce3d, true, theObject );
5692   TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5693 }
5694
5695 //================================================================================
5696 /*!
5697  * \brief Makes a part of the mesh linear
5698  */
5699 //================================================================================
5700
5701 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5702   throw (SALOME::SALOME_Exception)
5703 {
5704   SMESH_TRY;
5705
5706   TPythonDump pyDump;
5707
5708   TIDSortedElemSet elems;
5709   prepareIdSource( theObject );
5710   if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5711   {
5712     if ( elems.empty() )
5713     {
5714       ConvertFromQuadratic();
5715     }
5716     else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5717     {
5718       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5719     }
5720     else
5721     {
5722       getEditor().ConvertFromQuadratic(elems);
5723     }
5724   }
5725   declareMeshModified( /*isReComputeSafe=*/false );
5726
5727   pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5728
5729   SMESH_CATCH( SMESH::throwCorbaException );
5730 }
5731
5732 //=======================================================================
5733 //function : makeMesh
5734 //purpose  : create a named imported mesh
5735 //=======================================================================
5736
5737 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5738 {
5739   SMESH_Gen_i*              gen = SMESH_Gen_i::GetSMESHGen();
5740   SMESH::SMESH_Mesh_var    mesh = gen->CreateEmptyMesh();
5741   SALOMEDS::Study_var     study = gen->GetCurrentStudy();
5742   SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5743   gen->SetName( meshSO, theMeshName, "Mesh" );
5744   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5745
5746   return mesh._retn();
5747 }
5748
5749 //=======================================================================
5750 //function : dumpGroupsList
5751 //purpose  :
5752 //=======================================================================
5753
5754 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPython,
5755                                         const SMESH::ListOfGroups * theGroupList)
5756 {
5757   bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5758   if ( isDumpGroupList )
5759     theDumpPython << theGroupList << " = ";
5760 }
5761
5762 //================================================================================
5763 /*!
5764   \brief Generates the unique group name.
5765   \param thePrefix name prefix
5766   \return unique name
5767 */
5768 //================================================================================
5769
5770 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5771 {
5772   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5773   set<string> groupNames;
5774
5775   // Get existing group names
5776   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5777     SMESH::SMESH_GroupBase_var aGroup = groups[i];
5778     if (CORBA::is_nil(aGroup))
5779       continue;
5780
5781     CORBA::String_var name = aGroup->GetName();
5782     groupNames.insert( name.in() );
5783   }
5784
5785   // Find new name
5786   string name = thePrefix;
5787   int index = 0;
5788
5789   while (!groupNames.insert(name).second)
5790     name = SMESH_Comment( thePrefix ) << "_" << index++;
5791
5792   return name;
5793 }
5794
5795 //================================================================================
5796 /*!
5797  * \brief Prepare SMESH_IDSource for work
5798  */
5799 //================================================================================
5800
5801 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5802 {
5803   if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5804   {
5805     SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5806     filter->SetMesh( mesh );
5807   }
5808 }
5809
5810 //================================================================================
5811 /*!
5812  * \brief Duplicates given elements, i.e. creates new elements based on the 
5813  *        same nodes as the given ones.
5814  * \param theElements - container of elements to duplicate.
5815  * \param theGroupName - a name of group to contain the generated elements.
5816  *                    If a group with such a name already exists, the new elements
5817  *                    are added to the existng group, else a new group is created.
5818  *                    If \a theGroupName is empty, new elements are not added 
5819  *                    in any group.
5820  * \return a group where the new elements are added. NULL if theGroupName == "".
5821  * \sa DoubleNode()
5822  */
5823 //================================================================================
5824
5825 SMESH::SMESH_Group_ptr
5826 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5827                                    const char*               theGroupName)
5828   throw (SALOME::SALOME_Exception)
5829 {
5830   SMESH::SMESH_Group_var newGroup;
5831
5832   SMESH_TRY;
5833   initData();
5834
5835   TPythonDump pyDump;
5836
5837   TIDSortedElemSet elems;
5838   prepareIdSource( theElements );
5839   if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5840   {
5841     getEditor().DoubleElements( elems );
5842
5843     if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5844     {
5845       // group type
5846       SMESH::ElementType type =
5847         SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5848       // find existing group
5849       SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5850       for ( size_t i = 0; i < groups->length(); ++i )
5851         if ( groups[i]->GetType() == type )
5852         {
5853           CORBA::String_var name = groups[i]->GetName();
5854           if ( strcmp( name, theGroupName ) == 0 ) {
5855             newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5856             break;
5857           }
5858         }
5859       // create a new group
5860       if ( newGroup->_is_nil() )
5861         newGroup = myMesh_i->CreateGroup( type, theGroupName );
5862       // fill newGroup
5863       if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5864       {
5865         SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5866         const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5867         for ( int i = 1; i <= aSeq.Length(); i++ )
5868           groupDS->SMDSGroup().Add( aSeq(i) );
5869       }
5870     }
5871   }
5872   // python dump
5873   if ( !newGroup->_is_nil() )
5874     pyDump << newGroup << " = ";
5875   pyDump << this << ".DoubleElements( "
5876          << theElements << ", " << "'" << theGroupName <<"')";
5877
5878   SMESH_CATCH( SMESH::throwCorbaException );
5879
5880   return newGroup._retn();
5881 }
5882
5883 //================================================================================
5884 /*!
5885   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5886   \param theNodes - identifiers of nodes to be doubled
5887   \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5888          nodes. If list of element identifiers is empty then nodes are doubled but
5889          they not assigned to elements
5890   \return TRUE if operation has been completed successfully, FALSE otherwise
5891   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5892 */
5893 //================================================================================
5894
5895 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5896                                                 const SMESH::long_array& theModifiedElems )
5897   throw (SALOME::SALOME_Exception)
5898 {
5899   SMESH_TRY;
5900   initData();
5901
5902   list< int > aListOfNodes;
5903   int i, n;
5904   for ( i = 0, n = theNodes.length(); i < n; i++ )
5905     aListOfNodes.push_back( theNodes[ i ] );
5906
5907   list< int > aListOfElems;
5908   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5909     aListOfElems.push_back( theModifiedElems[ i ] );
5910
5911   bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5912
5913   declareMeshModified( /*isReComputeSafe=*/ !aResult );
5914
5915   // Update Python script
5916   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5917
5918   return aResult;
5919
5920   SMESH_CATCH( SMESH::throwCorbaException );
5921   return 0;
5922 }
5923
5924 //================================================================================
5925 /*!
5926   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5927   This method provided for convenience works as DoubleNodes() described above.
5928   \param theNodeId - identifier of node to be doubled.
5929   \param theModifiedElems - identifiers of elements to be updated.
5930   \return TRUE if operation has been completed successfully, FALSE otherwise
5931   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5932 */
5933 //================================================================================
5934
5935 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
5936                                                const SMESH::long_array& theModifiedElems )
5937   throw (SALOME::SALOME_Exception)
5938 {
5939   SMESH_TRY;
5940   SMESH::long_array_var aNodes = new SMESH::long_array;
5941   aNodes->length( 1 );
5942   aNodes[ 0 ] = theNodeId;
5943
5944   TPythonDump pyDump; // suppress dump by the next line
5945
5946   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5947
5948   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
5949
5950   return done;
5951
5952   SMESH_CATCH( SMESH::throwCorbaException );
5953   return 0;
5954 }
5955
5956 //================================================================================
5957 /*!
5958   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5959   This method provided for convenience works as DoubleNodes() described above.
5960   \param theNodes - group of nodes to be doubled.
5961   \param theModifiedElems - group of elements to be updated.
5962   \return TRUE if operation has been completed successfully, FALSE otherwise
5963   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
5964 */
5965 //================================================================================
5966
5967 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
5968                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
5969   throw (SALOME::SALOME_Exception)
5970 {
5971   SMESH_TRY;
5972   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
5973     return false;
5974
5975   SMESH::long_array_var aNodes = theNodes->GetListOfID();
5976   SMESH::long_array_var aModifiedElems;
5977   if ( !CORBA::is_nil( theModifiedElems ) )
5978     aModifiedElems = theModifiedElems->GetListOfID();
5979   else
5980   {
5981     aModifiedElems = new SMESH::long_array;
5982     aModifiedElems->length( 0 );
5983   }
5984
5985   TPythonDump pyDump; // suppress dump by the next line
5986
5987   bool done = DoubleNodes( aNodes, aModifiedElems );
5988
5989   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
5990
5991   return done;
5992
5993   SMESH_CATCH( SMESH::throwCorbaException );
5994   return 0;
5995 }
5996
5997 //================================================================================
5998 /*!
5999  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6000  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6001  * \param theNodes - group of nodes to be doubled.
6002  * \param theModifiedElems - group of elements to be updated.
6003  * \return a new group with newly created nodes
6004  * \sa DoubleNodeGroup()
6005  */
6006 //================================================================================
6007
6008 SMESH::SMESH_Group_ptr
6009 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6010                                         SMESH::SMESH_GroupBase_ptr theModifiedElems )
6011   throw (SALOME::SALOME_Exception)
6012 {
6013   SMESH_TRY;
6014   SMESH::SMESH_Group_var aNewGroup;
6015
6016   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6017     return aNewGroup._retn();
6018
6019   // Duplicate nodes
6020   SMESH::long_array_var aNodes = theNodes->GetListOfID();
6021   SMESH::long_array_var aModifiedElems;
6022   if ( !CORBA::is_nil( theModifiedElems ) )
6023     aModifiedElems = theModifiedElems->GetListOfID();
6024   else {
6025     aModifiedElems = new SMESH::long_array;
6026     aModifiedElems->length( 0 );
6027   }
6028
6029   TPythonDump pyDump; // suppress dump by the next line
6030
6031   bool aResult = DoubleNodes( aNodes, aModifiedElems );
6032   if ( aResult )
6033   {
6034     // Create group with newly created nodes
6035     SMESH::long_array_var anIds = GetLastCreatedNodes();
6036     if (anIds->length() > 0) {
6037       string anUnindexedName (theNodes->GetName());
6038       string aNewName = generateGroupName(anUnindexedName + "_double");
6039       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6040       aNewGroup->Add(anIds);
6041       pyDump << aNewGroup << " = ";
6042     }
6043   }
6044
6045   pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6046          << theModifiedElems << " )";
6047
6048   return aNewGroup._retn();
6049
6050   SMESH_CATCH( SMESH::throwCorbaException );
6051   return 0;
6052 }
6053
6054 //================================================================================
6055 /*!
6056   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6057   This method provided for convenience works as DoubleNodes() described above.
6058   \param theNodes - list of groups of nodes to be doubled
6059   \param theModifiedElems - list of groups of elements to be updated.
6060   \return TRUE if operation has been completed successfully, FALSE otherwise
6061   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6062 */
6063 //================================================================================
6064
6065 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6066                                                     const SMESH::ListOfGroups& theModifiedElems )
6067   throw (SALOME::SALOME_Exception)
6068 {
6069   SMESH_TRY;
6070   initData();
6071
6072   std::list< int > aNodes;
6073   int i, n, j, m;
6074   for ( i = 0, n = theNodes.length(); i < n; i++ )
6075   {
6076     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6077     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6078     {
6079       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6080       for ( j = 0, m = aCurr->length(); j < m; j++ )
6081         aNodes.push_back( aCurr[ j ] );
6082     }
6083   }
6084
6085   std::list< int > anElems;
6086   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6087   {
6088     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6089     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6090     {
6091       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6092       for ( j = 0, m = aCurr->length(); j < m; j++ )
6093         anElems.push_back( aCurr[ j ] );
6094     }
6095   }
6096
6097   bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6098
6099   declareMeshModified( /*isReComputeSafe=*/false );
6100
6101   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6102
6103   return aResult;
6104
6105   SMESH_CATCH( SMESH::throwCorbaException );
6106   return 0;
6107 }
6108
6109 //================================================================================
6110 /*!
6111  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6112  * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6113  * \param theNodes - group of nodes to be doubled.
6114  * \param theModifiedElems - group of elements to be updated.
6115  * \return a new group with newly created nodes
6116  * \sa DoubleNodeGroups()
6117  */
6118 //================================================================================
6119
6120 SMESH::SMESH_Group_ptr
6121 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6122                                          const SMESH::ListOfGroups& theModifiedElems )
6123   throw (SALOME::SALOME_Exception)
6124 {
6125   SMESH::SMESH_Group_var aNewGroup;
6126
6127   TPythonDump pyDump; // suppress dump by the next line
6128
6129   bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6130
6131   if ( aResult )
6132   {
6133     // Create group with newly created nodes
6134     SMESH::long_array_var anIds = GetLastCreatedNodes();
6135     if (anIds->length() > 0) {
6136       string anUnindexedName (theNodes[0]->GetName());
6137       string aNewName = generateGroupName(anUnindexedName + "_double");
6138       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6139       aNewGroup->Add(anIds);
6140       pyDump << aNewGroup << " = ";
6141     }
6142   }
6143
6144   pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6145          << theModifiedElems << " )";
6146
6147   return aNewGroup._retn();
6148 }
6149
6150
6151 //================================================================================
6152 /*!
6153   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6154   \param theElems - the list of elements (edges or faces) to be replicated
6155   The nodes for duplication could be found from these elements
6156   \param theNodesNot - list of nodes to NOT replicate
6157   \param theAffectedElems - the list of elements (cells and edges) to which the
6158   replicated nodes should be associated to.
6159   \return TRUE if operation has been completed successfully, FALSE otherwise
6160   \sa DoubleNodeGroup(), DoubleNodeGroups()
6161 */
6162 //================================================================================
6163
6164 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6165                                                    const SMESH::long_array& theNodesNot,
6166                                                    const SMESH::long_array& theAffectedElems )
6167   throw (SALOME::SALOME_Exception)
6168 {
6169   SMESH_TRY;
6170   initData();
6171
6172   SMESHDS_Mesh* aMeshDS = getMeshDS();
6173   TIDSortedElemSet anElems, aNodes, anAffected;
6174   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6175   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6176   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6177
6178   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6179
6180   // Update Python script
6181   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6182                 << theNodesNot << ", " << theAffectedElems << " )";
6183
6184   declareMeshModified( /*isReComputeSafe=*/false );
6185   return aResult;
6186
6187   SMESH_CATCH( SMESH::throwCorbaException );
6188   return 0;
6189 }
6190
6191 //================================================================================
6192 /*!
6193   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6194   \param theElems - the list of elements (edges or faces) to be replicated
6195   The nodes for duplication could be found from these elements
6196   \param theNodesNot - list of nodes to NOT replicate
6197   \param theShape - shape to detect affected elements (element which geometric center
6198   located on or inside shape).
6199   The replicated nodes should be associated to affected elements.
6200   \return TRUE if operation has been completed successfully, FALSE otherwise
6201   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6202 */
6203 //================================================================================
6204
6205 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6206                                                             const SMESH::long_array& theNodesNot,
6207                                                             GEOM::GEOM_Object_ptr    theShape )
6208   throw (SALOME::SALOME_Exception)
6209 {
6210   SMESH_TRY;
6211   initData();
6212
6213
6214   SMESHDS_Mesh* aMeshDS = getMeshDS();
6215   TIDSortedElemSet anElems, aNodes;
6216   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6217   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6218
6219   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6220   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6221
6222   // Update Python script
6223   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6224                 << theNodesNot << ", " << theShape << " )";
6225
6226   declareMeshModified( /*isReComputeSafe=*/false );
6227   return aResult;
6228
6229   SMESH_CATCH( SMESH::throwCorbaException );
6230   return 0;
6231 }
6232
6233 //================================================================================
6234 /*!
6235   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6236   \param theElems - group of of elements (edges or faces) to be replicated
6237   \param theNodesNot - group of nodes not to replicated
6238   \param theAffectedElems - group of elements to which the replicated nodes
6239   should be associated to.
6240   \return TRUE if operation has been completed successfully, FALSE otherwise
6241   \sa DoubleNodes(), DoubleNodeGroups()
6242 */
6243 //================================================================================
6244
6245 CORBA::Boolean
6246 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6247                                         SMESH::SMESH_GroupBase_ptr theNodesNot,
6248                                         SMESH::SMESH_GroupBase_ptr theAffectedElems)
6249   throw (SALOME::SALOME_Exception)
6250 {
6251   SMESH_TRY;
6252   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6253     return false;
6254
6255   initData();
6256
6257
6258   SMESHDS_Mesh* aMeshDS = getMeshDS();
6259   TIDSortedElemSet anElems, aNodes, anAffected;
6260   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6261   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6262   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6263
6264   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6265
6266   // Update Python script
6267   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6268                 << theNodesNot << ", " << theAffectedElems << " )";
6269
6270   declareMeshModified( /*isReComputeSafe=*/false );
6271   return aResult;
6272
6273   SMESH_CATCH( SMESH::throwCorbaException );
6274   return 0;
6275 }
6276
6277 //================================================================================
6278 /*!
6279  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6280  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6281  * \param theElems - group of of elements (edges or faces) to be replicated
6282  * \param theNodesNot - group of nodes not to replicated
6283  * \param theAffectedElems - group of elements to which the replicated nodes
6284  *        should be associated to.
6285  * \return a new group with newly created elements
6286  * \sa DoubleNodeElemGroup()
6287  */
6288 //================================================================================
6289
6290 SMESH::SMESH_Group_ptr
6291 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6292                                            SMESH::SMESH_GroupBase_ptr theNodesNot,
6293                                            SMESH::SMESH_GroupBase_ptr theAffectedElems)
6294   throw (SALOME::SALOME_Exception)
6295 {
6296   TPythonDump pyDump;
6297   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6298                                                                theNodesNot,
6299                                                                theAffectedElems,
6300                                                                true, false );
6301   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6302   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6303
6304   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6305          << theElems         << ", "
6306          << theNodesNot      << ", "
6307          << theAffectedElems << " )";
6308
6309   return elemGroup._retn();
6310 }
6311
6312 //================================================================================
6313 /*!
6314  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6315  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6316  * \param theElems - group of of elements (edges or faces) to be replicated
6317  * \param theNodesNot - group of nodes not to replicated
6318  * \param theAffectedElems - group of elements to which the replicated nodes
6319  *        should be associated to.
6320  * \return a new group with newly created elements
6321  * \sa DoubleNodeElemGroup()
6322  */
6323 //================================================================================
6324
6325 SMESH::ListOfGroups*
6326 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6327                                             SMESH::SMESH_GroupBase_ptr theNodesNot,
6328                                             SMESH::SMESH_GroupBase_ptr theAffectedElems,
6329                                             CORBA::Boolean             theElemGroupNeeded,
6330                                             CORBA::Boolean             theNodeGroupNeeded)
6331   throw (SALOME::SALOME_Exception)
6332 {
6333   SMESH_TRY;
6334   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6335   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6336   aTwoGroups->length( 2 );
6337
6338   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6339     return aTwoGroups._retn();
6340
6341   initData();
6342
6343
6344   SMESHDS_Mesh* aMeshDS = getMeshDS();
6345   TIDSortedElemSet anElems, aNodes, anAffected;
6346   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6347   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6348   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6349
6350
6351   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6352
6353   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6354
6355   TPythonDump pyDump;
6356
6357   if ( aResult )
6358   {
6359     // Create group with newly created elements
6360     CORBA::String_var elemGroupName = theElems->GetName();
6361     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6362     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6363     {
6364       SMESH::long_array_var anIds = GetLastCreatedElems();
6365       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6366       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6367       aNewElemGroup->Add(anIds);
6368     }
6369     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6370     {
6371       SMESH::long_array_var anIds = GetLastCreatedNodes();
6372       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6373       aNewNodeGroup->Add(anIds);
6374     }
6375   }
6376
6377   // Update Python script
6378
6379   pyDump << "[ ";
6380   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6381   else                            pyDump << aNewElemGroup << ", ";
6382   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6383   else                            pyDump << aNewNodeGroup << " ] = ";
6384
6385   pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6386          << theNodesNot        << ", "
6387          << theAffectedElems   << ", "
6388          << theElemGroupNeeded << ", "
6389          << theNodeGroupNeeded <<" )";
6390
6391   aTwoGroups[0] = aNewElemGroup._retn();
6392   aTwoGroups[1] = aNewNodeGroup._retn();
6393   return aTwoGroups._retn();
6394
6395   SMESH_CATCH( SMESH::throwCorbaException );
6396   return 0;
6397 }
6398
6399 //================================================================================
6400 /*!
6401   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6402   \param theElems - group of of elements (edges or faces) to be replicated
6403   \param theNodesNot - group of nodes not to replicated
6404   \param theShape - shape to detect affected elements (element which geometric center
6405   located on or inside shape).
6406   The replicated nodes should be associated to affected elements.
6407   \return TRUE if operation has been completed successfully, FALSE otherwise
6408   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6409 */
6410 //================================================================================
6411
6412 CORBA::Boolean
6413 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6414                                                 SMESH::SMESH_GroupBase_ptr theNodesNot,
6415                                                 GEOM::GEOM_Object_ptr      theShape )
6416   throw (SALOME::SALOME_Exception)
6417 {
6418   SMESH_TRY;
6419   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6420     return false;
6421
6422   initData();
6423
6424
6425   SMESHDS_Mesh* aMeshDS = getMeshDS();
6426   TIDSortedElemSet anElems, aNodes, anAffected;
6427   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6428   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6429
6430   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6431   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6432
6433
6434   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6435
6436   // Update Python script
6437   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6438                 << theNodesNot << ", " << theShape << " )";
6439   return aResult;
6440
6441   SMESH_CATCH( SMESH::throwCorbaException );
6442   return 0;
6443 }
6444
6445 //================================================================================
6446 /*!
6447  * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6448  *  \param [in] theGrpList - groups
6449  *  \param [in] theMeshDS -  mesh
6450  *  \param [out] theElemSet - set of elements
6451  *  \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6452  */
6453 //================================================================================
6454
6455 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6456                              SMESHDS_Mesh*              theMeshDS,
6457                              TIDSortedElemSet&          theElemSet,
6458                              const bool                 theIsNodeGrp)
6459 {
6460   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6461   {
6462     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6463     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6464                                     : aGrp->GetType() != SMESH::NODE ) )
6465     {
6466       SMESH::long_array_var anIDs = aGrp->GetIDs();
6467       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6468     }
6469   }
6470 }
6471
6472 //================================================================================
6473 /*!
6474   \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6475   This method provided for convenience works as DoubleNodes() described above.
6476   \param theElems - list of groups of elements (edges or faces) to be replicated
6477   \param theNodesNot - list of groups of nodes not to replicated
6478   \param theAffectedElems - group of elements to which the replicated nodes
6479   should be associated to.
6480   \return TRUE if operation has been completed successfully, FALSE otherwise
6481   \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6482 */
6483 //================================================================================
6484
6485 CORBA::Boolean
6486 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6487                                          const SMESH::ListOfGroups& theNodesNot,
6488                                          const SMESH::ListOfGroups& theAffectedElems)
6489   throw (SALOME::SALOME_Exception)
6490 {
6491   SMESH_TRY;
6492   initData();
6493
6494
6495   SMESHDS_Mesh* aMeshDS = getMeshDS();
6496   TIDSortedElemSet anElems, aNodes, anAffected;
6497   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6498   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6499   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6500
6501   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6502
6503   // Update Python script
6504   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6505                 << &theNodesNot << ", " << &theAffectedElems << " )";
6506
6507   declareMeshModified( /*isReComputeSafe=*/false );
6508   return aResult;
6509
6510   SMESH_CATCH( SMESH::throwCorbaException );
6511   return 0;
6512 }
6513
6514 //================================================================================
6515 /*!
6516  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6517  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6518   \param theElems - list of groups of elements (edges or faces) to be replicated
6519   \param theNodesNot - list of groups of nodes not to replicated
6520   \param theAffectedElems - group of elements to which the replicated nodes
6521   should be associated to.
6522  * \return a new group with newly created elements
6523  * \sa DoubleNodeElemGroups()
6524  */
6525 //================================================================================
6526
6527 SMESH::SMESH_Group_ptr
6528 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6529                                             const SMESH::ListOfGroups& theNodesNot,
6530                                             const SMESH::ListOfGroups& theAffectedElems)
6531   throw (SALOME::SALOME_Exception)
6532 {
6533   TPythonDump pyDump;
6534   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6535                                                                 theNodesNot,
6536                                                                 theAffectedElems,
6537                                                                 true, false );
6538   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6539   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6540
6541   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6542          << theElems         << ", "
6543          << theNodesNot      << ", "
6544          << theAffectedElems << " )";
6545
6546   return elemGroup._retn();
6547 }
6548
6549 //================================================================================
6550 /*!
6551  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6552  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6553   \param theElems - list of groups of elements (edges or faces) to be replicated
6554   \param theNodesNot - list of groups of nodes not to replicated
6555   \param theAffectedElems - group of elements to which the replicated nodes
6556   should be associated to.
6557  * \return a new group with newly created elements
6558  * \sa DoubleNodeElemGroups()
6559  */
6560 //================================================================================
6561
6562 SMESH::ListOfGroups*
6563 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6564                                              const SMESH::ListOfGroups& theNodesNot,
6565                                              const SMESH::ListOfGroups& theAffectedElems,
6566                                              CORBA::Boolean             theElemGroupNeeded,
6567                                              CORBA::Boolean             theNodeGroupNeeded)
6568   throw (SALOME::SALOME_Exception)
6569 {
6570   SMESH_TRY;
6571   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6572   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6573   aTwoGroups->length( 2 );
6574   
6575   initData();
6576
6577
6578   SMESHDS_Mesh* aMeshDS = getMeshDS();
6579   TIDSortedElemSet anElems, aNodes, anAffected;
6580   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6581   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6582   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6583
6584   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6585
6586   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6587
6588   TPythonDump pyDump;
6589   if ( aResult )
6590   {
6591     // Create group with newly created elements
6592     CORBA::String_var elemGroupName = theElems[0]->GetName();
6593     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6594     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6595     {
6596       SMESH::long_array_var anIds = GetLastCreatedElems();
6597       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6598       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6599       aNewElemGroup->Add(anIds);
6600     }
6601     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6602     {
6603       SMESH::long_array_var anIds = GetLastCreatedNodes();
6604       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6605       aNewNodeGroup->Add(anIds);
6606     }
6607   }
6608
6609   // Update Python script
6610
6611   pyDump << "[ ";
6612   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6613   else                            pyDump << aNewElemGroup << ", ";
6614   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6615   else                            pyDump << aNewNodeGroup << " ] = ";
6616
6617   pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6618          << &theNodesNot       << ", "
6619          << &theAffectedElems  << ", "
6620          << theElemGroupNeeded << ", "
6621          << theNodeGroupNeeded << " )";
6622
6623   aTwoGroups[0] = aNewElemGroup._retn();
6624   aTwoGroups[1] = aNewNodeGroup._retn();
6625   return aTwoGroups._retn();
6626
6627   SMESH_CATCH( SMESH::throwCorbaException );
6628   return 0;
6629 }
6630
6631 //================================================================================
6632 /*!
6633   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6634   This method provided for convenience works as DoubleNodes() described above.
6635   \param theElems - list of groups of elements (edges or faces) to be replicated
6636   \param theNodesNot - list of groups of nodes not to replicated
6637   \param theShape - shape to detect affected elements (element which geometric center
6638   located on or inside shape).
6639   The replicated nodes should be associated to affected elements.
6640   \return TRUE if operation has been completed successfully, FALSE otherwise
6641   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6642 */
6643 //================================================================================
6644
6645 CORBA::Boolean
6646 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6647                                                  const SMESH::ListOfGroups& theNodesNot,
6648                                                  GEOM::GEOM_Object_ptr      theShape )
6649   throw (SALOME::SALOME_Exception)
6650 {
6651   SMESH_TRY;
6652   initData();
6653
6654
6655   SMESHDS_Mesh* aMeshDS = getMeshDS();
6656   TIDSortedElemSet anElems, aNodes;
6657   listOfGroupToSet(theElems, aMeshDS, anElems,false );
6658   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6659
6660   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6661   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6662
6663   // Update Python script
6664   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6665                 << &theNodesNot << ", " << theShape << " )";
6666
6667   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6668   return aResult;
6669
6670   SMESH_CATCH( SMESH::throwCorbaException );
6671   return 0;
6672 }
6673
6674 //================================================================================
6675 /*!
6676   \brief Identify the elements that will be affected by node duplication (actual
6677          duplication is not performed.
6678   This method is the first step of DoubleNodeElemGroupsInRegion.
6679   \param theElems - list of groups of elements (edges or faces) to be replicated
6680   \param theNodesNot - list of groups of nodes not to replicated
6681   \param theShape - shape to detect affected elements (element which geometric center
6682          located on or inside shape).
6683          The replicated nodes should be associated to affected elements.
6684   \return groups of affected elements
6685   \sa DoubleNodeElemGroupsInRegion()
6686 */
6687 //================================================================================
6688 SMESH::ListOfGroups*
6689 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6690                                                 const SMESH::ListOfGroups& theNodesNot,
6691                                                 GEOM::GEOM_Object_ptr      theShape )
6692   throw (SALOME::SALOME_Exception)
6693 {
6694   SMESH_TRY;
6695   MESSAGE("AffectedElemGroupsInRegion");
6696   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6697   bool isEdgeGroup = false;
6698   bool isFaceGroup = false;
6699   bool isVolumeGroup = false;
6700   SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6701   SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6702   SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6703
6704   initData();
6705
6706   ::SMESH_MeshEditor aMeshEditor(myMesh);
6707
6708   SMESHDS_Mesh* aMeshDS = getMeshDS();
6709   TIDSortedElemSet anElems, aNodes;
6710   listOfGroupToSet(theElems, aMeshDS, anElems, false);
6711   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6712
6713   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6714   TIDSortedElemSet anAffected;
6715   bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6716
6717
6718   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6719
6720   TPythonDump pyDump;
6721   if (aResult)
6722   {
6723     int lg = anAffected.size();
6724     MESSAGE("lg="<< lg);
6725     SMESH::long_array_var volumeIds = new SMESH::long_array;
6726     volumeIds->length(lg);
6727     SMESH::long_array_var faceIds = new SMESH::long_array;
6728     faceIds->length(lg);
6729     SMESH::long_array_var edgeIds = new SMESH::long_array;
6730     edgeIds->length(lg);
6731     int ivol = 0;
6732     int iface = 0;
6733     int iedge = 0;
6734
6735     TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6736     for (; eIt != anAffected.end(); ++eIt)
6737     {
6738       const SMDS_MeshElement* anElem = *eIt;
6739       if (!anElem)
6740         continue;
6741       int elemId = anElem->GetID();
6742       if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6743         volumeIds[ivol++] = elemId;
6744       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6745         faceIds[iface++] = elemId;
6746       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6747         edgeIds[iedge++] = elemId;
6748     }
6749     volumeIds->length(ivol);
6750     faceIds->length(iface);
6751     edgeIds->length(iedge);
6752
6753     aNewVolumeGroup->Add(volumeIds);
6754     aNewFaceGroup->Add(faceIds);
6755     aNewEdgeGroup->Add(edgeIds);
6756     isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6757     isFaceGroup = (aNewFaceGroup->Size() > 0);
6758     isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6759   }
6760
6761   int nbGroups = 0;
6762   if (isEdgeGroup)   nbGroups++;
6763   if (isFaceGroup)   nbGroups++;
6764   if (isVolumeGroup) nbGroups++;
6765   aListOfGroups->length(nbGroups);
6766
6767   int i = 0;
6768   if (isEdgeGroup)   aListOfGroups[i++] = aNewEdgeGroup._retn();
6769   if (isFaceGroup)   aListOfGroups[i++] = aNewFaceGroup._retn();
6770   if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6771
6772   // Update Python script
6773
6774   pyDump << "[ ";
6775   if (isEdgeGroup)   pyDump << aNewEdgeGroup << ", ";
6776   if (isFaceGroup)   pyDump << aNewFaceGroup << ", ";
6777   if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6778   pyDump << "] = ";
6779   pyDump << this << ".AffectedElemGroupsInRegion( "
6780          << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6781
6782   return aListOfGroups._retn();
6783
6784   SMESH_CATCH( SMESH::throwCorbaException );
6785   return 0;
6786 }
6787
6788 //================================================================================
6789 /*!
6790   \brief Generated skin mesh (containing 2D cells) from 3D mesh
6791    The created 2D mesh elements based on nodes of free faces of boundary volumes
6792   \return TRUE if operation has been completed successfully, FALSE otherwise
6793 */
6794 //================================================================================
6795
6796 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6797   throw (SALOME::SALOME_Exception)
6798 {
6799   SMESH_TRY;
6800   initData();
6801
6802   bool aResult = getEditor().Make2DMeshFrom3D();
6803
6804   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6805
6806   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6807   return aResult;
6808
6809   SMESH_CATCH( SMESH::throwCorbaException );
6810   return false;
6811 }
6812
6813 //================================================================================
6814 /*!
6815  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6816  * The list of groups must contain at least two groups. The groups have to be disjoint:
6817  * no common element into two different groups.
6818  * The nodes of the internal faces at the boundaries of the groups are doubled.
6819  * Optionally, the internal faces are replaced by flat elements.
6820  * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6821  * The flat elements are stored in groups of volumes.
6822  * These groups are named according to the position of the group in the list:
6823  * 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.
6824  * 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.
6825  * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6826  * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6827  * @param theDomains - list of groups of volumes
6828  * @param createJointElems - if TRUE, create the elements
6829  * @return TRUE if operation has been completed successfully, FALSE otherwise
6830  */
6831 //================================================================================
6832
6833 CORBA::Boolean
6834 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6835                                                   CORBA::Boolean             createJointElems )
6836   throw (SALOME::SALOME_Exception)
6837 {
6838   bool aResult = false;
6839
6840   SMESH_TRY;
6841   initData();
6842
6843   SMESHDS_Mesh* aMeshDS = getMeshDS();
6844
6845   // MESSAGE("theDomains.length = "<<theDomains.length());
6846   if ( theDomains.length() <= 1 )
6847     THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6848   vector<TIDSortedElemSet> domains;
6849   domains.clear();
6850
6851   for ( int i = 0, n = theDomains.length(); i < n; i++ )
6852   {
6853     SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6854     if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6855     {
6856 //      if ( aGrp->GetType() != SMESH::VOLUME )
6857 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6858       TIDSortedElemSet domain;
6859       domain.clear();
6860       domains.push_back(domain);
6861       SMESH::long_array_var anIDs = aGrp->GetIDs();
6862       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6863     }
6864   }
6865
6866   aResult = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems );
6867   // TODO publish the groups of flat elements in study
6868
6869   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6870
6871   // Update Python script
6872   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6873       << ", " << createJointElems << " )";
6874
6875   SMESH_CATCH( SMESH::throwCorbaException );
6876
6877   return aResult;
6878 }
6879
6880 //================================================================================
6881 /*!
6882  * \brief Double nodes on some external faces and create flat elements.
6883  * Flat elements are mainly used by some types of mechanic calculations.
6884  *
6885  * Each group of the list must be constituted of faces.
6886  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6887  * @param theGroupsOfFaces - list of groups of faces
6888  * @return TRUE if operation has been completed successfully, FALSE otherwise
6889  */
6890 //================================================================================
6891
6892 CORBA::Boolean
6893 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6894   throw (SALOME::SALOME_Exception)
6895 {
6896   SMESH_TRY;
6897   initData();
6898
6899   SMESHDS_Mesh* aMeshDS = getMeshDS();
6900
6901   vector<TIDSortedElemSet> faceGroups;
6902   faceGroups.clear();
6903
6904   for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6905   {
6906     SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6907     if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6908     {
6909       TIDSortedElemSet faceGroup;
6910       faceGroup.clear();
6911       faceGroups.push_back(faceGroup);
6912       SMESH::long_array_var anIDs = aGrp->GetIDs();
6913       arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6914     }
6915   }
6916
6917   bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6918   // TODO publish the groups of flat elements in study
6919
6920   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6921
6922   // Update Python script
6923   TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6924   return aResult;
6925
6926   SMESH_CATCH( SMESH::throwCorbaException );
6927   return false;
6928 }
6929
6930 //================================================================================
6931 /*!
6932  *  \brief Identify all the elements around a geom shape, get the faces delimiting
6933  *         the hole.
6934  *
6935  *  Build groups of volume to remove, groups of faces to replace on the skin of the
6936  *  object, groups of faces to remove inside the object, (idem edges).
6937  *  Build ordered list of nodes at the border of each group of faces to replace
6938  *  (to be used to build a geom subshape).
6939  */
6940 //================================================================================
6941
6942 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double                  radius,
6943                                         GEOM::GEOM_Object_ptr          theShape,
6944                                         const char*                    groupName,
6945                                         const SMESH::double_array&     theNodesCoords,
6946                                         SMESH::array_of_long_array_out GroupsOfNodes)
6947   throw (SALOME::SALOME_Exception)
6948 {
6949   SMESH_TRY;
6950
6951   initData();
6952   std::vector<std::vector<int> > aListOfListOfNodes;
6953   ::SMESH_MeshEditor aMeshEditor( myMesh );
6954
6955   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
6956   if ( !theNodeSearcher )
6957     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
6958
6959   vector<double> nodesCoords;
6960   for (int i = 0; i < theNodesCoords.length(); i++)
6961   {
6962     nodesCoords.push_back( theNodesCoords[i] );
6963   }
6964
6965   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6966   aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
6967                              nodesCoords, aListOfListOfNodes);
6968
6969   GroupsOfNodes = new SMESH::array_of_long_array;
6970   GroupsOfNodes->length( aListOfListOfNodes.size() );
6971   std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
6972   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
6973   {
6974     vector<int>& aListOfNodes = *llIt;
6975     vector<int>::iterator lIt = aListOfNodes.begin();;
6976     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
6977     aGroup.length( aListOfNodes.size() );
6978     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
6979       aGroup[ j ] = (*lIt);
6980   }
6981   TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
6982                 << radius << ", "
6983                 << theShape
6984                 << ", '" << groupName << "', "
6985                 << theNodesCoords << " )";
6986
6987   SMESH_CATCH( SMESH::throwCorbaException );
6988 }
6989
6990 // issue 20749 ===================================================================
6991 /*!
6992  * \brief Creates missing boundary elements
6993  *  \param elements - elements whose boundary is to be checked
6994  *  \param dimension - defines type of boundary elements to create
6995  *  \param groupName - a name of group to store created boundary elements in,
6996  *                     "" means not to create the group
6997  *  \param meshName - a name of new mesh to store created boundary elements in,
6998  *                     "" means not to create the new mesh
6999  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
7000  *  \param toCopyExistingBondary - if true, not only new but also pre-existing
7001  *                                boundary elements will be copied into the new mesh
7002  *  \param group - returns the create group, if any
7003  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7004  */
7005 // ================================================================================
7006
7007 SMESH::SMESH_Mesh_ptr
7008 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7009                                      SMESH::Bnd_Dimension      dim,
7010                                      const char*               groupName,
7011                                      const char*               meshName,
7012                                      CORBA::Boolean            toCopyElements,
7013                                      CORBA::Boolean            toCopyExistingBondary,
7014                                      SMESH::SMESH_Group_out    group)
7015   throw (SALOME::SALOME_Exception)
7016 {
7017   SMESH_TRY;
7018   initData();
7019
7020   if ( dim > SMESH::BND_1DFROM2D )
7021     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7022
7023   SMESHDS_Mesh* aMeshDS = getMeshDS();
7024
7025   SMESH::SMESH_Mesh_var mesh_var;
7026   SMESH::SMESH_Group_var group_var;
7027
7028   TPythonDump pyDump;
7029
7030   TIDSortedElemSet elements;
7031   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7032   prepareIdSource( idSource );
7033   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7034   {
7035     // mesh to fill in
7036     mesh_var =
7037       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7038     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7039     // other mesh
7040     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7041
7042     // group of new boundary elements
7043     SMESH_Group* smesh_group = 0;
7044     if ( strlen(groupName) )
7045     {
7046       group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7047       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7048         smesh_group = group_i->GetSmeshGroup();
7049     }
7050
7051     // do it
7052     getEditor().MakeBoundaryMesh( elements,
7053                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
7054                                   smesh_group,
7055                                   smesh_mesh,
7056                                   toCopyElements,
7057                                   toCopyExistingBondary);
7058
7059     if ( smesh_mesh )
7060       smesh_mesh->GetMeshDS()->Modified();
7061   }
7062
7063   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7064
7065   // result of MakeBoundaryMesh() is a tuple (mesh, group)
7066   if ( mesh_var->_is_nil() )
7067     pyDump << myMesh_i->_this() << ", ";
7068   else
7069     pyDump << mesh_var << ", ";
7070   if ( group_var->_is_nil() )
7071     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7072   else
7073     pyDump << group_var << " = ";
7074   pyDump << this << ".MakeBoundaryMesh( "
7075          << idSource << ", "
7076          << "SMESH." << dimName[int(dim)] << ", "
7077          << "'" << groupName << "', "
7078          << "'" << meshName<< "', "
7079          << toCopyElements << ", "
7080          << toCopyExistingBondary << ")";
7081
7082   group = group_var._retn();
7083   return mesh_var._retn();
7084
7085   SMESH_CATCH( SMESH::throwCorbaException );
7086   return SMESH::SMESH_Mesh::_nil();
7087 }
7088
7089 //================================================================================
7090 /*!
7091  * \brief Creates missing boundary elements
7092  *  \param dimension - defines type of boundary elements to create
7093  *  \param groupName - a name of group to store all boundary elements in,
7094  *    "" means not to create the group
7095  *  \param meshName - a name of a new mesh, which is a copy of the initial 
7096  *    mesh + created boundary elements; "" means not to create the new mesh
7097  *  \param toCopyAll - if true, the whole initial mesh will be copied into
7098  *    the new mesh else only boundary elements will be copied into the new mesh
7099  *  \param groups - optional groups of elements to make boundary around
7100  *  \param mesh - returns the mesh where elements were added to
7101  *  \param group - returns the created group, if any
7102  *  \retval long - number of added boundary elements
7103  */
7104 //================================================================================
7105
7106 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7107                                                      const char* groupName,
7108                                                      const char* meshName,
7109                                                      CORBA::Boolean toCopyAll,
7110                                                      const SMESH::ListOfIDSources& groups,
7111                                                      SMESH::SMESH_Mesh_out mesh,
7112                                                      SMESH::SMESH_Group_out group)
7113   throw (SALOME::SALOME_Exception)
7114 {
7115   SMESH_TRY;
7116   initData();
7117
7118   if ( dim > SMESH::BND_1DFROM2D )
7119     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7120
7121   // separate groups belonging to this and other mesh
7122   SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7123   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7124   groupsOfThisMesh->length( groups.length() );
7125   groupsOfOtherMesh->length( groups.length() );
7126   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7127   for ( int i = 0; i < groups.length(); ++i )
7128   {
7129     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7130     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7131       groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7132     else
7133       groupsOfThisMesh[ nbGroups++ ] = groups[i];
7134     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7135       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
7136   }
7137   groupsOfThisMesh->length( nbGroups );
7138   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7139
7140   int nbAdded = 0;
7141   TPythonDump pyDump;
7142
7143   if ( nbGroupsOfOtherMesh > 0 )
7144   {
7145     // process groups belonging to another mesh
7146     SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
7147     SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7148     nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7149                                              groupsOfOtherMesh, mesh, group );
7150   }
7151
7152   SMESH::SMESH_Mesh_var mesh_var;
7153   SMESH::SMESH_Group_var group_var;
7154
7155   // get mesh to fill
7156   mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7157   const bool toCopyMesh = ( strlen( meshName ) > 0 );
7158   if ( toCopyMesh )
7159   {
7160     if ( toCopyAll )
7161       mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7162                                                       meshName,
7163                                                       /*toCopyGroups=*/false,
7164                                                       /*toKeepIDs=*/true);
7165     else
7166       mesh_var = makeMesh(meshName);
7167   }
7168   SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7169   SMESH_Mesh*  tgtMesh = &mesh_i->GetImpl();
7170
7171   // source mesh
7172   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7173   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7174
7175   // group of boundary elements
7176   SMESH_Group* smesh_group = 0;
7177   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7178   if ( strlen(groupName) )
7179   {
7180     SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7181     group_var = mesh_i->CreateGroup( groupType, groupName );
7182     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7183       smesh_group = group_i->GetSmeshGroup();
7184   }
7185
7186   TIDSortedElemSet elements;
7187
7188   if ( groups.length() > 0 )
7189   {
7190     for ( int i = 0; i < nbGroups; ++i )
7191     {
7192       elements.clear();
7193       if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7194       {
7195         SMESH::Bnd_Dimension bdim = 
7196           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7197         nbAdded += getEditor().MakeBoundaryMesh( elements,
7198                                                  ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7199                                                  smesh_group,
7200                                                  tgtMesh,
7201                                                  /*toCopyElements=*/false,
7202                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7203                                                  /*toAddExistingBondary=*/true,
7204                                                  /*aroundElements=*/true);
7205       }
7206     }
7207   }
7208   else
7209   {
7210     nbAdded += getEditor().MakeBoundaryMesh( elements,
7211                                              ::SMESH_MeshEditor::Bnd_Dimension(dim),
7212                                              smesh_group,
7213                                              tgtMesh,
7214                                              /*toCopyElements=*/false,
7215                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7216                                              /*toAddExistingBondary=*/true);
7217   }
7218   tgtMesh->GetMeshDS()->Modified();
7219
7220   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7221
7222   // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7223   pyDump << "nbAdded, ";
7224   if ( mesh_var->_is_nil() )
7225     pyDump << myMesh_i->_this() << ", ";
7226   else
7227     pyDump << mesh_var << ", ";
7228   if ( group_var->_is_nil() )
7229     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7230   else
7231     pyDump << group_var << " = ";
7232   pyDump << this << ".MakeBoundaryElements( "
7233          << "SMESH." << dimName[int(dim)] << ", "
7234          << "'" << groupName << "', "
7235          << "'" << meshName<< "', "
7236          << toCopyAll << ", "
7237          << groups << ")";
7238
7239   mesh  = mesh_var._retn();
7240   group = group_var._retn();
7241   return nbAdded;
7242
7243   SMESH_CATCH( SMESH::throwCorbaException );
7244   return 0;
7245 }