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