Salome HOME
Update copyrights 2014.
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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   return res._retn();
5257
5258   SMESH_CATCH( SMESH::throwCorbaException );
5259   return 0;
5260 }
5261
5262 //=======================================================================
5263 //function : FindAmongElementsByPoint
5264 //purpose  : Searching among the given elements, return elements of given type 
5265 //           where the given point is IN or ON.
5266 //           'ALL' type means elements of any type excluding nodes
5267 //=======================================================================
5268
5269 SMESH::long_array*
5270 SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementIDs,
5271                                              CORBA::Double             x,
5272                                              CORBA::Double             y,
5273                                              CORBA::Double             z,
5274                                              SMESH::ElementType        type)
5275   throw (SALOME::SALOME_Exception)
5276 {
5277   SMESH_TRY;
5278   SMESH::long_array_var res = new SMESH::long_array;
5279   
5280   SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
5281   if ( types->length() == 1 && // a part contains only nodes or 0D elements
5282        ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
5283        type != types[0] ) // but search of elements of dim > 0
5284     return res._retn();
5285
5286   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
5287     return FindElementsByPoint( x,y,z, type );
5288
5289   TIDSortedElemSet elements; // elems should live until FindElementsByPoint() finishes
5290
5291   theSearchersDeleter.Set( myMesh, getPartIOR( elementIDs, type ));
5292   if ( !theElementSearcher )
5293   {
5294     // create a searcher from elementIDs
5295     SMESH::SMESH_Mesh_var mesh = elementIDs->GetMesh();
5296     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
5297
5298     if ( !idSourceToSet( elementIDs, meshDS, elements,
5299                          SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
5300       return res._retn();
5301
5302     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5303     SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
5304
5305     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
5306   }
5307
5308   vector< const SMDS_MeshElement* > foundElems;
5309
5310   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
5311                                            SMDSAbs_ElementType( type ),
5312                                            foundElems);
5313   res->length( foundElems.size() );
5314   for ( int i = 0; i < foundElems.size(); ++i )
5315     res[i] = foundElems[i]->GetID();
5316
5317   return res._retn();
5318
5319   SMESH_CATCH( SMESH::throwCorbaException );
5320   return 0;
5321 }
5322
5323 //=======================================================================
5324 //function : GetPointState
5325 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
5326 //           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
5327 //=======================================================================
5328
5329 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
5330                                                CORBA::Double y,
5331                                                CORBA::Double z)
5332   throw (SALOME::SALOME_Exception)
5333 {
5334   SMESH_TRY;
5335   theSearchersDeleter.Set( myMesh );
5336   if ( !theElementSearcher ) {
5337     theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
5338   }
5339   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
5340
5341   SMESH_CATCH( SMESH::throwCorbaException );
5342   return 0;
5343 }
5344
5345 //=======================================================================
5346 //function : convError
5347 //purpose  :
5348 //=======================================================================
5349
5350 #define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
5351
5352 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
5353 {
5354   switch ( e ) {
5355     RETCASE( SEW_OK );
5356     RETCASE( SEW_BORDER1_NOT_FOUND );
5357     RETCASE( SEW_BORDER2_NOT_FOUND );
5358     RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
5359     RETCASE( SEW_BAD_SIDE_NODES );
5360     RETCASE( SEW_VOLUMES_TO_SPLIT );
5361     RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
5362     RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
5363     RETCASE( SEW_BAD_SIDE1_NODES );
5364     RETCASE( SEW_BAD_SIDE2_NODES );
5365   }
5366   return SMESH::SMESH_MeshEditor::SEW_OK;
5367 }
5368
5369 //=======================================================================
5370 //function : SewFreeBorders
5371 //purpose  :
5372 //=======================================================================
5373
5374 SMESH::SMESH_MeshEditor::Sew_Error
5375 SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
5376                                    CORBA::Long SecondNodeID1,
5377                                    CORBA::Long LastNodeID1,
5378                                    CORBA::Long FirstNodeID2,
5379                                    CORBA::Long SecondNodeID2,
5380                                    CORBA::Long LastNodeID2,
5381                                    CORBA::Boolean CreatePolygons,
5382                                    CORBA::Boolean CreatePolyedrs)
5383   throw (SALOME::SALOME_Exception)
5384 {
5385   SMESH_TRY;
5386   initData();
5387
5388   SMESHDS_Mesh* aMesh = getMeshDS();
5389
5390   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5391   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5392   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5393   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5394   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5395   const SMDS_MeshNode* aSide2ThirdNode   = aMesh->FindNode( LastNodeID2   );
5396
5397   if (!aBorderFirstNode ||
5398       !aBorderSecondNode||
5399       !aBorderLastNode)
5400     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5401   if (!aSide2FirstNode  ||
5402       !aSide2SecondNode ||
5403       !aSide2ThirdNode)
5404     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5405
5406   TPythonDump() << "error = " << this << ".SewFreeBorders( "
5407                 << FirstNodeID1  << ", "
5408                 << SecondNodeID1 << ", "
5409                 << LastNodeID1   << ", "
5410                 << FirstNodeID2  << ", "
5411                 << SecondNodeID2 << ", "
5412                 << LastNodeID2   << ", "
5413                 << CreatePolygons<< ", "
5414                 << CreatePolyedrs<< " )";
5415
5416   SMESH::SMESH_MeshEditor::Sew_Error error =
5417     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5418                                        aBorderSecondNode,
5419                                        aBorderLastNode,
5420                                        aSide2FirstNode,
5421                                        aSide2SecondNode,
5422                                        aSide2ThirdNode,
5423                                        true,
5424                                        CreatePolygons,
5425                                        CreatePolyedrs) );
5426
5427
5428   declareMeshModified( /*isReComputeSafe=*/false );
5429   return error;
5430
5431   SMESH_CATCH( SMESH::throwCorbaException );
5432   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5433 }
5434
5435
5436 //=======================================================================
5437 //function : SewConformFreeBorders
5438 //purpose  :
5439 //=======================================================================
5440
5441 SMESH::SMESH_MeshEditor::Sew_Error
5442 SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
5443                                           CORBA::Long SecondNodeID1,
5444                                           CORBA::Long LastNodeID1,
5445                                           CORBA::Long FirstNodeID2,
5446                                           CORBA::Long SecondNodeID2)
5447   throw (SALOME::SALOME_Exception)
5448 {
5449   SMESH_TRY;
5450   initData();
5451
5452   SMESHDS_Mesh* aMesh = getMeshDS();
5453
5454   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeID1  );
5455   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeID1 );
5456   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeID1   );
5457   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeID2  );
5458   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( SecondNodeID2 );
5459   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5460
5461   if (!aBorderFirstNode ||
5462       !aBorderSecondNode||
5463       !aBorderLastNode )
5464     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5465   if (!aSide2FirstNode  ||
5466       !aSide2SecondNode)
5467     return SMESH::SMESH_MeshEditor::SEW_BORDER2_NOT_FOUND;
5468
5469   TPythonDump() << "error = " << this << ".SewConformFreeBorders( "
5470                 << FirstNodeID1  << ", "
5471                 << SecondNodeID1 << ", "
5472                 << LastNodeID1   << ", "
5473                 << FirstNodeID2  << ", "
5474                 << SecondNodeID2 << " )";
5475
5476   SMESH::SMESH_MeshEditor::Sew_Error error =
5477     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5478                                        aBorderSecondNode,
5479                                        aBorderLastNode,
5480                                        aSide2FirstNode,
5481                                        aSide2SecondNode,
5482                                        aSide2ThirdNode,
5483                                        true,
5484                                        false, false) );
5485
5486   declareMeshModified( /*isReComputeSafe=*/false );
5487   return error;
5488
5489   SMESH_CATCH( SMESH::throwCorbaException );
5490   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5491 }
5492
5493
5494 //=======================================================================
5495 //function : SewBorderToSide
5496 //purpose  :
5497 //=======================================================================
5498
5499 SMESH::SMESH_MeshEditor::Sew_Error
5500 SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
5501                                     CORBA::Long SecondNodeIDOnFreeBorder,
5502                                     CORBA::Long LastNodeIDOnFreeBorder,
5503                                     CORBA::Long FirstNodeIDOnSide,
5504                                     CORBA::Long LastNodeIDOnSide,
5505                                     CORBA::Boolean CreatePolygons,
5506                                     CORBA::Boolean CreatePolyedrs)
5507   throw (SALOME::SALOME_Exception)
5508 {
5509   SMESH_TRY;
5510   initData();
5511
5512   SMESHDS_Mesh* aMesh = getMeshDS();
5513
5514   const SMDS_MeshNode* aBorderFirstNode  = aMesh->FindNode( FirstNodeIDOnFreeBorder  );
5515   const SMDS_MeshNode* aBorderSecondNode = aMesh->FindNode( SecondNodeIDOnFreeBorder );
5516   const SMDS_MeshNode* aBorderLastNode   = aMesh->FindNode( LastNodeIDOnFreeBorder   );
5517   const SMDS_MeshNode* aSide2FirstNode   = aMesh->FindNode( FirstNodeIDOnSide  );
5518   const SMDS_MeshNode* aSide2SecondNode  = aMesh->FindNode( LastNodeIDOnSide );
5519   const SMDS_MeshNode* aSide2ThirdNode   = 0;
5520
5521   if (!aBorderFirstNode ||
5522       !aBorderSecondNode||
5523       !aBorderLastNode  )
5524     return SMESH::SMESH_MeshEditor::SEW_BORDER1_NOT_FOUND;
5525   if (!aSide2FirstNode  ||
5526       !aSide2SecondNode)
5527     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE_NODES;
5528
5529   TPythonDump() << "error = " << this << ".SewBorderToSide( "
5530                 << FirstNodeIDOnFreeBorder  << ", "
5531                 << SecondNodeIDOnFreeBorder << ", "
5532                 << LastNodeIDOnFreeBorder   << ", "
5533                 << FirstNodeIDOnSide        << ", "
5534                 << LastNodeIDOnSide         << ", "
5535                 << CreatePolygons           << ", "
5536                 << CreatePolyedrs           << ") ";
5537
5538   SMESH::SMESH_MeshEditor::Sew_Error error =
5539     convError( getEditor().SewFreeBorder (aBorderFirstNode,
5540                                        aBorderSecondNode,
5541                                        aBorderLastNode,
5542                                        aSide2FirstNode,
5543                                        aSide2SecondNode,
5544                                        aSide2ThirdNode,
5545                                        false,
5546                                        CreatePolygons,
5547                                        CreatePolyedrs) );
5548
5549   declareMeshModified( /*isReComputeSafe=*/false );
5550   return error;
5551
5552   SMESH_CATCH( SMESH::throwCorbaException );
5553   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5554 }
5555
5556
5557 //=======================================================================
5558 //function : SewSideElements
5559 //purpose  :
5560 //=======================================================================
5561
5562 SMESH::SMESH_MeshEditor::Sew_Error
5563 SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
5564                                     const SMESH::long_array& IDsOfSide2Elements,
5565                                     CORBA::Long NodeID1OfSide1ToMerge,
5566                                     CORBA::Long NodeID1OfSide2ToMerge,
5567                                     CORBA::Long NodeID2OfSide1ToMerge,
5568                                     CORBA::Long NodeID2OfSide2ToMerge)
5569   throw (SALOME::SALOME_Exception)
5570 {
5571   SMESH_TRY;
5572   initData();
5573
5574   SMESHDS_Mesh* aMesh = getMeshDS();
5575
5576   const SMDS_MeshNode* aFirstNode1ToMerge  = aMesh->FindNode( NodeID1OfSide1ToMerge );
5577   const SMDS_MeshNode* aFirstNode2ToMerge  = aMesh->FindNode( NodeID1OfSide2ToMerge );
5578   const SMDS_MeshNode* aSecondNode1ToMerge = aMesh->FindNode( NodeID2OfSide1ToMerge );
5579   const SMDS_MeshNode* aSecondNode2ToMerge = aMesh->FindNode( NodeID2OfSide2ToMerge );
5580
5581   if (!aFirstNode1ToMerge ||
5582       !aFirstNode2ToMerge )
5583     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE1_NODES;
5584   if (!aSecondNode1ToMerge||
5585       !aSecondNode2ToMerge)
5586     return SMESH::SMESH_MeshEditor::SEW_BAD_SIDE2_NODES;
5587
5588   TIDSortedElemSet aSide1Elems, aSide2Elems;
5589   arrayToSet(IDsOfSide1Elements, aMesh, aSide1Elems);
5590   arrayToSet(IDsOfSide2Elements, aMesh, aSide2Elems);
5591
5592   TPythonDump() << "error = " << this << ".SewSideElements( "
5593                 << IDsOfSide1Elements << ", "
5594                 << IDsOfSide2Elements << ", "
5595                 << NodeID1OfSide1ToMerge << ", "
5596                 << NodeID1OfSide2ToMerge << ", "
5597                 << NodeID2OfSide1ToMerge << ", "
5598                 << NodeID2OfSide2ToMerge << ")";
5599
5600   SMESH::SMESH_MeshEditor::Sew_Error error =
5601     convError( getEditor().SewSideElements (aSide1Elems, aSide2Elems,
5602                                          aFirstNode1ToMerge,
5603                                          aFirstNode2ToMerge,
5604                                          aSecondNode1ToMerge,
5605                                          aSecondNode2ToMerge));
5606
5607   declareMeshModified( /*isReComputeSafe=*/false );
5608   return error;
5609
5610   SMESH_CATCH( SMESH::throwCorbaException );
5611   return SMESH::SMESH_MeshEditor::Sew_Error(0);
5612 }
5613
5614 //================================================================================
5615 /*!
5616  * \brief Set new nodes for given element
5617  * \param ide - element id
5618  * \param newIDs - new node ids
5619  * \retval CORBA::Boolean - true if result is OK
5620  */
5621 //================================================================================
5622
5623 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
5624                                                    const SMESH::long_array& newIDs)
5625   throw (SALOME::SALOME_Exception)
5626 {
5627   SMESH_TRY;
5628   initData();
5629
5630   const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
5631   if(!elem) return false;
5632
5633   int nbn = newIDs.length();
5634   int i=0;
5635   vector<const SMDS_MeshNode*> aNodes(nbn);
5636   int nbn1=-1;
5637   for(; i<nbn; i++) {
5638     const SMDS_MeshNode* aNode = getMeshDS()->FindNode(newIDs[i]);
5639     if(aNode) {
5640       nbn1++;
5641       aNodes[nbn1] = aNode;
5642     }
5643   }
5644   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
5645                 << ide << ", " << newIDs << " )";
5646
5647   MESSAGE("ChangeElementNodes");
5648   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
5649
5650   declareMeshModified( /*isReComputeSafe=*/ !res );
5651
5652   return res;
5653
5654   SMESH_CATCH( SMESH::throwCorbaException );
5655   return 0;
5656 }
5657
5658 //=======================================================================
5659 /*!
5660  * \brief Makes a part of the mesh quadratic or bi-quadratic
5661  */
5662 //=======================================================================
5663
5664 void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean            theForce3d,
5665                                             CORBA::Boolean            theToBiQuad,
5666                                             SMESH::SMESH_IDSource_ptr theObject)
5667   throw (SALOME::SALOME_Exception)
5668 {
5669   SMESH_TRY;
5670   TIDSortedElemSet elems;
5671   bool elemsOK;
5672   if ( !( elemsOK = CORBA::is_nil( theObject )))
5673   {
5674     prepareIdSource( theObject );
5675     elemsOK =  idSourceToSet( theObject, getMeshDS(), elems,
5676                               SMDSAbs_All, /*emptyIfIsMesh=*/true );
5677   }
5678   if ( elemsOK )
5679   {
5680     if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
5681       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5682
5683     if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
5684     else                 getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
5685
5686     declareMeshModified( /*isReComputeSafe=*/false );
5687   }
5688
5689   SMESH_CATCH( SMESH::throwCorbaException );
5690 }
5691
5692 //=======================================================================
5693 //function : ConvertFromQuadratic
5694 //purpose  :
5695 //=======================================================================
5696
5697 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
5698   throw (SALOME::SALOME_Exception)
5699 {
5700   CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
5701   TPythonDump() << this << ".ConvertFromQuadratic()";
5702   declareMeshModified( /*isReComputeSafe=*/!isDone );
5703   return isDone;
5704 }
5705
5706 //=======================================================================
5707 //function : ConvertToQuadratic
5708 //purpose  :
5709 //=======================================================================
5710
5711 void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
5712   throw (SALOME::SALOME_Exception)
5713 {
5714   convertToQuadratic( theForce3d, false );
5715   TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
5716 }
5717
5718 //================================================================================
5719 /*!
5720  * \brief Makes a part of the mesh quadratic
5721  */
5722 //================================================================================
5723
5724 void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theForce3d,
5725                                                   SMESH::SMESH_IDSource_ptr theObject)
5726   throw (SALOME::SALOME_Exception)
5727 {
5728   convertToQuadratic( theForce3d, false, theObject );
5729   TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
5730 }
5731
5732 //================================================================================
5733 /*!
5734  * \brief Makes a part of the mesh bi-quadratic
5735  */
5736 //================================================================================
5737
5738 void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean            theForce3d,
5739                                               SMESH::SMESH_IDSource_ptr theObject)
5740   throw (SALOME::SALOME_Exception)
5741 {
5742   convertToQuadratic( theForce3d, true, theObject );
5743   TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
5744 }
5745
5746 //================================================================================
5747 /*!
5748  * \brief Makes a part of the mesh linear
5749  */
5750 //================================================================================
5751
5752 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
5753   throw (SALOME::SALOME_Exception)
5754 {
5755   SMESH_TRY;
5756
5757   TPythonDump pyDump;
5758
5759   TIDSortedElemSet elems;
5760   prepareIdSource( theObject );
5761   if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
5762   {
5763     if ( elems.empty() )
5764     {
5765       ConvertFromQuadratic();
5766     }
5767     else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
5768     {
5769       THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
5770     }
5771     else
5772     {
5773       getEditor().ConvertFromQuadratic(elems);
5774     }
5775   }
5776   declareMeshModified( /*isReComputeSafe=*/false );
5777
5778   pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
5779
5780   SMESH_CATCH( SMESH::throwCorbaException );
5781 }
5782
5783 //=======================================================================
5784 //function : makeMesh
5785 //purpose  : create a named imported mesh
5786 //=======================================================================
5787
5788 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
5789 {
5790   SMESH_Gen_i*              gen = SMESH_Gen_i::GetSMESHGen();
5791   SMESH::SMESH_Mesh_var    mesh = gen->CreateEmptyMesh();
5792   SALOMEDS::Study_var     study = gen->GetCurrentStudy();
5793   SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
5794   gen->SetName( meshSO, theMeshName, "Mesh" );
5795   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
5796
5797   return mesh._retn();
5798 }
5799
5800 //=======================================================================
5801 //function : dumpGroupsList
5802 //purpose  :
5803 //=======================================================================
5804
5805 void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPython,
5806                                         const SMESH::ListOfGroups * theGroupList)
5807 {
5808   bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
5809   if ( isDumpGroupList )
5810     theDumpPython << theGroupList << " = ";
5811 }
5812
5813 //================================================================================
5814 /*!
5815   \brief Generates the unique group name.
5816   \param thePrefix name prefix
5817   \return unique name
5818 */
5819 //================================================================================
5820
5821 string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
5822 {
5823   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5824   set<string> groupNames;
5825
5826   // Get existing group names
5827   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
5828     SMESH::SMESH_GroupBase_var aGroup = groups[i];
5829     if (CORBA::is_nil(aGroup))
5830       continue;
5831
5832     CORBA::String_var name = aGroup->GetName();
5833     groupNames.insert( name.in() );
5834   }
5835
5836   // Find new name
5837   string name = thePrefix;
5838   int index = 0;
5839
5840   while (!groupNames.insert(name).second)
5841     name = SMESH_Comment( thePrefix ) << "_" << index++;
5842
5843   return name;
5844 }
5845
5846 //================================================================================
5847 /*!
5848  * \brief Prepare SMESH_IDSource for work
5849  */
5850 //================================================================================
5851
5852 void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
5853 {
5854   if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5855   {
5856     SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
5857     filter->SetMesh( mesh );
5858   }
5859 }
5860
5861 //================================================================================
5862 /*!
5863  * \brief Duplicates given elements, i.e. creates new elements based on the 
5864  *        same nodes as the given ones.
5865  * \param theElements - container of elements to duplicate.
5866  * \param theGroupName - a name of group to contain the generated elements.
5867  *                    If a group with such a name already exists, the new elements
5868  *                    are added to the existng group, else a new group is created.
5869  *                    If \a theGroupName is empty, new elements are not added 
5870  *                    in any group.
5871  * \return a group where the new elements are added. NULL if theGroupName == "".
5872  * \sa DoubleNode()
5873  */
5874 //================================================================================
5875
5876 SMESH::SMESH_Group_ptr
5877 SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
5878                                    const char*               theGroupName)
5879   throw (SALOME::SALOME_Exception)
5880 {
5881   SMESH::SMESH_Group_var newGroup;
5882
5883   SMESH_TRY;
5884   initData();
5885
5886   TPythonDump pyDump;
5887
5888   TIDSortedElemSet elems;
5889   prepareIdSource( theElements );
5890   if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
5891   {
5892     getEditor().DoubleElements( elems );
5893
5894     if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
5895     {
5896       // group type
5897       SMESH::ElementType type =
5898         SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
5899       // find existing group
5900       SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
5901       for ( size_t i = 0; i < groups->length(); ++i )
5902         if ( groups[i]->GetType() == type )
5903         {
5904           CORBA::String_var name = groups[i]->GetName();
5905           if ( strcmp( name, theGroupName ) == 0 ) {
5906             newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
5907             break;
5908           }
5909         }
5910       // create a new group
5911       if ( newGroup->_is_nil() )
5912         newGroup = myMesh_i->CreateGroup( type, theGroupName );
5913       // fill newGroup
5914       if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
5915       {
5916         SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
5917         const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
5918         for ( int i = 1; i <= aSeq.Length(); i++ )
5919           groupDS->SMDSGroup().Add( aSeq(i) );
5920       }
5921     }
5922   }
5923   // python dump
5924   if ( !newGroup->_is_nil() )
5925     pyDump << newGroup << " = ";
5926   pyDump << this << ".DoubleElements( "
5927          << theElements << ", " << "'" << theGroupName <<"')";
5928
5929   SMESH_CATCH( SMESH::throwCorbaException );
5930
5931   return newGroup._retn();
5932 }
5933
5934 //================================================================================
5935 /*!
5936   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5937   \param theNodes - identifiers of nodes to be doubled
5938   \param theModifiedElems - identifiers of elements to be updated by the new (doubled)
5939          nodes. If list of element identifiers is empty then nodes are doubled but
5940          they not assigned to elements
5941   \return TRUE if operation has been completed successfully, FALSE otherwise
5942   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
5943 */
5944 //================================================================================
5945
5946 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
5947                                                 const SMESH::long_array& theModifiedElems )
5948   throw (SALOME::SALOME_Exception)
5949 {
5950   SMESH_TRY;
5951   initData();
5952
5953   list< int > aListOfNodes;
5954   int i, n;
5955   for ( i = 0, n = theNodes.length(); i < n; i++ )
5956     aListOfNodes.push_back( theNodes[ i ] );
5957
5958   list< int > aListOfElems;
5959   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
5960     aListOfElems.push_back( theModifiedElems[ i ] );
5961
5962   bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
5963
5964   declareMeshModified( /*isReComputeSafe=*/ !aResult );
5965
5966   // Update Python script
5967   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
5968
5969   return aResult;
5970
5971   SMESH_CATCH( SMESH::throwCorbaException );
5972   return 0;
5973 }
5974
5975 //================================================================================
5976 /*!
5977   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
5978   This method provided for convenience works as DoubleNodes() described above.
5979   \param theNodeId - identifier of node to be doubled.
5980   \param theModifiedElems - identifiers of elements to be updated.
5981   \return TRUE if operation has been completed successfully, FALSE otherwise
5982   \sa DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
5983 */
5984 //================================================================================
5985
5986 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
5987                                                const SMESH::long_array& theModifiedElems )
5988   throw (SALOME::SALOME_Exception)
5989 {
5990   SMESH_TRY;
5991   SMESH::long_array_var aNodes = new SMESH::long_array;
5992   aNodes->length( 1 );
5993   aNodes[ 0 ] = theNodeId;
5994
5995   TPythonDump pyDump; // suppress dump by the next line
5996
5997   CORBA::Boolean done = DoubleNodes( aNodes, theModifiedElems );
5998
5999   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
6000
6001   return done;
6002
6003   SMESH_CATCH( SMESH::throwCorbaException );
6004   return 0;
6005 }
6006
6007 //================================================================================
6008 /*!
6009   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6010   This method provided for convenience works as DoubleNodes() described above.
6011   \param theNodes - group of nodes to be doubled.
6012   \param theModifiedElems - group of elements to be updated.
6013   \return TRUE if operation has been completed successfully, FALSE otherwise
6014   \sa DoubleNode(), DoubleNodes(), DoubleNodeGroups()
6015 */
6016 //================================================================================
6017
6018 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
6019                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
6020   throw (SALOME::SALOME_Exception)
6021 {
6022   SMESH_TRY;
6023   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6024     return false;
6025
6026   SMESH::long_array_var aNodes = theNodes->GetListOfID();
6027   SMESH::long_array_var aModifiedElems;
6028   if ( !CORBA::is_nil( theModifiedElems ) )
6029     aModifiedElems = theModifiedElems->GetListOfID();
6030   else
6031   {
6032     aModifiedElems = new SMESH::long_array;
6033     aModifiedElems->length( 0 );
6034   }
6035
6036   TPythonDump pyDump; // suppress dump by the next line
6037
6038   bool done = DoubleNodes( aNodes, aModifiedElems );
6039
6040   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
6041
6042   return done;
6043
6044   SMESH_CATCH( SMESH::throwCorbaException );
6045   return 0;
6046 }
6047
6048 //================================================================================
6049 /*!
6050  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6051  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
6052  * \param theNodes - group of nodes to be doubled.
6053  * \param theModifiedElems - group of elements to be updated.
6054  * \return a new group with newly created nodes
6055  * \sa DoubleNodeGroup()
6056  */
6057 //================================================================================
6058
6059 SMESH::SMESH_Group_ptr
6060 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
6061                                         SMESH::SMESH_GroupBase_ptr theModifiedElems )
6062   throw (SALOME::SALOME_Exception)
6063 {
6064   SMESH_TRY;
6065   SMESH::SMESH_Group_var aNewGroup;
6066
6067   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
6068     return aNewGroup._retn();
6069
6070   // Duplicate nodes
6071   SMESH::long_array_var aNodes = theNodes->GetListOfID();
6072   SMESH::long_array_var aModifiedElems;
6073   if ( !CORBA::is_nil( theModifiedElems ) )
6074     aModifiedElems = theModifiedElems->GetListOfID();
6075   else {
6076     aModifiedElems = new SMESH::long_array;
6077     aModifiedElems->length( 0 );
6078   }
6079
6080   TPythonDump pyDump; // suppress dump by the next line
6081
6082   bool aResult = DoubleNodes( aNodes, aModifiedElems );
6083   if ( aResult )
6084   {
6085     // Create group with newly created nodes
6086     SMESH::long_array_var anIds = GetLastCreatedNodes();
6087     if (anIds->length() > 0) {
6088       string anUnindexedName (theNodes->GetName());
6089       string aNewName = generateGroupName(anUnindexedName + "_double");
6090       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6091       aNewGroup->Add(anIds);
6092       pyDump << aNewGroup << " = ";
6093     }
6094   }
6095
6096   pyDump << this << ".DoubleNodeGroupNew( " << theNodes << ", "
6097          << theModifiedElems << " )";
6098
6099   return aNewGroup._retn();
6100
6101   SMESH_CATCH( SMESH::throwCorbaException );
6102   return 0;
6103 }
6104
6105 //================================================================================
6106 /*!
6107   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6108   This method provided for convenience works as DoubleNodes() described above.
6109   \param theNodes - list of groups of nodes to be doubled
6110   \param theModifiedElems - list of groups of elements to be updated.
6111   \return TRUE if operation has been completed successfully, FALSE otherwise
6112   \sa DoubleNode(), DoubleNodeGroup(), DoubleNodes()
6113 */
6114 //================================================================================
6115
6116 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
6117                                                     const SMESH::ListOfGroups& theModifiedElems )
6118   throw (SALOME::SALOME_Exception)
6119 {
6120   SMESH_TRY;
6121   initData();
6122
6123   std::list< int > aNodes;
6124   int i, n, j, m;
6125   for ( i = 0, n = theNodes.length(); i < n; i++ )
6126   {
6127     SMESH::SMESH_GroupBase_var aGrp = theNodes[ i ];
6128     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() == SMESH::NODE )
6129     {
6130       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6131       for ( j = 0, m = aCurr->length(); j < m; j++ )
6132         aNodes.push_back( aCurr[ j ] );
6133     }
6134   }
6135
6136   std::list< int > anElems;
6137   for ( i = 0, n = theModifiedElems.length(); i < n; i++ )
6138   {
6139     SMESH::SMESH_GroupBase_var aGrp = theModifiedElems[ i ];
6140     if ( !CORBA::is_nil( aGrp ) && aGrp->GetType() != SMESH::NODE )
6141     {
6142       SMESH::long_array_var aCurr = aGrp->GetListOfID();
6143       for ( j = 0, m = aCurr->length(); j < m; j++ )
6144         anElems.push_back( aCurr[ j ] );
6145     }
6146   }
6147
6148   bool aResult = getEditor().DoubleNodes( aNodes, anElems );
6149
6150   declareMeshModified( /*isReComputeSafe=*/false );
6151
6152   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
6153
6154   return aResult;
6155
6156   SMESH_CATCH( SMESH::throwCorbaException );
6157   return 0;
6158 }
6159
6160 //================================================================================
6161 /*!
6162  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6163  * Works as DoubleNodeGroups(), but returns a new group with newly created nodes.
6164  * \param theNodes - group of nodes to be doubled.
6165  * \param theModifiedElems - group of elements to be updated.
6166  * \return a new group with newly created nodes
6167  * \sa DoubleNodeGroups()
6168  */
6169 //================================================================================
6170
6171 SMESH::SMESH_Group_ptr
6172 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
6173                                          const SMESH::ListOfGroups& theModifiedElems )
6174   throw (SALOME::SALOME_Exception)
6175 {
6176   SMESH::SMESH_Group_var aNewGroup;
6177
6178   TPythonDump pyDump; // suppress dump by the next line
6179
6180   bool aResult = DoubleNodeGroups( theNodes, theModifiedElems );
6181
6182   if ( aResult )
6183   {
6184     // Create group with newly created nodes
6185     SMESH::long_array_var anIds = GetLastCreatedNodes();
6186     if (anIds->length() > 0) {
6187       string anUnindexedName (theNodes[0]->GetName());
6188       string aNewName = generateGroupName(anUnindexedName + "_double");
6189       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6190       aNewGroup->Add(anIds);
6191       pyDump << aNewGroup << " = ";
6192     }
6193   }
6194
6195   pyDump << this << ".DoubleNodeGroupsNew( " << theNodes << ", "
6196          << theModifiedElems << " )";
6197
6198   return aNewGroup._retn();
6199 }
6200
6201
6202 //================================================================================
6203 /*!
6204   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6205   \param theElems - the list of elements (edges or faces) to be replicated
6206   The nodes for duplication could be found from these elements
6207   \param theNodesNot - list of nodes to NOT replicate
6208   \param theAffectedElems - the list of elements (cells and edges) to which the
6209   replicated nodes should be associated to.
6210   \return TRUE if operation has been completed successfully, FALSE otherwise
6211   \sa DoubleNodeGroup(), DoubleNodeGroups()
6212 */
6213 //================================================================================
6214
6215 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
6216                                                    const SMESH::long_array& theNodesNot,
6217                                                    const SMESH::long_array& theAffectedElems )
6218   throw (SALOME::SALOME_Exception)
6219 {
6220   SMESH_TRY;
6221   initData();
6222
6223   SMESHDS_Mesh* aMeshDS = getMeshDS();
6224   TIDSortedElemSet anElems, aNodes, anAffected;
6225   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6226   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6227   arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
6228
6229   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6230
6231   // Update Python script
6232   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
6233                 << theNodesNot << ", " << theAffectedElems << " )";
6234
6235   declareMeshModified( /*isReComputeSafe=*/false );
6236   return aResult;
6237
6238   SMESH_CATCH( SMESH::throwCorbaException );
6239   return 0;
6240 }
6241
6242 //================================================================================
6243 /*!
6244   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6245   \param theElems - the list of elements (edges or faces) to be replicated
6246   The nodes for duplication could be found from these elements
6247   \param theNodesNot - list of nodes to NOT replicate
6248   \param theShape - shape to detect affected elements (element which geometric center
6249   located on or inside shape).
6250   The replicated nodes should be associated to affected elements.
6251   \return TRUE if operation has been completed successfully, FALSE otherwise
6252   \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
6253 */
6254 //================================================================================
6255
6256 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
6257                                                             const SMESH::long_array& theNodesNot,
6258                                                             GEOM::GEOM_Object_ptr    theShape )
6259   throw (SALOME::SALOME_Exception)
6260 {
6261   SMESH_TRY;
6262   initData();
6263
6264
6265   SMESHDS_Mesh* aMeshDS = getMeshDS();
6266   TIDSortedElemSet anElems, aNodes;
6267   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
6268   arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
6269
6270   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6271   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6272
6273   // Update Python script
6274   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
6275                 << theNodesNot << ", " << theShape << " )";
6276
6277   declareMeshModified( /*isReComputeSafe=*/false );
6278   return aResult;
6279
6280   SMESH_CATCH( SMESH::throwCorbaException );
6281   return 0;
6282 }
6283
6284 //================================================================================
6285 /*!
6286   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6287   \param theElems - group of of elements (edges or faces) to be replicated
6288   \param theNodesNot - group of nodes not to replicated
6289   \param theAffectedElems - group of elements to which the replicated nodes
6290   should be associated to.
6291   \return TRUE if operation has been completed successfully, FALSE otherwise
6292   \sa DoubleNodes(), DoubleNodeGroups()
6293 */
6294 //================================================================================
6295
6296 CORBA::Boolean
6297 SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
6298                                         SMESH::SMESH_GroupBase_ptr theNodesNot,
6299                                         SMESH::SMESH_GroupBase_ptr theAffectedElems)
6300   throw (SALOME::SALOME_Exception)
6301 {
6302   SMESH_TRY;
6303   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6304     return false;
6305
6306   initData();
6307
6308
6309   SMESHDS_Mesh* aMeshDS = getMeshDS();
6310   TIDSortedElemSet anElems, aNodes, anAffected;
6311   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6312   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6313   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6314
6315   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6316
6317   // Update Python script
6318   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
6319                 << theNodesNot << ", " << theAffectedElems << " )";
6320
6321   declareMeshModified( /*isReComputeSafe=*/false );
6322   return aResult;
6323
6324   SMESH_CATCH( SMESH::throwCorbaException );
6325   return 0;
6326 }
6327
6328 //================================================================================
6329 /*!
6330  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6331  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6332  * \param theElems - group of of elements (edges or faces) to be replicated
6333  * \param theNodesNot - group of nodes not to replicated
6334  * \param theAffectedElems - group of elements to which the replicated nodes
6335  *        should be associated to.
6336  * \return a new group with newly created elements
6337  * \sa DoubleNodeElemGroup()
6338  */
6339 //================================================================================
6340
6341 SMESH::SMESH_Group_ptr
6342 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
6343                                            SMESH::SMESH_GroupBase_ptr theNodesNot,
6344                                            SMESH::SMESH_GroupBase_ptr theAffectedElems)
6345   throw (SALOME::SALOME_Exception)
6346 {
6347   TPythonDump pyDump;
6348   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
6349                                                                theNodesNot,
6350                                                                theAffectedElems,
6351                                                                true, false );
6352   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6353   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6354
6355   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupNew( "
6356          << theElems         << ", "
6357          << theNodesNot      << ", "
6358          << theAffectedElems << " )";
6359
6360   return elemGroup._retn();
6361 }
6362
6363 //================================================================================
6364 /*!
6365  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6366  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
6367  * \param theElems - group of of elements (edges or faces) to be replicated
6368  * \param theNodesNot - group of nodes not to replicated
6369  * \param theAffectedElems - group of elements to which the replicated nodes
6370  *        should be associated to.
6371  * \return a new group with newly created elements
6372  * \sa DoubleNodeElemGroup()
6373  */
6374 //================================================================================
6375
6376 SMESH::ListOfGroups*
6377 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
6378                                             SMESH::SMESH_GroupBase_ptr theNodesNot,
6379                                             SMESH::SMESH_GroupBase_ptr theAffectedElems,
6380                                             CORBA::Boolean             theElemGroupNeeded,
6381                                             CORBA::Boolean             theNodeGroupNeeded)
6382   throw (SALOME::SALOME_Exception)
6383 {
6384   SMESH_TRY;
6385   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6386   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6387   aTwoGroups->length( 2 );
6388
6389   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6390     return aTwoGroups._retn();
6391
6392   initData();
6393
6394
6395   SMESHDS_Mesh* aMeshDS = getMeshDS();
6396   TIDSortedElemSet anElems, aNodes, anAffected;
6397   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6398   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6399   idSourceToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
6400
6401
6402   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6403
6404   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6405
6406   TPythonDump pyDump;
6407
6408   if ( aResult )
6409   {
6410     // Create group with newly created elements
6411     CORBA::String_var elemGroupName = theElems->GetName();
6412     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6413     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6414     {
6415       SMESH::long_array_var anIds = GetLastCreatedElems();
6416       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6417       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6418       aNewElemGroup->Add(anIds);
6419     }
6420     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6421     {
6422       SMESH::long_array_var anIds = GetLastCreatedNodes();
6423       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6424       aNewNodeGroup->Add(anIds);
6425     }
6426   }
6427
6428   // Update Python script
6429
6430   pyDump << "[ ";
6431   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6432   else                            pyDump << aNewElemGroup << ", ";
6433   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6434   else                            pyDump << aNewNodeGroup << " ] = ";
6435
6436   pyDump << this << ".DoubleNodeElemGroup2New( " << theElems << ", "
6437          << theNodesNot        << ", "
6438          << theAffectedElems   << ", "
6439          << theElemGroupNeeded << ", "
6440          << theNodeGroupNeeded <<" )";
6441
6442   aTwoGroups[0] = aNewElemGroup._retn();
6443   aTwoGroups[1] = aNewNodeGroup._retn();
6444   return aTwoGroups._retn();
6445
6446   SMESH_CATCH( SMESH::throwCorbaException );
6447   return 0;
6448 }
6449
6450 //================================================================================
6451 /*!
6452   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6453   \param theElems - group of of elements (edges or faces) to be replicated
6454   \param theNodesNot - group of nodes not to replicated
6455   \param theShape - shape to detect affected elements (element which geometric center
6456   located on or inside shape).
6457   The replicated nodes should be associated to affected elements.
6458   \return TRUE if operation has been completed successfully, FALSE otherwise
6459   \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
6460 */
6461 //================================================================================
6462
6463 CORBA::Boolean
6464 SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
6465                                                 SMESH::SMESH_GroupBase_ptr theNodesNot,
6466                                                 GEOM::GEOM_Object_ptr      theShape )
6467   throw (SALOME::SALOME_Exception)
6468 {
6469   SMESH_TRY;
6470   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
6471     return false;
6472
6473   initData();
6474
6475
6476   SMESHDS_Mesh* aMeshDS = getMeshDS();
6477   TIDSortedElemSet anElems, aNodes, anAffected;
6478   idSourceToSet( theElems, aMeshDS, anElems, SMDSAbs_All );
6479   idSourceToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node );
6480
6481   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6482   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6483
6484
6485   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6486
6487   // Update Python script
6488   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
6489                 << theNodesNot << ", " << theShape << " )";
6490   return aResult;
6491
6492   SMESH_CATCH( SMESH::throwCorbaException );
6493   return 0;
6494 }
6495
6496 //================================================================================
6497 /*!
6498  * \brief Re-load elements from a list of groups into a TIDSortedElemSet
6499  *  \param [in] theGrpList - groups
6500  *  \param [in] theMeshDS -  mesh
6501  *  \param [out] theElemSet - set of elements
6502  *  \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
6503  */
6504 //================================================================================
6505
6506 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
6507                              SMESHDS_Mesh*              theMeshDS,
6508                              TIDSortedElemSet&          theElemSet,
6509                              const bool                 theIsNodeGrp)
6510 {
6511   for ( int i = 0, n = theGrpList.length(); i < n; i++ )
6512   {
6513     SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
6514     if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE
6515                                     : aGrp->GetType() != SMESH::NODE ) )
6516     {
6517       SMESH::long_array_var anIDs = aGrp->GetIDs();
6518       arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
6519     }
6520   }
6521 }
6522
6523 //================================================================================
6524 /*!
6525   \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
6526   This method provided for convenience works as DoubleNodes() described above.
6527   \param theElems - list of groups of elements (edges or faces) to be replicated
6528   \param theNodesNot - list of groups of nodes not to replicated
6529   \param theAffectedElems - group of elements to which the replicated nodes
6530   should be associated to.
6531   \return TRUE if operation has been completed successfully, FALSE otherwise
6532   \sa DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
6533 */
6534 //================================================================================
6535
6536 CORBA::Boolean
6537 SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
6538                                          const SMESH::ListOfGroups& theNodesNot,
6539                                          const SMESH::ListOfGroups& theAffectedElems)
6540   throw (SALOME::SALOME_Exception)
6541 {
6542   SMESH_TRY;
6543   initData();
6544
6545
6546   SMESHDS_Mesh* aMeshDS = getMeshDS();
6547   TIDSortedElemSet anElems, aNodes, anAffected;
6548   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6549   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6550   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6551
6552   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6553
6554   // Update Python script
6555   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
6556                 << &theNodesNot << ", " << &theAffectedElems << " )";
6557
6558   declareMeshModified( /*isReComputeSafe=*/false );
6559   return aResult;
6560
6561   SMESH_CATCH( SMESH::throwCorbaException );
6562   return 0;
6563 }
6564
6565 //================================================================================
6566 /*!
6567  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6568  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6569   \param theElems - list of groups of elements (edges or faces) to be replicated
6570   \param theNodesNot - list of groups of nodes not to replicated
6571   \param theAffectedElems - group of elements to which the replicated nodes
6572   should be associated to.
6573  * \return a new group with newly created elements
6574  * \sa DoubleNodeElemGroups()
6575  */
6576 //================================================================================
6577
6578 SMESH::SMESH_Group_ptr
6579 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
6580                                             const SMESH::ListOfGroups& theNodesNot,
6581                                             const SMESH::ListOfGroups& theAffectedElems)
6582   throw (SALOME::SALOME_Exception)
6583 {
6584   TPythonDump pyDump;
6585   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
6586                                                                 theNodesNot,
6587                                                                 theAffectedElems,
6588                                                                 true, false );
6589   SMESH::SMESH_GroupBase_var baseGroup = twoGroups[0].in();
6590   SMESH::SMESH_Group_var     elemGroup = SMESH::SMESH_Group::_narrow( baseGroup );
6591
6592   pyDump << elemGroup << " = " << this << ".DoubleNodeElemGroupsNew( "
6593          << theElems         << ", "
6594          << theNodesNot      << ", "
6595          << theAffectedElems << " )";
6596
6597   return elemGroup._retn();
6598 }
6599
6600 //================================================================================
6601 /*!
6602  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6603  * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
6604   \param theElems - list of groups of elements (edges or faces) to be replicated
6605   \param theNodesNot - list of groups of nodes not to replicated
6606   \param theAffectedElems - group of elements to which the replicated nodes
6607   should be associated to.
6608  * \return a new group with newly created elements
6609  * \sa DoubleNodeElemGroups()
6610  */
6611 //================================================================================
6612
6613 SMESH::ListOfGroups*
6614 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
6615                                              const SMESH::ListOfGroups& theNodesNot,
6616                                              const SMESH::ListOfGroups& theAffectedElems,
6617                                              CORBA::Boolean             theElemGroupNeeded,
6618                                              CORBA::Boolean             theNodeGroupNeeded)
6619   throw (SALOME::SALOME_Exception)
6620 {
6621   SMESH_TRY;
6622   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
6623   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
6624   aTwoGroups->length( 2 );
6625   
6626   initData();
6627
6628
6629   SMESHDS_Mesh* aMeshDS = getMeshDS();
6630   TIDSortedElemSet anElems, aNodes, anAffected;
6631   listOfGroupToSet(theElems, aMeshDS, anElems, false );
6632   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6633   listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
6634
6635   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
6636
6637   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6638
6639   TPythonDump pyDump;
6640   if ( aResult )
6641   {
6642     // Create group with newly created elements
6643     CORBA::String_var elemGroupName = theElems[0]->GetName();
6644     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
6645     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
6646     {
6647       SMESH::long_array_var anIds = GetLastCreatedElems();
6648       SMESH::ElementType aGroupType = myMesh_i->GetElementType(anIds[0], true);
6649       aNewElemGroup = myMesh_i->CreateGroup(aGroupType, aNewName.c_str());
6650       aNewElemGroup->Add(anIds);
6651     }
6652     if ( !getEditor().GetLastCreatedNodes().IsEmpty() && theNodeGroupNeeded )
6653     {
6654       SMESH::long_array_var anIds = GetLastCreatedNodes();
6655       aNewNodeGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
6656       aNewNodeGroup->Add(anIds);
6657     }
6658   }
6659
6660   // Update Python script
6661
6662   pyDump << "[ ";
6663   if ( aNewElemGroup->_is_nil() ) pyDump << "nothing, ";
6664   else                            pyDump << aNewElemGroup << ", ";
6665   if ( aNewNodeGroup->_is_nil() ) pyDump << "nothing ] = ";
6666   else                            pyDump << aNewNodeGroup << " ] = ";
6667
6668   pyDump << this << ".DoubleNodeElemGroups2New( " << &theElems << ", "
6669          << &theNodesNot       << ", "
6670          << &theAffectedElems  << ", "
6671          << theElemGroupNeeded << ", "
6672          << theNodeGroupNeeded << " )";
6673
6674   aTwoGroups[0] = aNewElemGroup._retn();
6675   aTwoGroups[1] = aNewNodeGroup._retn();
6676   return aTwoGroups._retn();
6677
6678   SMESH_CATCH( SMESH::throwCorbaException );
6679   return 0;
6680 }
6681
6682 //================================================================================
6683 /*!
6684   \brief Creates a hole in a mesh by doubling the nodes of some particular elements
6685   This method provided for convenience works as DoubleNodes() described above.
6686   \param theElems - list of groups of elements (edges or faces) to be replicated
6687   \param theNodesNot - list of groups of nodes not to replicated
6688   \param theShape - shape to detect affected elements (element which geometric center
6689   located on or inside shape).
6690   The replicated nodes should be associated to affected elements.
6691   \return TRUE if operation has been completed successfully, FALSE otherwise
6692   \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
6693 */
6694 //================================================================================
6695
6696 CORBA::Boolean
6697 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
6698                                                  const SMESH::ListOfGroups& theNodesNot,
6699                                                  GEOM::GEOM_Object_ptr      theShape )
6700   throw (SALOME::SALOME_Exception)
6701 {
6702   SMESH_TRY;
6703   initData();
6704
6705
6706   SMESHDS_Mesh* aMeshDS = getMeshDS();
6707   TIDSortedElemSet anElems, aNodes;
6708   listOfGroupToSet(theElems, aMeshDS, anElems,false );
6709   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
6710
6711   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
6712   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
6713
6714   // Update Python script
6715   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
6716                 << &theNodesNot << ", " << theShape << " )";
6717
6718   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6719   return aResult;
6720
6721   SMESH_CATCH( SMESH::throwCorbaException );
6722   return 0;
6723 }
6724
6725 //================================================================================
6726 /*!
6727   \brief Identify the elements that will be affected by node duplication (actual
6728          duplication is not performed.
6729   This method is the first step of DoubleNodeElemGroupsInRegion.
6730   \param theElems - list of groups of elements (edges or faces) to be replicated
6731   \param theNodesNot - list of groups of nodes not to replicated
6732   \param theShape - shape to detect affected elements (element which geometric center
6733          located on or inside shape).
6734          The replicated nodes should be associated to affected elements.
6735   \return groups of affected elements
6736   \sa DoubleNodeElemGroupsInRegion()
6737 */
6738 //================================================================================
6739 SMESH::ListOfGroups*
6740 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
6741                                                 const SMESH::ListOfGroups& theNodesNot,
6742                                                 GEOM::GEOM_Object_ptr      theShape )
6743   throw (SALOME::SALOME_Exception)
6744 {
6745   SMESH_TRY;
6746   MESSAGE("AffectedElemGroupsInRegion");
6747   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
6748   bool isEdgeGroup = false;
6749   bool isFaceGroup = false;
6750   bool isVolumeGroup = false;
6751   SMESH::SMESH_Group_var aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE, "affectedEdges");
6752   SMESH::SMESH_Group_var aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE, "affectedFaces");
6753   SMESH::SMESH_Group_var aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME, "affectedVolumes");
6754
6755   initData();
6756
6757   ::SMESH_MeshEditor aMeshEditor(myMesh);
6758
6759   SMESHDS_Mesh* aMeshDS = getMeshDS();
6760   TIDSortedElemSet anElems, aNodes;
6761   listOfGroupToSet(theElems, aMeshDS, anElems, false);
6762   listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true);
6763
6764   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape(theShape);
6765   TIDSortedElemSet anAffected;
6766   bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
6767
6768
6769   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6770
6771   TPythonDump pyDump;
6772   if (aResult)
6773   {
6774     int lg = anAffected.size();
6775     MESSAGE("lg="<< lg);
6776     SMESH::long_array_var volumeIds = new SMESH::long_array;
6777     volumeIds->length(lg);
6778     SMESH::long_array_var faceIds = new SMESH::long_array;
6779     faceIds->length(lg);
6780     SMESH::long_array_var edgeIds = new SMESH::long_array;
6781     edgeIds->length(lg);
6782     int ivol = 0;
6783     int iface = 0;
6784     int iedge = 0;
6785
6786     TIDSortedElemSet::const_iterator eIt = anAffected.begin();
6787     for (; eIt != anAffected.end(); ++eIt)
6788     {
6789       const SMDS_MeshElement* anElem = *eIt;
6790       if (!anElem)
6791         continue;
6792       int elemId = anElem->GetID();
6793       if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
6794         volumeIds[ivol++] = elemId;
6795       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
6796         faceIds[iface++] = elemId;
6797       else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
6798         edgeIds[iedge++] = elemId;
6799     }
6800     volumeIds->length(ivol);
6801     faceIds->length(iface);
6802     edgeIds->length(iedge);
6803
6804     aNewVolumeGroup->Add(volumeIds);
6805     aNewFaceGroup->Add(faceIds);
6806     aNewEdgeGroup->Add(edgeIds);
6807     isVolumeGroup = (aNewVolumeGroup->Size() > 0);
6808     isFaceGroup = (aNewFaceGroup->Size() > 0);
6809     isEdgeGroup = (aNewEdgeGroup->Size() > 0);
6810   }
6811
6812   int nbGroups = 0;
6813   if (isEdgeGroup)   nbGroups++;
6814   if (isFaceGroup)   nbGroups++;
6815   if (isVolumeGroup) nbGroups++;
6816   aListOfGroups->length(nbGroups);
6817
6818   int i = 0;
6819   if (isEdgeGroup)   aListOfGroups[i++] = aNewEdgeGroup._retn();
6820   if (isFaceGroup)   aListOfGroups[i++] = aNewFaceGroup._retn();
6821   if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
6822
6823   // Update Python script
6824
6825   pyDump << "[ ";
6826   if (isEdgeGroup)   pyDump << aNewEdgeGroup << ", ";
6827   if (isFaceGroup)   pyDump << aNewFaceGroup << ", ";
6828   if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
6829   pyDump << "] = ";
6830   pyDump << this << ".AffectedElemGroupsInRegion( "
6831          << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
6832
6833   return aListOfGroups._retn();
6834
6835   SMESH_CATCH( SMESH::throwCorbaException );
6836   return 0;
6837 }
6838
6839 //================================================================================
6840 /*!
6841   \brief Generated skin mesh (containing 2D cells) from 3D mesh
6842    The created 2D mesh elements based on nodes of free faces of boundary volumes
6843   \return TRUE if operation has been completed successfully, FALSE otherwise
6844 */
6845 //================================================================================
6846
6847 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
6848   throw (SALOME::SALOME_Exception)
6849 {
6850   SMESH_TRY;
6851   initData();
6852
6853   bool aResult = getEditor().Make2DMeshFrom3D();
6854
6855   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
6856
6857   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6858   return aResult;
6859
6860   SMESH_CATCH( SMESH::throwCorbaException );
6861   return false;
6862 }
6863
6864 //================================================================================
6865 /*!
6866  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
6867  * The list of groups must contain at least two groups. The groups have to be disjoint:
6868  * no common element into two different groups.
6869  * The nodes of the internal faces at the boundaries of the groups are doubled.
6870  * Optionally, the internal faces are replaced by flat elements.
6871  * Triangles are transformed into prisms, and quadrangles into hexahedrons.
6872  * The flat elements are stored in groups of volumes.
6873  * These groups are named according to the position of the group in the list:
6874  * 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.
6875  * 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.
6876  * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
6877  * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
6878  * @param theDomains - list of groups of volumes
6879  * @param createJointElems - if TRUE, create the elements
6880  * @return TRUE if operation has been completed successfully, FALSE otherwise
6881  */
6882 //================================================================================
6883
6884 CORBA::Boolean
6885 SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
6886                                                   CORBA::Boolean             createJointElems )
6887   throw (SALOME::SALOME_Exception)
6888 {
6889   bool aResult = false;
6890
6891   SMESH_TRY;
6892   initData();
6893
6894   SMESHDS_Mesh* aMeshDS = getMeshDS();
6895
6896   // MESSAGE("theDomains.length = "<<theDomains.length());
6897   if ( theDomains.length() <= 1 )
6898     THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
6899   vector<TIDSortedElemSet> domains;
6900   domains.clear();
6901
6902   for ( int i = 0, n = theDomains.length(); i < n; i++ )
6903   {
6904     SMESH::SMESH_GroupBase_var aGrp = theDomains[ i ];
6905     if ( !CORBA::is_nil( aGrp ) /*&& ( aGrp->GetType() != SMESH::NODE )*/ )
6906     {
6907 //      if ( aGrp->GetType() != SMESH::VOLUME )
6908 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
6909       TIDSortedElemSet domain;
6910       domain.clear();
6911       domains.push_back(domain);
6912       SMESH::long_array_var anIDs = aGrp->GetIDs();
6913       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
6914     }
6915   }
6916
6917   aResult = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems );
6918   // TODO publish the groups of flat elements in study
6919
6920   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6921
6922   // Update Python script
6923   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
6924       << ", " << createJointElems << " )";
6925
6926   SMESH_CATCH( SMESH::throwCorbaException );
6927
6928   return aResult;
6929 }
6930
6931 //================================================================================
6932 /*!
6933  * \brief Double nodes on some external faces and create flat elements.
6934  * Flat elements are mainly used by some types of mechanic calculations.
6935  *
6936  * Each group of the list must be constituted of faces.
6937  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
6938  * @param theGroupsOfFaces - list of groups of faces
6939  * @return TRUE if operation has been completed successfully, FALSE otherwise
6940  */
6941 //================================================================================
6942
6943 CORBA::Boolean
6944 SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
6945   throw (SALOME::SALOME_Exception)
6946 {
6947   SMESH_TRY;
6948   initData();
6949
6950   SMESHDS_Mesh* aMeshDS = getMeshDS();
6951
6952   vector<TIDSortedElemSet> faceGroups;
6953   faceGroups.clear();
6954
6955   for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
6956   {
6957     SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
6958     if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
6959     {
6960       TIDSortedElemSet faceGroup;
6961       faceGroup.clear();
6962       faceGroups.push_back(faceGroup);
6963       SMESH::long_array_var anIDs = aGrp->GetIDs();
6964       arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
6965     }
6966   }
6967
6968   bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
6969   // TODO publish the groups of flat elements in study
6970
6971   declareMeshModified( /*isReComputeSafe=*/ !aResult );
6972
6973   // Update Python script
6974   TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
6975   return aResult;
6976
6977   SMESH_CATCH( SMESH::throwCorbaException );
6978   return false;
6979 }
6980
6981 //================================================================================
6982 /*!
6983  *  \brief Identify all the elements around a geom shape, get the faces delimiting
6984  *         the hole.
6985  *
6986  *  Build groups of volume to remove, groups of faces to replace on the skin of the
6987  *  object, groups of faces to remove inside the object, (idem edges).
6988  *  Build ordered list of nodes at the border of each group of faces to replace
6989  *  (to be used to build a geom subshape).
6990  */
6991 //================================================================================
6992
6993 void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double                  radius,
6994                                         GEOM::GEOM_Object_ptr          theShape,
6995                                         const char*                    groupName,
6996                                         const SMESH::double_array&     theNodesCoords,
6997                                         SMESH::array_of_long_array_out GroupsOfNodes)
6998   throw (SALOME::SALOME_Exception)
6999 {
7000   SMESH_TRY;
7001
7002   initData();
7003   std::vector<std::vector<int> > aListOfListOfNodes;
7004   ::SMESH_MeshEditor aMeshEditor( myMesh );
7005
7006   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
7007   if ( !theNodeSearcher )
7008     theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
7009
7010   vector<double> nodesCoords;
7011   for (int i = 0; i < theNodesCoords.length(); i++)
7012   {
7013     nodesCoords.push_back( theNodesCoords[i] );
7014   }
7015
7016   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
7017   aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
7018                              nodesCoords, aListOfListOfNodes);
7019
7020   GroupsOfNodes = new SMESH::array_of_long_array;
7021   GroupsOfNodes->length( aListOfListOfNodes.size() );
7022   std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
7023   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
7024   {
7025     vector<int>& aListOfNodes = *llIt;
7026     vector<int>::iterator lIt = aListOfNodes.begin();;
7027     SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
7028     aGroup.length( aListOfNodes.size() );
7029     for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
7030       aGroup[ j ] = (*lIt);
7031   }
7032   TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
7033                 << radius << ", "
7034                 << theShape
7035                 << ", '" << groupName << "', "
7036                 << theNodesCoords << " )";
7037
7038   SMESH_CATCH( SMESH::throwCorbaException );
7039 }
7040
7041 // issue 20749 ===================================================================
7042 /*!
7043  * \brief Creates missing boundary elements
7044  *  \param elements - elements whose boundary is to be checked
7045  *  \param dimension - defines type of boundary elements to create
7046  *  \param groupName - a name of group to store created boundary elements in,
7047  *                     "" means not to create the group
7048  *  \param meshName - a name of new mesh to store created boundary elements in,
7049  *                     "" means not to create the new mesh
7050  *  \param toCopyElements - if true, the checked elements will be copied into the new mesh
7051  *  \param toCopyExistingBondary - if true, not only new but also pre-existing
7052  *                                boundary elements will be copied into the new mesh
7053  *  \param group - returns the create group, if any
7054  *  \retval SMESH::SMESH_Mesh - the mesh where elements were added to
7055  */
7056 // ================================================================================
7057
7058 SMESH::SMESH_Mesh_ptr
7059 SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
7060                                      SMESH::Bnd_Dimension      dim,
7061                                      const char*               groupName,
7062                                      const char*               meshName,
7063                                      CORBA::Boolean            toCopyElements,
7064                                      CORBA::Boolean            toCopyExistingBondary,
7065                                      SMESH::SMESH_Group_out    group)
7066   throw (SALOME::SALOME_Exception)
7067 {
7068   SMESH_TRY;
7069   initData();
7070
7071   if ( dim > SMESH::BND_1DFROM2D )
7072     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7073
7074   SMESHDS_Mesh* aMeshDS = getMeshDS();
7075
7076   SMESH::SMESH_Mesh_var mesh_var;
7077   SMESH::SMESH_Group_var group_var;
7078
7079   TPythonDump pyDump;
7080
7081   TIDSortedElemSet elements;
7082   SMDSAbs_ElementType elemType = (dim == SMESH::BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
7083   prepareIdSource( idSource );
7084   if ( idSourceToSet( idSource, aMeshDS, elements, elemType,/*emptyIfIsMesh=*/true ))
7085   {
7086     // mesh to fill in
7087     mesh_var =
7088       strlen(meshName) ? makeMesh(meshName) : SMESH::SMESH_Mesh::_duplicate(myMesh_i->_this());
7089     SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7090     // other mesh
7091     SMESH_Mesh* smesh_mesh = (mesh_i==myMesh_i) ? (SMESH_Mesh*)0 : &mesh_i->GetImpl();
7092
7093     // group of new boundary elements
7094     SMESH_Group* smesh_group = 0;
7095     if ( strlen(groupName) )
7096     {
7097       group_var = mesh_i->CreateGroup( SMESH::ElementType(int(elemType)-1),groupName);
7098       if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7099         smesh_group = group_i->GetSmeshGroup();
7100     }
7101
7102     // do it
7103     getEditor().MakeBoundaryMesh( elements,
7104                                   ::SMESH_MeshEditor::Bnd_Dimension(dim),
7105                                   smesh_group,
7106                                   smesh_mesh,
7107                                   toCopyElements,
7108                                   toCopyExistingBondary);
7109
7110     if ( smesh_mesh )
7111       smesh_mesh->GetMeshDS()->Modified();
7112   }
7113
7114   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7115
7116   // result of MakeBoundaryMesh() is a tuple (mesh, group)
7117   if ( mesh_var->_is_nil() )
7118     pyDump << myMesh_i->_this() << ", ";
7119   else
7120     pyDump << mesh_var << ", ";
7121   if ( group_var->_is_nil() )
7122     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7123   else
7124     pyDump << group_var << " = ";
7125   pyDump << this << ".MakeBoundaryMesh( "
7126          << idSource << ", "
7127          << "SMESH." << dimName[int(dim)] << ", "
7128          << "'" << groupName << "', "
7129          << "'" << meshName<< "', "
7130          << toCopyElements << ", "
7131          << toCopyExistingBondary << ")";
7132
7133   group = group_var._retn();
7134   return mesh_var._retn();
7135
7136   SMESH_CATCH( SMESH::throwCorbaException );
7137   return SMESH::SMESH_Mesh::_nil();
7138 }
7139
7140 //================================================================================
7141 /*!
7142  * \brief Creates missing boundary elements
7143  *  \param dimension - defines type of boundary elements to create
7144  *  \param groupName - a name of group to store all boundary elements in,
7145  *    "" means not to create the group
7146  *  \param meshName - a name of a new mesh, which is a copy of the initial 
7147  *    mesh + created boundary elements; "" means not to create the new mesh
7148  *  \param toCopyAll - if true, the whole initial mesh will be copied into
7149  *    the new mesh else only boundary elements will be copied into the new mesh
7150  *  \param groups - optional groups of elements to make boundary around
7151  *  \param mesh - returns the mesh where elements were added to
7152  *  \param group - returns the created group, if any
7153  *  \retval long - number of added boundary elements
7154  */
7155 //================================================================================
7156
7157 CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
7158                                                      const char* groupName,
7159                                                      const char* meshName,
7160                                                      CORBA::Boolean toCopyAll,
7161                                                      const SMESH::ListOfIDSources& groups,
7162                                                      SMESH::SMESH_Mesh_out mesh,
7163                                                      SMESH::SMESH_Group_out group)
7164   throw (SALOME::SALOME_Exception)
7165 {
7166   SMESH_TRY;
7167   initData();
7168
7169   if ( dim > SMESH::BND_1DFROM2D )
7170     THROW_SALOME_CORBA_EXCEPTION("Invalid boundary dimension", SALOME::BAD_PARAM);
7171
7172   // separate groups belonging to this and other mesh
7173   SMESH::ListOfIDSources_var groupsOfThisMesh = new SMESH::ListOfIDSources;
7174   SMESH::ListOfIDSources_var groupsOfOtherMesh = new SMESH::ListOfIDSources;
7175   groupsOfThisMesh->length( groups.length() );
7176   groupsOfOtherMesh->length( groups.length() );
7177   int nbGroups = 0, nbGroupsOfOtherMesh = 0;
7178   for ( int i = 0; i < groups.length(); ++i )
7179   {
7180     SMESH::SMESH_Mesh_var m = groups[i]->GetMesh();
7181     if ( myMesh_i != SMESH::DownCast<SMESH_Mesh_i*>( m ))
7182       groupsOfOtherMesh[ nbGroupsOfOtherMesh++ ] = groups[i];
7183     else
7184       groupsOfThisMesh[ nbGroups++ ] = groups[i];
7185     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
7186       THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
7187   }
7188   groupsOfThisMesh->length( nbGroups );
7189   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
7190
7191   int nbAdded = 0;
7192   TPythonDump pyDump;
7193
7194   if ( nbGroupsOfOtherMesh > 0 )
7195   {
7196     // process groups belonging to another mesh
7197     SMESH::SMESH_Mesh_var    otherMesh = groupsOfOtherMesh[0]->GetMesh();
7198     SMESH::SMESH_MeshEditor_var editor = otherMesh->GetMeshEditor();
7199     nbAdded += editor->MakeBoundaryElements( dim, groupName, meshName, toCopyAll,
7200                                              groupsOfOtherMesh, mesh, group );
7201   }
7202
7203   SMESH::SMESH_Mesh_var mesh_var;
7204   SMESH::SMESH_Group_var group_var;
7205
7206   // get mesh to fill
7207   mesh_var = SMESH::SMESH_Mesh::_duplicate( myMesh_i->_this() );
7208   const bool toCopyMesh = ( strlen( meshName ) > 0 );
7209   if ( toCopyMesh )
7210   {
7211     if ( toCopyAll )
7212       mesh_var = SMESH_Gen_i::GetSMESHGen()->CopyMesh(mesh_var,
7213                                                       meshName,
7214                                                       /*toCopyGroups=*/false,
7215                                                       /*toKeepIDs=*/true);
7216     else
7217       mesh_var = makeMesh(meshName);
7218   }
7219   SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh_var );
7220   SMESH_Mesh*  tgtMesh = &mesh_i->GetImpl();
7221
7222   // source mesh
7223   SMESH_Mesh*     srcMesh = ( toCopyMesh && !toCopyAll ) ? myMesh : tgtMesh;
7224   SMESHDS_Mesh* srcMeshDS = srcMesh->GetMeshDS();
7225
7226   // group of boundary elements
7227   SMESH_Group* smesh_group = 0;
7228   SMDSAbs_ElementType elemType = (dim == SMESH::BND_2DFROM3D) ? SMDSAbs_Volume : SMDSAbs_Face;
7229   if ( strlen(groupName) )
7230   {
7231     SMESH::ElementType groupType = SMESH::ElementType( int(elemType)-1 );
7232     group_var = mesh_i->CreateGroup( groupType, groupName );
7233     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( group_var ))
7234       smesh_group = group_i->GetSmeshGroup();
7235   }
7236
7237   TIDSortedElemSet elements;
7238
7239   if ( groups.length() > 0 )
7240   {
7241     for ( int i = 0; i < nbGroups; ++i )
7242     {
7243       elements.clear();
7244       if ( idSourceToSet( groupsOfThisMesh[i], srcMeshDS, elements, elemType,/*emptyIfIsMesh=*/0 ))
7245       {
7246         SMESH::Bnd_Dimension bdim = 
7247           ( elemType == SMDSAbs_Volume ) ? SMESH::BND_2DFROM3D : SMESH::BND_1DFROM2D;
7248         nbAdded += getEditor().MakeBoundaryMesh( elements,
7249                                                  ::SMESH_MeshEditor::Bnd_Dimension(bdim),
7250                                                  smesh_group,
7251                                                  tgtMesh,
7252                                                  /*toCopyElements=*/false,
7253                                                  /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7254                                                  /*toAddExistingBondary=*/true,
7255                                                  /*aroundElements=*/true);
7256       }
7257     }
7258   }
7259   else
7260   {
7261     nbAdded += getEditor().MakeBoundaryMesh( elements,
7262                                              ::SMESH_MeshEditor::Bnd_Dimension(dim),
7263                                              smesh_group,
7264                                              tgtMesh,
7265                                              /*toCopyElements=*/false,
7266                                              /*toCopyExistingBondary=*/srcMesh != tgtMesh,
7267                                              /*toAddExistingBondary=*/true);
7268   }
7269   tgtMesh->GetMeshDS()->Modified();
7270
7271   const char* dimName[] = { "BND_2DFROM3D", "BND_1DFROM3D", "BND_1DFROM2D" };
7272
7273   // result of MakeBoundaryElements() is a tuple (nb, mesh, group)
7274   pyDump << "nbAdded, ";
7275   if ( mesh_var->_is_nil() )
7276     pyDump << myMesh_i->_this() << ", ";
7277   else
7278     pyDump << mesh_var << ", ";
7279   if ( group_var->_is_nil() )
7280     pyDump << "_NoneGroup = "; // assignment to None is forbiden
7281   else
7282     pyDump << group_var << " = ";
7283   pyDump << this << ".MakeBoundaryElements( "
7284          << "SMESH." << dimName[int(dim)] << ", "
7285          << "'" << groupName << "', "
7286          << "'" << meshName<< "', "
7287          << toCopyAll << ", "
7288          << groups << ")";
7289
7290   mesh  = mesh_var._retn();
7291   group = group_var._retn();
7292   return nbAdded;
7293
7294   SMESH_CATCH( SMESH::throwCorbaException );
7295   return 0;
7296 }