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