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