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