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