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