Salome HOME
87e88611289bc893010542658742e0552164cc85
[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,