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