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