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