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