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