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