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