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