Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 //  File   : SMESH_Mesh_i.cxx
24 //  Author : Paul RASCLE, EDF
25 //  Module : SMESH
26 //
27 #include "SMESH_Mesh_i.hxx"
28
29 #include "SMESH_Filter_i.hxx"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_Group_i.hxx"
32 #include "SMESH_MEDMesh_i.hxx"
33 #include "SMESH_MeshEditor_i.hxx"
34 #include "SMESH_PythonDump.hxx"
35 #include "SMESH_subMesh_i.hxx"
36
37 #include "DriverMED_R_SMESHDS_Mesh.h"
38 #include "DriverMED_W_SMESHDS_Mesh.h"
39 #include "SMDS_VolumeTool.hxx"
40 #include "SMESHDS_Command.hxx"
41 #include "SMESHDS_CommandType.hxx"
42 #include "SMESHDS_GroupOnGeom.hxx"
43 #include "SMESH_Group.hxx"
44 #include "SMESH_MeshEditor.hxx"
45 #include "SMESH_MesherHelper.hxx"
46 #include "SMDS_EdgePosition.hxx"
47 #include "SMDS_FacePosition.hxx"
48
49 #include "OpUtil.hxx"
50 #include "SALOME_NamingService.hxx"
51 #include "Utils_CorbaException.hxx"
52 #include "Utils_ExceptHandlers.hxx"
53 #include "Utils_SINGLETON.hxx"
54 #include "utilities.h"
55
56 // OCCT Includes
57 #include <BRep_Builder.hxx>
58 #include <OSD_Directory.hxx>
59 #include <OSD_File.hxx>
60 #include <OSD_Path.hxx>
61 #include <OSD_Protection.hxx>
62 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
63 #include <TColStd_MapOfInteger.hxx>
64 #include <TColStd_SequenceOfInteger.hxx>
65 #include <TCollection_AsciiString.hxx>
66 #include <TopExp_Explorer.hxx>
67 #include <TopoDS_Compound.hxx>
68
69 // STL Includes
70 #include <string>
71 #include <iostream>
72 #include <sstream>
73 #include <sys/stat.h>
74
75 #ifdef _DEBUG_
76 static int MYDEBUG = 0;
77 #else
78 static int MYDEBUG = 0;
79 #endif
80
81 using namespace std;
82 using SMESH::TPythonDump;
83
84 int SMESH_Mesh_i::myIdGenerator = 0;
85
86
87
88 //=============================================================================
89 /*!
90  *  Constructor
91  */
92 //=============================================================================
93
94 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
95                             SMESH_Gen_i*            gen_i,
96                             CORBA::Long studyId )
97 : SALOME::GenericObj_i( thePOA )
98 {
99   MESSAGE("SMESH_Mesh_i");
100   _impl = NULL;
101   _gen_i = gen_i;
102   _id = myIdGenerator++;
103   _studyId = studyId;
104 }
105
106 //=============================================================================
107 /*!
108  *  Destructor
109  */
110 //=============================================================================
111
112 SMESH_Mesh_i::~SMESH_Mesh_i()
113 {
114   INFOS("~SMESH_Mesh_i");
115   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it;
116   for ( it = _mapGroups.begin(); it != _mapGroups.end(); it++ ) {
117     SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( it->second ).in() );
118     if ( aGroup ) {
119       // this method is colled from destructor of group (PAL6331)
120       //_impl->RemoveGroup( aGroup->GetLocalID() );
121       
122       aGroup->Destroy();
123     }
124   }
125   _mapGroups.clear();
126   delete _impl;
127 }
128
129 //=============================================================================
130 /*!
131  *  SetShape
132  *
133  *  Associates <this> mesh with <theShape> and puts a reference
134  *  to <theShape> into the current study;
135  *  the previous shape is substituted by the new one.
136  */
137 //=============================================================================
138
139 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
140     throw (SALOME::SALOME_Exception)
141 {
142   Unexpect aCatch(SALOME_SalomeException);
143   try {
144     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
145   }
146   catch(SALOME_Exception & S_ex) {
147     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
148   }
149 }
150
151 //================================================================================
152 /*!
153  * \brief return true if mesh has a shape to build a shape on
154  */
155 //================================================================================
156
157 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
158   throw (SALOME::SALOME_Exception)
159 {
160   Unexpect aCatch(SALOME_SalomeException);
161   bool res = false;
162   try {
163     res = _impl->HasShapeToMesh();
164   }
165   catch(SALOME_Exception & S_ex) {
166     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
167   }
168   return res;
169 }
170
171 //=======================================================================
172 //function : GetShapeToMesh
173 //purpose  :
174 //=======================================================================
175
176 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
177   throw (SALOME::SALOME_Exception)
178 {
179   Unexpect aCatch(SALOME_SalomeException);
180   GEOM::GEOM_Object_var aShapeObj;
181   try {
182     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
183     if ( !S.IsNull() )
184       aShapeObj = _gen_i->ShapeToGeomObject( S );
185   }
186   catch(SALOME_Exception & S_ex) {
187     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
188   }
189   return aShapeObj._retn();
190 }
191
192 //================================================================================
193 /*!
194  * \brief Remove all nodes and elements
195  */
196 //================================================================================
197
198 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
199 {
200   Unexpect aCatch(SALOME_SalomeException);
201   try {
202     _impl->Clear();
203   }
204   catch(SALOME_Exception & S_ex) {
205     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
206   }
207   TPythonDump() <<  _this() << ".Clear()";
208 }
209
210 //================================================================================
211 /*!
212  * \brief Remove all nodes and elements for indicated shape
213  */
214 //================================================================================
215
216 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
217   throw (SALOME::SALOME_Exception)
218 {
219   Unexpect aCatch(SALOME_SalomeException);
220   try {
221     _impl->ClearSubMesh( ShapeID );
222   }
223   catch(SALOME_Exception & S_ex) {
224     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
225   }
226 }
227
228 //=============================================================================
229 /*!
230  *
231  */
232 //=============================================================================
233
234 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
235 {
236   SMESH::DriverMED_ReadStatus res;
237   switch (theStatus)
238   {
239   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
240     res = SMESH::DRS_OK; break;
241   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
242     res = SMESH::DRS_EMPTY; break;
243   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
244     res = SMESH::DRS_WARN_RENUMBER; break;
245   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
246     res = SMESH::DRS_WARN_SKIP_ELEM; break;
247   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
248   default:
249     res = SMESH::DRS_FAIL; break;
250   }
251   return res;
252 }
253
254 //=============================================================================
255 /*!
256  *  ImportMEDFile
257  *
258  *  Imports mesh data from MED file
259  */
260 //=============================================================================
261
262 SMESH::DriverMED_ReadStatus
263 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
264   throw ( SALOME::SALOME_Exception )
265 {
266   Unexpect aCatch(SALOME_SalomeException);
267   int status;
268   try {
269     status = _impl->MEDToMesh( theFileName, theMeshName );
270   }
271   catch( SALOME_Exception& S_ex ) {
272     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
273   }
274   catch ( ... ) {
275     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
276   }
277
278   CreateGroupServants();
279
280   int major, minor, release;
281   if( !MED::getMEDVersion( theFileName, major, minor, release ) )
282     major = minor = release = -1;
283   myFileInfo           = new SALOME_MED::MedFileInfo();
284   myFileInfo->fileName = theFileName;
285   myFileInfo->fileSize = 0;
286 #ifdef WIN32
287   struct _stati64 d;
288   if ( ::_stati64( theFileName, &d ) != -1 )
289 #else
290   struct stat64 d;
291   if ( ::stat64( theFileName, &d ) != -1 )
292 #endif
293     myFileInfo->fileSize = d.st_size;
294   myFileInfo->major    = major;
295   myFileInfo->minor    = minor;
296   myFileInfo->release  = release;
297
298   return ConvertDriverMEDReadStatus(status);
299 }
300
301 //================================================================================
302 /*!
303  * \brief Return string representation of a MED file version comprising nbDigits
304  */
305 //================================================================================
306
307 char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits)
308 {
309   std::string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version),
310                                                                nbDigits);
311   return CORBA::string_dup( ver.c_str() );
312 }
313
314 //=============================================================================
315 /*!
316  *  ImportUNVFile
317  *
318  *  Imports mesh data from MED file
319  */
320 //=============================================================================
321
322 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
323   throw ( SALOME::SALOME_Exception )
324 {
325   // Read mesh with name = <theMeshName> into SMESH_Mesh
326   _impl->UNVToMesh( theFileName );
327
328   CreateGroupServants();
329
330   return 1;
331 }
332
333 //=============================================================================
334 /*!
335  *  ImportSTLFile
336  *
337  *  Imports mesh data from STL file
338  */
339 //=============================================================================
340 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
341   throw ( SALOME::SALOME_Exception )
342 {
343   // Read mesh with name = <theMeshName> into SMESH_Mesh
344   _impl->STLToMesh( theFileName );
345
346   return 1;
347 }
348
349 //=============================================================================
350 /*!
351  *  importMEDFile
352  *
353  *  Imports mesh data from MED file
354  */
355 //=============================================================================
356
357 // int SMESH_Mesh_i::importMEDFile( const char* theFileName, const char* theMeshName )
358 // {
359 //   // Read mesh with name = <theMeshName> and all its groups into SMESH_Mesh
360 //   int status = _impl->MEDToMesh( theFileName, theMeshName );
361 //   CreateGroupServants();
362
363 //   return status;
364 // }
365
366 //=============================================================================
367 /*!
368  *
369  */
370 //=============================================================================
371
372 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
373
374 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
375                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
376 {
377   switch (theStatus) {
378   RETURNCASE( HYP_OK            );
379   RETURNCASE( HYP_MISSING       );
380   RETURNCASE( HYP_CONCURENT     );
381   RETURNCASE( HYP_BAD_PARAMETER );
382   RETURNCASE( HYP_HIDDEN_ALGO   );
383   RETURNCASE( HYP_HIDING_ALGO   );
384   RETURNCASE( HYP_UNKNOWN_FATAL );
385   RETURNCASE( HYP_INCOMPATIBLE  );
386   RETURNCASE( HYP_NOTCONFORM    );
387   RETURNCASE( HYP_ALREADY_EXIST );
388   RETURNCASE( HYP_BAD_DIM       );
389   RETURNCASE( HYP_BAD_SUBSHAPE  );
390   RETURNCASE( HYP_BAD_GEOMETRY  );
391   RETURNCASE( HYP_NEED_SHAPE    );
392   default:;
393   }
394   return SMESH::HYP_UNKNOWN_FATAL;
395 }
396
397 //=============================================================================
398 /*!
399  *  AddHypothesis
400  *
401  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
402  *  the SObject actually having a reference to <aSubShape>.
403  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
404  */
405 //=============================================================================
406
407 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
408                                                      SMESH::SMESH_Hypothesis_ptr anHyp)
409   throw(SALOME::SALOME_Exception)
410 {
411   Unexpect aCatch(SALOME_SalomeException);
412   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
413
414   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
415     _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
416                                  aSubShapeObject, anHyp );
417
418   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
419
420   // Update Python script
421   if(_impl->HasShapeToMesh()) {
422     TPythonDump() << "status = " << _this() << ".AddHypothesis( "
423                   << aSubShapeObject << ", " << anHyp << " )";
424   }
425   else {
426     TPythonDump() << "status = " << _this() << ".AddHypothesis( "<< anHyp << " )";
427   }
428   
429   return ConvertHypothesisStatus(status);
430 }
431
432 //=============================================================================
433 /*!
434  *
435  */
436 //=============================================================================
437
438 SMESH_Hypothesis::Hypothesis_Status
439   SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
440                               SMESH::SMESH_Hypothesis_ptr anHyp)
441 {
442   if(MYDEBUG) MESSAGE("addHypothesis");
443
444   if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
445     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
446                                  SALOME::BAD_PARAM);
447
448   SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
449   if (CORBA::is_nil(myHyp))
450     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
451                                  SALOME::BAD_PARAM);
452
453   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
454   try
455   {
456     TopoDS_Shape myLocSubShape;
457     //use PseudoShape in case if mesh has no shape
458     if(HasShapeToMesh())
459       myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
460     else              
461       myLocSubShape = _impl->GetShapeToMesh();
462     
463     int hypId = myHyp->GetId();
464     status = _impl->AddHypothesis(myLocSubShape, hypId);
465     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
466       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
467       // assure there is a corresponding submesh
468       if ( !_impl->IsMainShape( myLocSubShape )) {
469         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
470         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
471           createSubMesh( aSubShapeObject );
472       }
473     }
474   }
475   catch(SALOME_Exception & S_ex)
476   {
477     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
478   }
479   return status;
480 }
481
482 //=============================================================================
483 /*!
484  *
485  */
486 //=============================================================================
487
488 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
489                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
490      throw(SALOME::SALOME_Exception)
491 {
492   Unexpect aCatch(SALOME_SalomeException);
493   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
494
495   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
496     _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
497                                       aSubShapeObject, anHyp );
498
499   // Update Python script
500     // Update Python script
501   if(_impl->HasShapeToMesh()) {
502   TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
503                 << aSubShapeObject << ", " << anHyp << " )";
504   }
505   else {
506     TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
507                   << anHyp << " )";
508   }
509
510   return ConvertHypothesisStatus(status);
511 }
512
513 //=============================================================================
514 /*!
515  *
516  */
517 //=============================================================================
518
519 SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
520                                  SMESH::SMESH_Hypothesis_ptr anHyp)
521 {
522         if(MYDEBUG) MESSAGE("removeHypothesis()");
523         // **** proposer liste de subShape (selection multiple)
524
525         if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
526                 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
527                         SALOME::BAD_PARAM);
528
529         SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
530         if (CORBA::is_nil(myHyp))
531           THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
532                         SALOME::BAD_PARAM);
533
534         SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
535         try
536         {
537                 TopoDS_Shape myLocSubShape;
538                 //use PseudoShape in case if mesh has no shape
539                 if(HasShapeToMesh())
540                   myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
541                 else
542                   myLocSubShape = _impl->GetShapeToMesh();
543                 
544                 int hypId = myHyp->GetId();
545                 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
546                 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
547                   _mapHypo.erase( hypId );
548         }
549         catch(SALOME_Exception & S_ex)
550         {
551                 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
552         }
553         return status;
554 }
555
556 //=============================================================================
557 /*!
558  *
559  */
560 //=============================================================================
561
562 SMESH::ListOfHypothesis *
563         SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
564 throw(SALOME::SALOME_Exception)
565 {
566   Unexpect aCatch(SALOME_SalomeException);
567   if (MYDEBUG) MESSAGE("GetHypothesisList");
568   if (CORBA::is_nil(aSubShapeObject))
569     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
570                                  SALOME::BAD_PARAM);
571
572   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
573
574   try {
575     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
576     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
577     int i = 0, n = aLocalList.size();
578     aList->length( n );
579
580     for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
581       SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
582       if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
583         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
584     }
585
586     aList->length( i );
587   }
588   catch(SALOME_Exception & S_ex) {
589     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
590   }
591
592   return aList._retn();
593 }
594
595 //=============================================================================
596 /*!
597  *
598  */
599 //=============================================================================
600 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
601                                                   const char*           theName )
602      throw(SALOME::SALOME_Exception)
603 {
604   Unexpect aCatch(SALOME_SalomeException);
605   MESSAGE("SMESH_Mesh_i::GetSubMesh");
606   if (CORBA::is_nil(aSubShapeObject))
607     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
608                                  SALOME::BAD_PARAM);
609
610   SMESH::SMESH_subMesh_var subMesh;
611   SMESH::SMESH_Mesh_var    aMesh = SMESH::SMESH_Mesh::_narrow(_this());
612   try {
613     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
614
615     //Get or Create the SMESH_subMesh object implementation
616
617     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
618     subMesh = getSubMesh( subMeshId );
619
620     // create a new subMesh object servant if there is none for the shape
621     if ( subMesh->_is_nil() )
622       subMesh = createSubMesh( aSubShapeObject );
623
624     if ( _gen_i->CanPublishInStudy( subMesh )) {
625       SALOMEDS::SObject_var aSO =
626         _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
627                                subMesh, aSubShapeObject, theName );
628       if ( !aSO->_is_nil()) {
629         // Update Python script
630         TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
631                       << aSubShapeObject << ", '" << theName << "' )";
632       }
633     }
634   }
635   catch(SALOME_Exception & S_ex) {
636     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
637   }
638   return subMesh._retn();
639 }
640
641 //=============================================================================
642 /*!
643  *
644  */
645 //=============================================================================
646
647 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
648      throw (SALOME::SALOME_Exception)
649 {
650   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
651   if ( theSubMesh->_is_nil() )
652     return;
653
654   GEOM::GEOM_Object_var aSubShapeObject;
655   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
656   if ( !aStudy->_is_nil() )  {
657     // Remove submesh's SObject
658     SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
659     if ( !anSO->_is_nil() ) {
660       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
661       SALOMEDS::SObject_var anObj, aRef;
662       if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
663         aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
664
665       aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
666
667       // Update Python script
668       TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
669     }
670   }
671
672   removeSubMesh( theSubMesh, aSubShapeObject.in() );
673 }
674
675 //=============================================================================
676 /*!
677  *  ElementTypeString
678  */
679 //=============================================================================
680 #define CASE2STRING(enum) case SMESH::enum: return "SMESH."#enum;
681 inline TCollection_AsciiString ElementTypeString (SMESH::ElementType theElemType)
682 {
683   switch (theElemType) {
684     CASE2STRING( ALL );
685     CASE2STRING( NODE );
686     CASE2STRING( EDGE );
687     CASE2STRING( FACE );
688     CASE2STRING( VOLUME );
689   default:;
690   }
691   return "";
692 }
693
694 //=============================================================================
695 /*!
696  *
697  */
698 //=============================================================================
699
700 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
701                                                  const char*         theName )
702      throw(SALOME::SALOME_Exception)
703 {
704   Unexpect aCatch(SALOME_SalomeException);
705   SMESH::SMESH_Group_var aNewGroup =
706     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
707
708   if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
709     SALOMEDS::SObject_var aSO =
710       _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
711                            aNewGroup, GEOM::GEOM_Object::_nil(), theName);
712     if ( !aSO->_is_nil()) {
713       // Update Python script
714       TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
715                     << ElementTypeString(theElemType) << ", '" << theName << "' )";
716     }
717   }
718   return aNewGroup._retn();
719 }
720
721
722 //=============================================================================
723 /*!
724  *
725  */
726 //=============================================================================
727 SMESH::SMESH_GroupOnGeom_ptr SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
728                                                                 const char*           theName,
729                                                                 GEOM::GEOM_Object_ptr theGeomObj)
730      throw(SALOME::SALOME_Exception)
731 {
732   Unexpect aCatch(SALOME_SalomeException);
733   SMESH::SMESH_GroupOnGeom_var aNewGroup;
734
735   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
736   if ( !aShape.IsNull() ) {
737     aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
738       ( createGroup( theElemType, theName, aShape ));
739     if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
740       SALOMEDS::SObject_var aSO =
741         _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
742                              aNewGroup, theGeomObj, theName);
743       if ( !aSO->_is_nil()) {
744         // Update Python script
745         TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
746                       << ElementTypeString(theElemType) << ", '" << theName << "', "
747                       << theGeomObj << " )";
748       }
749     }
750   }
751
752   return aNewGroup._retn();
753 }
754
755 //=============================================================================
756 /*!
757  *
758  */
759 //=============================================================================
760
761 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
762      throw (SALOME::SALOME_Exception)
763 {
764   if ( theGroup->_is_nil() )
765     return;
766
767   SMESH_GroupBase_i* aGroup =
768     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
769   if ( !aGroup )
770     return;
771
772   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
773   if ( !aStudy->_is_nil() )  {
774     SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
775
776     if ( !aGroupSO->_is_nil() ) {
777       // Update Python script
778       TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
779
780       // Remove group's SObject
781       aStudy->NewBuilder()->RemoveObjectWithChildren( aGroupSO );
782     }
783   }
784
785   // Remove the group from SMESH data structures
786   removeGroup( aGroup->GetLocalID() );
787 }
788
789 //=============================================================================
790 /*! RemoveGroupWithContents
791  *  Remove group with its contents
792  */
793 //=============================================================================
794 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
795   throw (SALOME::SALOME_Exception)
796 {
797   if ( theGroup->_is_nil() )
798     return;
799
800   SMESH_GroupBase_i* aGroup =
801     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
802   if ( !aGroup )
803     return;
804
805   SMESH::long_array_var anIds = aGroup->GetListOfID();
806   SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
807
808   // Update Python script
809   TPythonDump() << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
810
811   // Remove contents
812   if ( aGroup->GetType() == SMESH::NODE )
813     aMeshEditor->RemoveNodes( anIds );
814   else
815     aMeshEditor->RemoveElements( anIds );
816
817   // Remove group
818   RemoveGroup( theGroup );
819
820   // Clear python lines, created by RemoveNodes/Elements() and RemoveGroup()
821   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
822   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
823 }
824
825
826 //================================================================================
827 /*!
828  * \brief Get the list of groups existing in the mesh
829   * \retval SMESH::ListOfGroups * - list of groups
830  */
831 //================================================================================
832
833 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
834 {
835   Unexpect aCatch(SALOME_SalomeException);
836   if (MYDEBUG) MESSAGE("GetGroups");
837
838   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
839
840   // Python Dump
841   TPythonDump aPythonDump;
842   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
843     aPythonDump << "[ ";
844
845   try {
846     aList->length( _mapGroups.size() );
847     int i = 0;
848     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
849     for ( ; it != _mapGroups.end(); it++ ) {
850       if ( CORBA::is_nil( it->second )) continue;
851       aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
852       // Python Dump
853       if (i > 1) aPythonDump << ", ";
854       aPythonDump << it->second;
855     }
856     aList->length( i );
857   }
858   catch(SALOME_Exception & S_ex) {
859     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
860   }
861
862   // Update Python script
863   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
864     aPythonDump << " ] = " << _this() << ".GetGroups()";
865
866   return aList._retn();
867 }
868 //=============================================================================
869 /*!
870  *  Get number of groups existing in the mesh
871  */
872 //=============================================================================
873
874 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
875 {
876   Unexpect aCatch(SALOME_SalomeException);
877   return _mapGroups.size();
878 }
879
880 //=============================================================================
881 /*! UnionGroups
882  *  New group is created. All mesh elements that are
883  *  present in initial groups are added to the new one
884  */
885 //=============================================================================
886 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
887                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
888                                                   const char* theName )
889   throw (SALOME::SALOME_Exception)
890 {
891   try
892   {
893     if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
894          theGroup1->GetType() != theGroup2->GetType() )
895       return SMESH::SMESH_Group::_nil();
896
897     // Create Union
898     SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
899     if ( aResGrp->_is_nil() )
900       return SMESH::SMESH_Group::_nil();
901
902     SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
903     SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
904
905     TColStd_MapOfInteger aResMap;
906
907     for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
908       aResMap.Add( anIds1[ i1 ] );
909
910     for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
911       aResMap.Add( anIds2[ i2 ] );
912
913     SMESH::long_array_var aResIds = new SMESH::long_array;
914     aResIds->length( aResMap.Extent() );
915
916     int resI = 0;
917     TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
918     for( ; anIter.More(); anIter.Next() )
919       aResIds[ resI++ ] = anIter.Key();
920
921     aResGrp->Add( aResIds );
922
923     // Clear python lines, created by CreateGroup() and Add()
924     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
925     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
926     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
927
928     // Update Python script
929     TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
930                   << theGroup1 << ", " << theGroup2 << ", '"
931                   << theName << "' )";
932
933     return aResGrp._retn();
934   }
935   catch( ... )
936   {
937     return SMESH::SMESH_Group::_nil();
938   }
939 }
940
941 //=============================================================================
942 /*!
943   \brief Union list of groups. New group is created. All mesh elements that are
944    present in initial groups are added to the new one.
945   \param theGroups list of groups
946   \param theName name of group to be created
947   \return pointer on the group
948 */
949 //=============================================================================
950 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
951                                                        const char*                theName )
952 throw (SALOME::SALOME_Exception)
953 {
954   if ( !theName )
955     return SMESH::SMESH_Group::_nil();
956
957   try
958   {
959     NCollection_Map< int > anIds;
960     SMESH::ElementType aType = SMESH::ALL;
961     for ( int g = 0, n = theGroups.length(); g < n; g++ )
962     {
963       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
964       if ( CORBA::is_nil( aGrp ) )
965         continue;
966
967       // check type
968       SMESH::ElementType aCurrType = aGrp->GetType();
969       if ( aType == SMESH::ALL )
970         aType = aCurrType;
971       else 
972       {
973         if ( aType != aCurrType )
974           return SMESH::SMESH_Group::_nil();
975       }
976
977       // unite ids
978       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
979       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
980       {
981         int aCurrId = aCurrIds[ i ];
982         anIds.Add( aCurrId );
983       }
984     }
985
986     // Create group
987     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
988     if ( aResGrp->_is_nil() )
989       return SMESH::SMESH_Group::_nil();
990     
991     // Create array of identifiers
992     SMESH::long_array_var aResIds = new SMESH::long_array;
993     aResIds->length( anIds.Extent() );
994     
995     NCollection_Map< int >::Iterator anIter( anIds );
996     for ( int i = 0; anIter.More(); anIter.Next(), i++ )
997     {
998       aResIds[ i ] = anIter.Value();
999     }
1000     aResGrp->Add( aResIds );
1001
1002     // Clear python lines, created by CreateGroup() and Add()
1003     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1004     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1005     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1006
1007     // Update Python script
1008     
1009     TPythonDump() << aResGrp << " = " << _this() << ".UnionListOfGroups( "
1010                   << &theGroups << ", '" << theName << "' )";
1011
1012     return aResGrp._retn();
1013   }
1014   catch( ... )
1015   {
1016     return SMESH::SMESH_Group::_nil();
1017   }
1018 }
1019
1020 //=============================================================================
1021 /*! IntersectGroups
1022  *  New group is created. All mesh elements that are
1023  *  present in both initial groups are added to the new one.
1024  */
1025 //=============================================================================
1026 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1027                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1028                                                       const char* theName )
1029   throw (SALOME::SALOME_Exception)
1030 {
1031   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1032        theGroup1->GetType() != theGroup2->GetType() )
1033     return SMESH::SMESH_Group::_nil();
1034
1035   // Create Intersection
1036   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1037   if ( aResGrp->_is_nil() )
1038     return aResGrp;
1039
1040   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1041   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1042
1043   TColStd_MapOfInteger aMap1;
1044
1045   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1046     aMap1.Add( anIds1[ i1 ] );
1047
1048   TColStd_SequenceOfInteger aSeq;
1049
1050   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1051     if ( aMap1.Contains( anIds2[ i2 ] ) )
1052       aSeq.Append( anIds2[ i2 ] );
1053
1054   SMESH::long_array_var aResIds = new SMESH::long_array;
1055   aResIds->length( aSeq.Length() );
1056
1057   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1058     aResIds[ resI ] = aSeq( resI + 1 );
1059
1060   aResGrp->Add( aResIds );
1061
1062   // Clear python lines, created by CreateGroup() and Add()
1063   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1064   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1065   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1066
1067   // Update Python script
1068   TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
1069                 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1070
1071   return aResGrp._retn();
1072 }
1073
1074 //=============================================================================
1075 /*!
1076   \brief Intersect list of groups. New group is created. All mesh elements that 
1077   are present in all initial groups simultaneously are added to the new one.
1078   \param theGroups list of groups
1079   \param theName name of group to be created
1080   \return pointer on the group
1081 */
1082 //=============================================================================
1083 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectListOfGroups( 
1084   const SMESH::ListOfGroups& theGroups, const char* theName )
1085 throw (SALOME::SALOME_Exception)
1086 {
1087   if ( !theName )
1088     return SMESH::SMESH_Group::_nil();
1089
1090   try
1091   {
1092     NCollection_DataMap< int, int > anIdToCount;
1093     SMESH::ElementType aType = SMESH::ALL;
1094     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1095     {
1096       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1097       if ( CORBA::is_nil( aGrp ) )
1098         continue;
1099
1100       // check type
1101       SMESH::ElementType aCurrType = aGrp->GetType();
1102       if ( aType == SMESH::ALL )
1103         aType = aCurrType;
1104       else 
1105       {
1106         if ( aType != aCurrType )
1107           return SMESH::SMESH_Group::_nil();
1108       }
1109
1110       // calculates number of occurance ids in groups
1111       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1112       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1113       {
1114         int aCurrId = aCurrIds[ i ];
1115         if ( !anIdToCount.IsBound( aCurrId ) )
1116           anIdToCount.Bind( aCurrId, 1 );
1117         else 
1118           anIdToCount( aCurrId ) = anIdToCount( aCurrId ) + 1;
1119       }
1120     }
1121     
1122     // create map of ids
1123     int nbGrp = theGroups.length();
1124     NCollection_Map< int > anIds;
1125     NCollection_DataMap< int, int >::Iterator anIter( anIdToCount );
1126     for ( ; anIter.More(); anIter.Next() )
1127     {
1128       int aCurrId = anIter.Key();
1129       int aCurrNb = anIter.Value();
1130       if ( aCurrNb == nbGrp )
1131         anIds.Add( aCurrId );
1132     }
1133
1134     // Create group
1135     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1136     if ( aResGrp->_is_nil() )
1137       return SMESH::SMESH_Group::_nil();
1138     
1139     // Create array of identifiers
1140     SMESH::long_array_var aResIds = new SMESH::long_array;
1141     aResIds->length( anIds.Extent() );
1142     
1143     NCollection_Map< int >::Iterator aListIter( anIds );
1144     for ( int i = 0; aListIter.More(); aListIter.Next(), i++ )
1145     {
1146       aResIds[ i ] = aListIter.Value();
1147     }
1148     aResGrp->Add( aResIds );
1149
1150     // Clear python lines, created by CreateGroup() and Add()
1151     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1152     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1153     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1154
1155     // Update Python script
1156     
1157     TPythonDump() << aResGrp << " = " << _this() << ".IntersectListOfGroups( "
1158                   << &theGroups << ", '" << theName << "' )";
1159
1160     return aResGrp._retn();
1161   }
1162   catch( ... )
1163   {
1164     return SMESH::SMESH_Group::_nil();
1165   }
1166 }
1167
1168 //=============================================================================
1169 /*! CutGroups
1170  *  New group is created. All mesh elements that are present in
1171  *  main group but do not present in tool group are added to the new one
1172  */
1173 //=============================================================================
1174 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1175                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1176                                                 const char* theName )
1177   throw (SALOME::SALOME_Exception)
1178 {
1179   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1180        theGroup1->GetType() != theGroup2->GetType() )
1181     return SMESH::SMESH_Group::_nil();
1182
1183   // Perform Cutting
1184   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1185   if ( aResGrp->_is_nil() )
1186     return aResGrp;
1187
1188   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1189   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1190
1191   TColStd_MapOfInteger aMap2;
1192
1193   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1194     aMap2.Add( anIds2[ i2 ] );
1195
1196   TColStd_SequenceOfInteger aSeq;
1197   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1198     if ( !aMap2.Contains( anIds1[ i1 ] ) )
1199       aSeq.Append( anIds1[ i1 ] );
1200
1201   SMESH::long_array_var aResIds = new SMESH::long_array;
1202   aResIds->length( aSeq.Length() );
1203
1204   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1205     aResIds[ resI ] = aSeq( resI + 1 );
1206
1207   aResGrp->Add( aResIds );
1208
1209   // Clear python lines, created by CreateGroup() and Add()
1210   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1211   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1212   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1213
1214   // Update Python script
1215   TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
1216                 << theGroup1 << ", " << theGroup2 << ", '"
1217                 << theName << "' )";
1218
1219   return aResGrp._retn();
1220 }
1221
1222 //=============================================================================
1223 /*!
1224   \brief Cut lists of groups. New group is created. All mesh elements that are 
1225   present in main groups but do not present in tool groups are added to the new one
1226   \param theMainGroups list of main groups
1227   \param theToolGroups list of tool groups
1228   \param theName name of group to be created
1229   \return pointer on the group
1230 */
1231 //=============================================================================
1232 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutListOfGroups( 
1233   const SMESH::ListOfGroups& theMainGroups, 
1234   const SMESH::ListOfGroups& theToolGroups, 
1235   const char* theName )
1236   throw (SALOME::SALOME_Exception)
1237 {
1238   if ( !theName )
1239     return SMESH::SMESH_Group::_nil();
1240
1241   try
1242   {
1243     NCollection_Map< int > aToolIds;
1244     SMESH::ElementType aType = SMESH::ALL;
1245     int g, n;
1246     // iterate through tool groups
1247     for ( g = 0, n = theToolGroups.length(); g < n; g++ )
1248     {
1249       SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1250       if ( CORBA::is_nil( aGrp ) )
1251         continue;
1252
1253       // check type
1254       SMESH::ElementType aCurrType = aGrp->GetType();
1255       if ( aType == SMESH::ALL )
1256         aType = aCurrType;
1257       else 
1258       {
1259         if ( aType != aCurrType )
1260           return SMESH::SMESH_Group::_nil();
1261       }
1262
1263       // unite tool ids
1264       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1265       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1266       {
1267         int aCurrId = aCurrIds[ i ];
1268         aToolIds.Add( aCurrId );
1269       }
1270     }
1271
1272     NCollection_Map< int > anIds; // result
1273
1274     // Iterate through main group 
1275     for ( g = 0, n = theMainGroups.length(); g < n; g++ )
1276     {
1277       SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1278       if ( CORBA::is_nil( aGrp ) )
1279         continue;
1280
1281       // check type
1282       SMESH::ElementType aCurrType = aGrp->GetType();
1283       if ( aType == SMESH::ALL )
1284         aType = aCurrType;
1285       else 
1286       {
1287         if ( aType != aCurrType )
1288           return SMESH::SMESH_Group::_nil();
1289       }
1290
1291       // unite tool ids
1292       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1293       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1294       {
1295         int aCurrId = aCurrIds[ i ];
1296         if ( !aToolIds.Contains( aCurrId ) )
1297           anIds.Add( aCurrId );
1298       }
1299     }
1300
1301     // Create group
1302     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1303     if ( aResGrp->_is_nil() )
1304       return SMESH::SMESH_Group::_nil();
1305     
1306     // Create array of identifiers
1307     SMESH::long_array_var aResIds = new SMESH::long_array;
1308     aResIds->length( anIds.Extent() );
1309     
1310     NCollection_Map< int >::Iterator anIter( anIds );
1311     for ( int i = 0; anIter.More(); anIter.Next(), i++ )
1312     {
1313       aResIds[ i ] = anIter.Value();
1314     }
1315     aResGrp->Add( aResIds );
1316
1317     // Clear python lines, created by CreateGroup() and Add()
1318     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1319     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1320     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1321
1322     // Update Python script
1323
1324     TPythonDump() << aResGrp << " = " << _this() << ".CutListOfGroups( "
1325                   << &theMainGroups << ", " << &theToolGroups << ", '"
1326                   << theName << "' )";
1327     
1328     return aResGrp._retn();
1329   }
1330   catch( ... )
1331   {
1332     return SMESH::SMESH_Group::_nil();
1333   }
1334 }
1335
1336 //=============================================================================
1337 /*!
1338   \brief Create groups of entities from existing groups of superior dimensions 
1339   System 
1340   1) extract all nodes from each group,
1341   2) combine all elements of specified dimension laying on these nodes.
1342   \param theGroups list of source groups 
1343   \param theElemType dimension of elements 
1344   \param theName name of new group
1345   \return pointer on new group
1346 */
1347 //=============================================================================
1348 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateDimGroup( 
1349   const SMESH::ListOfGroups& theGroups, 
1350   SMESH::ElementType         theElemType, 
1351   const char*                theName )
1352   throw (SALOME::SALOME_Exception)
1353 {
1354   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1355
1356   if ( !theName || !aMeshDS )
1357     return SMESH::SMESH_Group::_nil();
1358
1359   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1360
1361   try
1362   {
1363     // Create map of nodes from all groups 
1364
1365     NCollection_Map< int > aNodeMap;
1366     
1367     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1368     {
1369       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1370       if ( CORBA::is_nil( aGrp ) )
1371         continue;
1372
1373       SMESH::ElementType aType = aGrp->GetType();
1374       if ( aType == SMESH::ALL )
1375         continue;
1376       else if ( aType == SMESH::NODE )
1377       {
1378         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1379         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1380         {
1381           int aCurrId = aCurrIds[ i ];
1382           const SMDS_MeshNode* aNode = aMeshDS->FindNode( aCurrId );
1383           if ( aNode )
1384             aNodeMap.Add( aNode->GetID() );
1385         }
1386       }
1387       else 
1388       {
1389         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1390         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1391         {
1392           int aCurrId = aCurrIds[ i ];
1393           const SMDS_MeshElement* anElem = aMeshDS->FindElement( aCurrId );
1394           if ( !anElem )
1395             continue;
1396           SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1397           while( aNodeIter->more() )
1398           {
1399             const SMDS_MeshNode* aNode = 
1400               dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1401             if ( aNode )
1402               aNodeMap.Add( aNode->GetID() );
1403           }
1404         }
1405       }
1406     }
1407
1408     // Get result identifiers 
1409
1410     NCollection_Map< int > aResultIds;
1411     if ( theElemType == SMESH::NODE )
1412     {
1413       NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1414       for ( ; aNodeIter.More(); aNodeIter.Next() )
1415         aResultIds.Add( aNodeIter.Value() );
1416     }
1417     else
1418     {
1419       // Create list of elements of given dimension constructed on the nodes
1420       NCollection_Map< int > anElemList;
1421       NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1422       for ( ; aNodeIter.More(); aNodeIter.Next() )
1423       {
1424         const SMDS_MeshElement* aNode = 
1425           dynamic_cast<const SMDS_MeshElement*>( aMeshDS->FindNode( aNodeIter.Value() ) );
1426         if ( !aNode )
1427           continue;
1428
1429          SMDS_ElemIteratorPtr anElemIter = aNode->elementsIterator( anElemType );
1430         while( anElemIter->more() )
1431         {
1432           const SMDS_MeshElement* anElem = 
1433             dynamic_cast<const SMDS_MeshElement*>( anElemIter->next() );
1434           if ( anElem && anElem->GetType() == anElemType )
1435             anElemList.Add( anElem->GetID() );
1436         }
1437       }
1438
1439       // check whether all nodes of elements are present in nodes map
1440       NCollection_Map< int >::Iterator anIter( anElemList );
1441       for ( ; anIter.More(); anIter.Next() )
1442       {
1443         const SMDS_MeshElement* anElem = aMeshDS->FindElement( anIter.Value() );
1444         if ( !anElem )
1445           continue;
1446
1447         bool isOk = true;
1448         SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1449         while( aNodeIter->more() )
1450         {
1451           const SMDS_MeshNode* aNode = 
1452             dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1453           if ( !aNode || !aNodeMap.Contains( aNode->GetID() ) )
1454           {
1455             isOk = false;
1456             break;
1457           }
1458         } 
1459         if ( isOk )
1460           aResultIds.Add( anElem->GetID() );
1461       }
1462     }
1463
1464     // Create group
1465
1466     SMESH::SMESH_Group_var aResGrp = CreateGroup( theElemType, theName );
1467     if ( aResGrp->_is_nil() )
1468       return SMESH::SMESH_Group::_nil();
1469     
1470     // Create array of identifiers
1471     SMESH::long_array_var aResIds = new SMESH::long_array;
1472     aResIds->length( aResultIds.Extent() );
1473     
1474     NCollection_Map< int >::Iterator aResIter( aResultIds );
1475     for ( int i = 0; aResIter.More(); aResIter.Next(), i++ )
1476       aResIds[ i ] = aResIter.Value();
1477     aResGrp->Add( aResIds );
1478
1479     // Remove strings corresponding to group creation
1480     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1481     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1482     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1483
1484     // Update Python script
1485     
1486     TPythonDump() << aResGrp << " = " << _this() << ".CreateDimGroup( "
1487                   << &theGroups << ", " << theElemType << ", '" << theName << "' )";
1488
1489     return aResGrp._retn();
1490   }
1491   catch( ... )
1492   {
1493     return SMESH::SMESH_Group::_nil();
1494   }
1495 }
1496
1497 //================================================================================
1498 /*!
1499  * \brief Return group items of a group present in a study
1500  */
1501 //================================================================================
1502
1503 static GEOM::GEOM_Object_ptr getGroupItemsFromStudy(CORBA::Object_ptr    theMesh,
1504                                                     SMESH_Gen_i*         theGen,
1505                                                     list<TopoDS_Shape> & theItems)
1506 {
1507   GEOM::GEOM_Object_var groupObj;
1508   SALOMEDS::Study_var  study = theGen->GetCurrentStudy();
1509   GEOM::GEOM_Gen_var geomGen = theGen->GetGeomEngine();
1510   if ( study->_is_nil() || geomGen->_is_nil() )
1511     return groupObj._retn();
1512   
1513   GEOM::GEOM_IGroupOperations_var groupOp =
1514     geomGen->GetIGroupOperations( theGen->GetCurrentStudyID() );
1515   GEOM::GEOM_IShapesOperations_var shapeOp =
1516     geomGen->GetIShapesOperations( theGen->GetCurrentStudyID() );
1517
1518   SALOMEDS::SObject_var meshOS = theGen->ObjectToSObject(study, theMesh);
1519   if ( meshOS->_is_nil() || groupOp->_is_nil() || shapeOp->_is_nil() )
1520     return groupObj._retn();
1521   SALOMEDS::SObject_var fatherSO = meshOS->GetFather();
1522   if ( fatherSO->_is_nil() || fatherSO->Tag() != theGen->GetSubMeshOnCompoundTag() )
1523     return groupObj._retn(); // keep only submeshes on groups
1524
1525   SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(meshOS);
1526   if ( anIter->_is_nil() ) return groupObj._retn();
1527   for ( ; anIter->More(); anIter->Next())
1528   {
1529     SALOMEDS::SObject_var aSObject = anIter->Value();
1530     SALOMEDS::SObject_var aRefSO;
1531     if ( !aSObject->_is_nil() && aSObject->ReferencedObject(aRefSO) )
1532     {
1533       groupObj = GEOM::GEOM_Object::_narrow(aRefSO->GetObject());
1534       if ( groupObj->_is_nil() ) break;
1535       GEOM::ListOfLong_var  ids = groupOp->GetObjects( groupObj );
1536       GEOM::GEOM_Object_var mainShape = groupObj->GetMainShape();
1537       for ( int i = 0; i < ids->length(); ++i ) {
1538         GEOM::GEOM_Object_var subShape = shapeOp->GetSubShape( mainShape, ids[i] );
1539         TopoDS_Shape S = theGen->GeomObjectToShape( subShape );
1540         if ( !S.IsNull() )
1541           theItems.push_back( S );
1542       }
1543       break;
1544     }
1545   }
1546   return groupObj._retn();
1547 }
1548
1549 //=============================================================================
1550 /*!
1551  * \brief Update hypotheses assigned to geom groups if the latter change
1552  * 
1553  * NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1554  */
1555 //=============================================================================
1556
1557 void SMESH_Mesh_i::CheckGeomGroupModif()
1558 {
1559   if ( !_impl->HasShapeToMesh() ) return;
1560
1561   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1562   if ( study->_is_nil() ) return;
1563
1564   // check if items of groups changed
1565   map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
1566   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
1567   {
1568     const TopoDS_Shape & oldGroupShape = i_sm->second->GetSubShape();
1569     SMESHDS_SubMesh * oldDS = i_sm->second->GetSubMeshDS();
1570     if ( !oldDS /*|| !oldDS->IsComplexSubmesh()*/ )
1571       continue;
1572     int oldID = i_sm->first;
1573     map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldID );
1574     if ( i_smIor == _mapSubMeshIor.end() )
1575       continue;
1576     list< TopoDS_Shape> newItems;
1577     GEOM::GEOM_Object_var groupObj = getGroupItemsFromStudy ( i_smIor->second, _gen_i, newItems );
1578     if ( groupObj->_is_nil() )
1579       continue;
1580
1581     int nbOldItems = oldDS->IsComplexSubmesh() ? oldDS->NbSubMeshes() : 1;
1582     int nbNewItems = newItems.size();
1583     bool groupChanged = ( nbOldItems != nbNewItems);
1584     if ( !groupChanged ) {
1585       if ( !oldDS->IsComplexSubmesh() ) { // old group has one item
1586         groupChanged = ( oldGroupShape != newItems.front() );
1587       }
1588       else {
1589         list<TopoDS_Shape>::iterator item = newItems.begin();
1590         for ( ; item != newItems.end() && !groupChanged; ++item )
1591         {
1592           SMESHDS_SubMesh * itemDS = _impl->GetMeshDS()->MeshElements( *item );
1593           groupChanged = ( !itemDS || !oldDS->ContainsSubMesh( itemDS ));
1594         }
1595       }
1596     }
1597     // update hypotheses and submeshes if necessary
1598     if ( groupChanged )
1599     {
1600       // get a new group shape
1601       GEOM_Client* geomClient = _gen_i->GetShapeReader();
1602       if ( !geomClient ) continue;
1603       TCollection_AsciiString groupIOR = _gen_i->GetGeomEngine()->GetStringFromIOR( groupObj );
1604       geomClient->RemoveShapeFromBuffer( groupIOR );
1605       TopoDS_Shape newGroupShape = _gen_i->GeomObjectToShape( groupObj );
1606       // update hypotheses
1607       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldGroupShape);
1608       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1609       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1610       {
1611         _impl->RemoveHypothesis( oldGroupShape, (*hypIt)->GetID());
1612         _impl->AddHypothesis   ( newGroupShape, (*hypIt)->GetID());
1613       }
1614       // care of submeshes
1615       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newGroupShape );
1616       int newID = newSubmesh->GetId();
1617       if ( newID != oldID ) {
1618         _mapSubMesh   [ newID ] = newSubmesh;
1619         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1620         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1621         _mapSubMesh.erase   (oldID);
1622         _mapSubMesh_i.erase (oldID);
1623         _mapSubMeshIor.erase(oldID);
1624         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1625       }
1626     }
1627   }
1628 }
1629
1630 //=============================================================================
1631 /*!
1632  * \brief Create standalone group instead if group on geometry
1633  * 
1634  */
1635 //=============================================================================
1636
1637 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupOnGeom_ptr theGroup )
1638 {
1639   SMESH::SMESH_Group_var aGroup;
1640   if ( theGroup->_is_nil() )
1641     return aGroup._retn();
1642
1643   Unexpect aCatch(SALOME_SalomeException);
1644
1645   SMESH_GroupBase_i* aGroupToRem =
1646     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
1647   if ( !aGroupToRem )
1648     return aGroup._retn();
1649
1650   int anId = aGroupToRem->GetLocalID();
1651   if ( !_impl->ConvertToStandalone( anId ) )
1652     return aGroup._retn();
1653
1654     SMESH_GroupBase_i* aGroupImpl;
1655       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1656
1657
1658   // remove old instance of group from own map
1659   _mapGroups.erase( anId );
1660
1661   SALOMEDS::StudyBuilder_var builder;
1662   SALOMEDS::SObject_var aGroupSO;
1663   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1664   if ( !aStudy->_is_nil() )  {
1665     builder = aStudy->NewBuilder();
1666     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1667     if ( !aGroupSO->_is_nil() ) {
1668
1669     // remove reference to geometry
1670     SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
1671     for ( ; chItr->More(); chItr->Next() )
1672       // Remove group's child SObject
1673       builder->RemoveObject( chItr->Value() );
1674
1675       // Update Python script
1676       TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
1677                     << aGroupSO << " )";
1678     }
1679   }
1680
1681   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1682   SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1683   aGroupImpl->Register();
1684   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1685
1686   // remember new group in own map
1687   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
1688   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1689
1690   // register CORBA object for persistence
1691   //int nextId = _gen_i->RegisterObject( aGroup );
1692   //if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1693   builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
1694
1695   return aGroup._retn();
1696 }
1697
1698 //=============================================================================
1699 /*!
1700  *
1701  */
1702 //=============================================================================
1703
1704 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1705 {
1706   if(MYDEBUG) MESSAGE( "createSubMesh" );
1707   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1708
1709   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1710   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1711   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1712   SMESH::SMESH_subMesh_var subMesh
1713     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1714
1715   _mapSubMesh[subMeshId] = mySubMesh;
1716   _mapSubMesh_i[subMeshId] = subMeshServant;
1717   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1718
1719   // register CORBA object for persistence
1720   int nextId = _gen_i->RegisterObject( subMesh );
1721   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1722
1723   return subMesh._retn();
1724 }
1725
1726 //=======================================================================
1727 //function : getSubMesh
1728 //purpose  :
1729 //=======================================================================
1730
1731 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
1732 {
1733   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
1734   if ( it == _mapSubMeshIor.end() )
1735     return SMESH::SMESH_subMesh::_nil();
1736
1737   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
1738 }
1739
1740
1741 //=============================================================================
1742 /*!
1743  *
1744  */
1745 //=============================================================================
1746
1747 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
1748                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
1749 {
1750   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
1751   if ( theSubMesh->_is_nil() || theSubShapeObject->_is_nil() )
1752     return;
1753
1754   try {
1755     SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
1756     for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
1757       removeHypothesis( theSubShapeObject, aHypList[i] );
1758     }
1759   }
1760   catch( const SALOME::SALOME_Exception& ) {
1761     INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
1762   }
1763
1764   int subMeshId = theSubMesh->GetId();
1765
1766   _mapSubMesh.erase(subMeshId);
1767   _mapSubMesh_i.erase(subMeshId);
1768   _mapSubMeshIor.erase(subMeshId);
1769   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
1770 }
1771
1772 //=============================================================================
1773 /*!
1774  *
1775  */
1776 //=============================================================================
1777
1778 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
1779                                                       const char*         theName,
1780                                                       const TopoDS_Shape& theShape )
1781 {
1782   int anId;
1783   SMESH::SMESH_GroupBase_var aGroup;
1784   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
1785     SMESH_GroupBase_i* aGroupImpl;
1786     if ( !theShape.IsNull() )
1787       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
1788     else
1789       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1790
1791     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1792     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1793     aGroupImpl->Register();
1794     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1795
1796     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
1797     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1798
1799     // register CORBA object for persistence
1800     int nextId = _gen_i->RegisterObject( aGroup );
1801     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1802   }
1803   return aGroup._retn();
1804 }
1805
1806 //=============================================================================
1807 /*!
1808  * SMESH_Mesh_i::removeGroup
1809  *
1810  * Should be called by ~SMESH_Group_i()
1811  */
1812 //=============================================================================
1813
1814 void SMESH_Mesh_i::removeGroup( const int theId )
1815 {
1816   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
1817   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
1818     _mapGroups.erase( theId );
1819     _impl->RemoveGroup( theId );
1820   }
1821 }
1822
1823
1824 //=============================================================================
1825 /*!
1826  *
1827  */
1828 //=============================================================================
1829
1830 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
1831 throw(SALOME::SALOME_Exception)
1832 {
1833   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
1834
1835   SMESH::log_array_var aLog;
1836   try{
1837     list < SMESHDS_Command * >logDS = _impl->GetLog();
1838     aLog = new SMESH::log_array;
1839     int indexLog = 0;
1840     int lg = logDS.size();
1841     SCRUTE(lg);
1842     aLog->length(lg);
1843     list < SMESHDS_Command * >::iterator its = logDS.begin();
1844     while(its != logDS.end()){
1845       SMESHDS_Command *com = *its;
1846       int comType = com->GetType();
1847       //SCRUTE(comType);
1848       int lgcom = com->GetNumber();
1849       //SCRUTE(lgcom);
1850       const list < int >&intList = com->GetIndexes();
1851       int inum = intList.size();
1852       //SCRUTE(inum);
1853       list < int >::const_iterator ii = intList.begin();
1854       const list < double >&coordList = com->GetCoords();
1855       int rnum = coordList.size();
1856       //SCRUTE(rnum);
1857       list < double >::const_iterator ir = coordList.begin();
1858       aLog[indexLog].commandType = comType;
1859       aLog[indexLog].number = lgcom;
1860       aLog[indexLog].coords.length(rnum);
1861       aLog[indexLog].indexes.length(inum);
1862       for(int i = 0; i < rnum; i++){
1863         aLog[indexLog].coords[i] = *ir;
1864         //MESSAGE(" "<<i<<" "<<ir.Value());
1865         ir++;
1866       }
1867       for(int i = 0; i < inum; i++){
1868         aLog[indexLog].indexes[i] = *ii;
1869         //MESSAGE(" "<<i<<" "<<ii.Value());
1870         ii++;
1871       }
1872       indexLog++;
1873       its++;
1874     }
1875     if(clearAfterGet)
1876       _impl->ClearLog();
1877   }
1878   catch(SALOME_Exception & S_ex){
1879     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1880   }
1881   return aLog._retn();
1882 }
1883
1884
1885 //=============================================================================
1886 /*!
1887  *
1888  */
1889 //=============================================================================
1890
1891 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
1892 {
1893   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
1894   // ****
1895 }
1896
1897 //=============================================================================
1898 /*!
1899  *
1900  */
1901 //=============================================================================
1902
1903 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
1904 {
1905   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
1906   return _id;
1907 }
1908
1909 //=============================================================================
1910 /*!
1911  *
1912  */
1913 //=============================================================================
1914
1915 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
1916 {
1917   return _studyId;
1918 }
1919
1920 //=============================================================================
1921 /*!
1922  *
1923  */
1924 //=============================================================================
1925
1926 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
1927 {
1928   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
1929   _impl = impl;
1930 }
1931
1932 //=============================================================================
1933 /*!
1934  *
1935  */
1936 //=============================================================================
1937
1938 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
1939 {
1940   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
1941   return *_impl;
1942 }
1943
1944 //=============================================================================
1945 /*!
1946  * Return mesh editor
1947  */
1948 //=============================================================================
1949
1950 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
1951 {
1952   // Create MeshEditor
1953   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
1954   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1955
1956   // Update Python script
1957   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
1958
1959   return aMesh._retn();
1960 }
1961
1962 //=============================================================================
1963 /*!
1964  * Return mesh edition previewer
1965  */
1966 //=============================================================================
1967
1968 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
1969 {
1970   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
1971   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1972   return aMesh._retn();
1973 }
1974
1975 //=============================================================================
1976 /*!
1977  *
1978  */
1979 //=============================================================================
1980 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
1981 {
1982   Unexpect aCatch(SALOME_SalomeException);
1983   _impl->SetAutoColor(theAutoColor);
1984 }
1985
1986 //=============================================================================
1987 /*!
1988  *
1989  */
1990 //=============================================================================
1991 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
1992 {
1993   Unexpect aCatch(SALOME_SalomeException);
1994   return _impl->GetAutoColor();
1995 }
1996
1997
1998 //=============================================================================
1999 /*!
2000  *  Export in different formats
2001  */
2002 //=============================================================================
2003
2004 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2005 {
2006   return _impl->HasDuplicatedGroupNamesMED();
2007 }
2008
2009 void SMESH_Mesh_i::PrepareForWriting (const char* file)
2010 {
2011   TCollection_AsciiString aFullName ((char*)file);
2012   OSD_Path aPath (aFullName);
2013   OSD_File aFile (aPath);
2014   if (aFile.Exists()) {
2015     // existing filesystem node
2016     if (aFile.KindOfFile() == OSD_FILE) {
2017       if (aFile.IsWriteable()) {
2018         aFile.Reset();
2019         aFile.Remove();
2020         if (aFile.Failed()) {
2021           TCollection_AsciiString msg ("File ");
2022           msg += aFullName + " cannot be replaced.";
2023           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2024         }
2025       } else {
2026         TCollection_AsciiString msg ("File ");
2027         msg += aFullName + " cannot be overwritten.";
2028         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2029       }
2030     } else {
2031       TCollection_AsciiString msg ("Location ");
2032       msg += aFullName + " is not a file.";
2033       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2034     }
2035   } else {
2036     // nonexisting file; check if it can be created
2037     aFile.Reset();
2038     aFile.Build(OSD_WriteOnly, OSD_Protection());
2039     if (aFile.Failed()) {
2040       TCollection_AsciiString msg ("You cannot create the file ");
2041       msg += aFullName + ". Check the directory existance and access rights.";
2042       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2043     } else {
2044       aFile.Close();
2045       aFile.Remove();
2046     }
2047   }
2048 }
2049
2050 void SMESH_Mesh_i::ExportToMED (const char* file,
2051                                 CORBA::Boolean auto_groups,
2052                                 SMESH::MED_VERSION theVersion)
2053   throw(SALOME::SALOME_Exception)
2054 {
2055   Unexpect aCatch(SALOME_SalomeException);
2056
2057   // Perform Export
2058   PrepareForWriting(file);
2059   const char* aMeshName = "Mesh";
2060   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2061   if ( !aStudy->_is_nil() ) {
2062     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2063     if ( !aMeshSO->_is_nil() ) {
2064       aMeshName = aMeshSO->GetName();
2065       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2066       if ( !aStudy->GetProperties()->IsLocked() )
2067         {
2068         SALOMEDS::GenericAttribute_var anAttr;
2069         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2070         SALOMEDS::AttributeExternalFileDef_var aFileName;
2071         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2072         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2073         ASSERT(!aFileName->_is_nil());
2074         aFileName->SetValue(file);
2075         SALOMEDS::AttributeFileType_var aFileType;
2076         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2077         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2078         ASSERT(!aFileType->_is_nil());
2079         aFileType->SetValue("FICHIERMED");
2080         }
2081     }
2082   }
2083   // Update Python script
2084   // set name of mesh before export
2085   TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName << "')";
2086   
2087   // check names of groups
2088   checkGroupNames();
2089
2090   TPythonDump() << _this() << ".ExportToMED( '"
2091                 << file << "', " << auto_groups << ", " << theVersion << " )";
2092
2093   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
2094 }
2095
2096 void SMESH_Mesh_i::ExportMED (const char* file,
2097                               CORBA::Boolean auto_groups)
2098   throw(SALOME::SALOME_Exception)
2099 {
2100   ExportToMED(file,auto_groups,SMESH::MED_V2_1);
2101 }
2102
2103 void SMESH_Mesh_i::ExportDAT (const char *file)
2104   throw(SALOME::SALOME_Exception)
2105 {
2106   Unexpect aCatch(SALOME_SalomeException);
2107
2108   // Update Python script
2109   // check names of groups
2110   checkGroupNames();
2111   TPythonDump() << _this() << ".ExportDAT( '" << file << "' )";
2112
2113   // Perform Export
2114   PrepareForWriting(file);
2115   _impl->ExportDAT(file);
2116 }
2117
2118 void SMESH_Mesh_i::ExportUNV (const char *file)
2119   throw(SALOME::SALOME_Exception)
2120 {
2121   Unexpect aCatch(SALOME_SalomeException);
2122
2123   // Update Python script
2124   // check names of groups
2125   checkGroupNames();
2126   TPythonDump() << _this() << ".ExportUNV( '" << file << "' )";
2127
2128   // Perform Export
2129   PrepareForWriting(file);
2130   _impl->ExportUNV(file);
2131 }
2132
2133 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2134   throw(SALOME::SALOME_Exception)
2135 {
2136   Unexpect aCatch(SALOME_SalomeException);
2137
2138   // Update Python script
2139   // check names of groups
2140   checkGroupNames();
2141   TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )";
2142
2143   // Perform Export
2144   PrepareForWriting(file);
2145   _impl->ExportSTL(file, isascii);
2146 }
2147
2148 //=============================================================================
2149 /*!
2150  *
2151  */
2152 //=============================================================================
2153
2154 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2155 {
2156   Unexpect aCatch(SALOME_SalomeException);
2157   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2158   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2159   return aMesh._retn();
2160 }
2161
2162 //=============================================================================
2163 /*!
2164  *
2165  */
2166 //=============================================================================
2167 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2168 {
2169   Unexpect aCatch(SALOME_SalomeException);
2170   return _impl->NbNodes();
2171 }
2172
2173 //=============================================================================
2174 /*!
2175  *
2176  */
2177 //=============================================================================
2178 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2179 {
2180   Unexpect aCatch(SALOME_SalomeException);
2181   return NbEdges() + NbFaces() + NbVolumes();
2182 }
2183
2184 //=============================================================================
2185 /*!
2186  *
2187  */
2188 //=============================================================================
2189 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2190 {
2191   Unexpect aCatch(SALOME_SalomeException);
2192   return _impl->NbEdges();
2193 }
2194
2195 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2196   throw(SALOME::SALOME_Exception)
2197 {
2198   Unexpect aCatch(SALOME_SalomeException);
2199   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2200 }
2201
2202 //=============================================================================
2203 /*!
2204  *
2205  */
2206 //=============================================================================
2207 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2208 {
2209   Unexpect aCatch(SALOME_SalomeException);
2210   return _impl->NbFaces();
2211 }
2212
2213 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2214 {
2215   Unexpect aCatch(SALOME_SalomeException);
2216   return _impl->NbTriangles();
2217 }
2218
2219 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2220 {
2221   Unexpect aCatch(SALOME_SalomeException);
2222   return _impl->NbQuadrangles();
2223 }
2224
2225 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2226 {
2227   Unexpect aCatch(SALOME_SalomeException);
2228   return _impl->NbPolygons();
2229 }
2230
2231 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2232   throw(SALOME::SALOME_Exception)
2233 {
2234   Unexpect aCatch(SALOME_SalomeException);
2235   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2236 }
2237
2238 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2239   throw(SALOME::SALOME_Exception)
2240 {
2241   Unexpect aCatch(SALOME_SalomeException);
2242   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2243 }
2244
2245 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2246   throw(SALOME::SALOME_Exception)
2247 {
2248   Unexpect aCatch(SALOME_SalomeException);
2249   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2250 }
2251
2252 //=============================================================================
2253 /*!
2254  *
2255  */
2256 //=============================================================================
2257 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2258 {
2259   Unexpect aCatch(SALOME_SalomeException);
2260   return _impl->NbVolumes();
2261 }
2262
2263 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2264 {
2265   Unexpect aCatch(SALOME_SalomeException);
2266   return _impl->NbTetras();
2267 }
2268
2269 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2270 {
2271   Unexpect aCatch(SALOME_SalomeException);
2272   return _impl->NbHexas();
2273 }
2274
2275 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2276 {
2277   Unexpect aCatch(SALOME_SalomeException);
2278   return _impl->NbPyramids();
2279 }
2280
2281 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2282 {
2283   Unexpect aCatch(SALOME_SalomeException);
2284   return _impl->NbPrisms();
2285 }
2286
2287 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2288 {
2289   Unexpect aCatch(SALOME_SalomeException);
2290   return _impl->NbPolyhedrons();
2291 }
2292
2293 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2294   throw(SALOME::SALOME_Exception)
2295 {
2296   Unexpect aCatch(SALOME_SalomeException);
2297   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2298 }
2299
2300 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2301   throw(SALOME::SALOME_Exception)
2302 {
2303   Unexpect aCatch(SALOME_SalomeException);
2304   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2305 }
2306
2307 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2308   throw(SALOME::SALOME_Exception)
2309 {
2310   Unexpect aCatch(SALOME_SalomeException);
2311   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2312 }
2313
2314 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2315   throw(SALOME::SALOME_Exception)
2316 {
2317   Unexpect aCatch(SALOME_SalomeException);
2318   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2319 }
2320
2321 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2322   throw(SALOME::SALOME_Exception)
2323 {
2324   Unexpect aCatch(SALOME_SalomeException);
2325   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2326 }
2327
2328 //=============================================================================
2329 /*!
2330  *
2331  */
2332 //=============================================================================
2333 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2334 {
2335   Unexpect aCatch(SALOME_SalomeException);
2336   return _mapSubMesh_i.size();
2337 }
2338
2339 //=============================================================================
2340 /*!
2341  *
2342  */
2343 //=============================================================================
2344 char* SMESH_Mesh_i::Dump()
2345 {
2346   std::ostringstream os;
2347   _impl->Dump( os );
2348   return CORBA::string_dup( os.str().c_str() );
2349 }
2350
2351 //=============================================================================
2352 /*!
2353  *
2354  */
2355 //=============================================================================
2356 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2357 {
2358 //   SMESH::long_array_var aResult = new SMESH::long_array();
2359 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2360 //   int aMinId = aSMESHDS_Mesh->MinElementID();
2361 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
2362
2363 //   aResult->length(aMaxId - aMinId + 1);
2364
2365 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
2366 //     aResult[i++] = id;
2367
2368 //   return aResult._retn();
2369   // PAL12398
2370   return GetElementsId();
2371 }
2372
2373 //=============================================================================
2374 /*!
2375  *
2376  */
2377 //=============================================================================
2378
2379 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2380      throw (SALOME::SALOME_Exception)
2381 {
2382   Unexpect aCatch(SALOME_SalomeException);
2383   MESSAGE("SMESH_Mesh_i::GetElementsId");
2384   SMESH::long_array_var aResult = new SMESH::long_array();
2385   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2386
2387   if ( aSMESHDS_Mesh == NULL )
2388     return aResult._retn();
2389
2390   long nbElements = NbElements();
2391   aResult->length( nbElements );
2392   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2393   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
2394     aResult[i] = anIt->next()->GetID();
2395
2396   return aResult._retn();
2397 }
2398
2399
2400 //=============================================================================
2401 /*!
2402  *
2403  */
2404 //=============================================================================
2405
2406 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
2407     throw (SALOME::SALOME_Exception)
2408 {
2409   Unexpect aCatch(SALOME_SalomeException);
2410   MESSAGE("SMESH_subMesh_i::GetElementsByType");
2411   SMESH::long_array_var aResult = new SMESH::long_array();
2412   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2413
2414   if ( aSMESHDS_Mesh == NULL )
2415     return aResult._retn();
2416
2417   long nbElements = NbElements();
2418
2419   // No sense in returning ids of elements along with ids of nodes:
2420   // when theElemType == SMESH::ALL, return node ids only if
2421   // there are no elements
2422   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
2423     return GetNodesId();
2424
2425   aResult->length( nbElements );
2426
2427   int i = 0;
2428
2429   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2430   while ( i < nbElements && anIt->more() ) {
2431     const SMDS_MeshElement* anElem = anIt->next();
2432     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
2433       aResult[i++] = anElem->GetID();
2434   }
2435
2436   aResult->length( i );
2437
2438   return aResult._retn();
2439 }
2440
2441 //=============================================================================
2442 /*!
2443  *
2444  */
2445 //=============================================================================
2446
2447 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
2448   throw (SALOME::SALOME_Exception)
2449 {
2450   Unexpect aCatch(SALOME_SalomeException);
2451   MESSAGE("SMESH_subMesh_i::GetNodesId");
2452   SMESH::long_array_var aResult = new SMESH::long_array();
2453   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2454
2455   if ( aSMESHDS_Mesh == NULL )
2456     return aResult._retn();
2457
2458   long nbNodes = NbNodes();
2459   aResult->length( nbNodes );
2460   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
2461   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
2462     aResult[i] = anIt->next()->GetID();
2463
2464   return aResult._retn();
2465 }
2466
2467 //=============================================================================
2468 /*!
2469  *
2470  */
2471 //=============================================================================
2472
2473 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
2474   throw (SALOME::SALOME_Exception)
2475 {
2476   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
2477 }
2478
2479
2480 //=============================================================================
2481 /*!
2482  * Returns ID of elements for given submesh
2483  */
2484 //=============================================================================
2485 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
2486      throw (SALOME::SALOME_Exception)
2487 {
2488   SMESH::long_array_var aResult = new SMESH::long_array();
2489
2490   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2491   if(!SM) return aResult._retn();
2492
2493   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2494   if(!SDSM) return aResult._retn();
2495
2496   aResult->length(SDSM->NbElements());
2497
2498   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2499   int i = 0;
2500   while ( eIt->more() ) {
2501     aResult[i++] = eIt->next()->GetID();
2502   }
2503
2504   return aResult._retn();
2505 }
2506
2507
2508 //=============================================================================
2509 /*!
2510  * Returns ID of nodes for given submesh
2511  * If param all==true - returns all nodes, else -
2512  * returns only nodes on shapes.
2513  */
2514 //=============================================================================
2515 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
2516      throw (SALOME::SALOME_Exception)
2517 {
2518   SMESH::long_array_var aResult = new SMESH::long_array();
2519
2520   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2521   if(!SM) return aResult._retn();
2522
2523   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2524   if(!SDSM) return aResult._retn();
2525
2526   set<int> theElems;
2527   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
2528     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
2529     while ( nIt->more() ) {
2530       const SMDS_MeshNode* elem = nIt->next();
2531       theElems.insert( elem->GetID() );
2532     }
2533   }
2534   else { // all nodes of submesh elements
2535     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2536     while ( eIt->more() ) {
2537       const SMDS_MeshElement* anElem = eIt->next();
2538       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
2539       while ( nIt->more() ) {
2540         const SMDS_MeshElement* elem = nIt->next();
2541         theElems.insert( elem->GetID() );
2542       }
2543     }
2544   }
2545
2546   aResult->length(theElems.size());
2547   set<int>::iterator itElem;
2548   int i = 0;
2549   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
2550     aResult[i++] = *itElem;
2551
2552   return aResult._retn();
2553 }
2554   
2555
2556 //=============================================================================
2557 /*!
2558  * Returns type of elements for given submesh
2559  */
2560 //=============================================================================
2561 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
2562      throw (SALOME::SALOME_Exception)
2563 {
2564   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2565   if(!SM) return SMESH::ALL;
2566
2567   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2568   if(!SDSM) return SMESH::ALL;
2569
2570   if(SDSM->NbElements()==0)
2571     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
2572
2573   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2574   const SMDS_MeshElement* anElem = eIt->next();
2575   return ( SMESH::ElementType ) anElem->GetType();
2576 }
2577   
2578
2579 //=============================================================================
2580 /*!
2581  *
2582  */
2583 //=============================================================================
2584
2585 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
2586 {
2587   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
2588   if ( MYDEBUG )
2589     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
2590   return pointeur;
2591 }
2592
2593
2594 //=============================================================================
2595 /*!
2596  * Get XYZ coordinates of node as list of double
2597  * If there is not node for given ID - returns empty list
2598  */
2599 //=============================================================================
2600
2601 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
2602 {
2603   SMESH::double_array_var aResult = new SMESH::double_array();
2604   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2605   if ( aSMESHDS_Mesh == NULL )
2606     return aResult._retn();
2607
2608   // find node
2609   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2610   if(!aNode)
2611     return aResult._retn();
2612
2613   // add coordinates
2614   aResult->length(3);
2615   aResult[0] = aNode->X();
2616   aResult[1] = aNode->Y();
2617   aResult[2] = aNode->Z();
2618   return aResult._retn();
2619 }
2620
2621
2622 //=============================================================================
2623 /*!
2624  * For given node returns list of IDs of inverse elements
2625  * If there is not node for given ID - returns empty list
2626  */
2627 //=============================================================================
2628
2629 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
2630 {
2631   SMESH::long_array_var aResult = new SMESH::long_array();
2632   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2633   if ( aSMESHDS_Mesh == NULL )
2634     return aResult._retn();
2635
2636   // find node
2637   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2638   if(!aNode)
2639     return aResult._retn();
2640
2641   // find inverse elements
2642   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
2643   TColStd_SequenceOfInteger IDs;
2644   while(eIt->more()) {
2645     const SMDS_MeshElement* elem = eIt->next();
2646     IDs.Append(elem->GetID());
2647   }
2648   if(IDs.Length()>0) {
2649     aResult->length(IDs.Length());
2650     int i = 1;
2651     for(; i<=IDs.Length(); i++) {
2652       aResult[i-1] = IDs.Value(i);
2653     }
2654   }
2655   return aResult._retn();
2656 }
2657
2658 //=============================================================================
2659 /*!
2660  * \brief Return position of a node on shape
2661  */
2662 //=============================================================================
2663
2664 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
2665 {
2666   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
2667   aNodePosition->shapeID = 0;
2668   aNodePosition->shapeType = GEOM::SHAPE;
2669
2670   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
2671   if ( !mesh ) return aNodePosition;
2672
2673   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
2674   {
2675     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
2676     {
2677       aNodePosition->shapeID = pos->GetShapeId();
2678       switch ( pos->GetTypeOfPosition() ) {
2679       case SMDS_TOP_EDGE:
2680         aNodePosition->shapeType = GEOM::EDGE;
2681         aNodePosition->params.length(1);
2682         aNodePosition->params[0] =
2683           static_cast<SMDS_EdgePosition*>( pos.get() )->GetUParameter();
2684         break;
2685       case SMDS_TOP_FACE:
2686         aNodePosition->shapeType = GEOM::FACE;
2687         aNodePosition->params.length(2);
2688         aNodePosition->params[0] =
2689           static_cast<SMDS_FacePosition*>( pos.get() )->GetUParameter();
2690         aNodePosition->params[1] =
2691           static_cast<SMDS_FacePosition*>( pos.get() )->GetVParameter();
2692         break;
2693       case SMDS_TOP_VERTEX:
2694         aNodePosition->shapeType = GEOM::VERTEX;
2695         break;
2696       case SMDS_TOP_3DSPACE:
2697         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
2698           aNodePosition->shapeType = GEOM::SOLID;
2699         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
2700           aNodePosition->shapeType = GEOM::SHELL;
2701         break;
2702       default:;
2703       }
2704     }
2705   }
2706   return aNodePosition;
2707 }
2708
2709 //=============================================================================
2710 /*!
2711  * If given element is node returns IDs of shape from position
2712  * If there is not node for given ID - returns -1
2713  */
2714 //=============================================================================
2715
2716 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
2717 {
2718   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2719   if ( aSMESHDS_Mesh == NULL )
2720     return -1;
2721
2722   // try to find node
2723   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2724   if(aNode) {
2725     SMDS_PositionPtr pos = aNode->GetPosition();
2726     if(!pos)
2727       return -1;
2728     else
2729       return pos->GetShapeId();
2730   }
2731
2732   return -1;
2733 }
2734
2735
2736 //=============================================================================
2737 /*!
2738  * For given element returns ID of result shape after 
2739  * ::FindShape() from SMESH_MeshEditor
2740  * If there is not element for given ID - returns -1
2741  */
2742 //=============================================================================
2743
2744 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
2745 {
2746   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2747   if ( aSMESHDS_Mesh == NULL )
2748     return -1;
2749
2750   // try to find element
2751   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2752   if(!elem)
2753     return -1;
2754
2755   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
2756   ::SMESH_MeshEditor aMeshEditor(_impl);
2757   int index = aMeshEditor.FindShape( elem );
2758   if(index>0)
2759     return index;
2760
2761   return -1;
2762 }
2763
2764
2765 //=============================================================================
2766 /*!
2767  * Returns number of nodes for given element
2768  * If there is not element for given ID - returns -1
2769  */
2770 //=============================================================================
2771
2772 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
2773 {
2774   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2775   if ( aSMESHDS_Mesh == NULL ) return -1;
2776   // try to find element
2777   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2778   if(!elem) return -1;
2779   return elem->NbNodes();
2780 }
2781
2782
2783 //=============================================================================
2784 /*!
2785  * Returns ID of node by given index for given element
2786  * If there is not element for given ID - returns -1
2787  * If there is not node for given index - returns -2
2788  */
2789 //=============================================================================
2790
2791 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
2792 {
2793   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2794   if ( aSMESHDS_Mesh == NULL ) return -1;
2795   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2796   if(!elem) return -1;
2797   if( index>=elem->NbNodes() || index<0 ) return -1;
2798   return elem->GetNode(index)->GetID();
2799 }
2800
2801 //=============================================================================
2802 /*!
2803  * Returns IDs of nodes of given element
2804  */
2805 //=============================================================================
2806
2807 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
2808 {
2809   SMESH::long_array_var aResult = new SMESH::long_array();
2810   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
2811   {
2812     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
2813     {
2814       aResult->length( elem->NbNodes() );
2815       for ( int i = 0; i < elem->NbNodes(); ++i )
2816         aResult[ i ] = elem->GetNode( i )->GetID();
2817     }
2818   }
2819   return aResult._retn();
2820 }
2821
2822 //=============================================================================
2823 /*!
2824  * Returns true if given node is medium node
2825  * in given quadratic element
2826  */
2827 //=============================================================================
2828
2829 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
2830 {
2831   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2832   if ( aSMESHDS_Mesh == NULL ) return false;
2833   // try to find node
2834   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2835   if(!aNode) return false;
2836   // try to find element
2837   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
2838   if(!elem) return false;
2839
2840   return elem->IsMediumNode(aNode);
2841 }
2842
2843
2844 //=============================================================================
2845 /*!
2846  * Returns true if given node is medium node
2847  * in one of quadratic elements
2848  */
2849 //=============================================================================
2850
2851 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
2852                                                    SMESH::ElementType theElemType)
2853 {
2854   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2855   if ( aSMESHDS_Mesh == NULL ) return false;
2856
2857   // try to find node
2858   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2859   if(!aNode) return false;
2860
2861   SMESH_MesherHelper aHelper( *(_impl) );
2862
2863   SMDSAbs_ElementType aType;
2864   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
2865   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
2866   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
2867   else aType = SMDSAbs_All;
2868
2869   return aHelper.IsMedium(aNode,aType);
2870 }
2871
2872
2873 //=============================================================================
2874 /*!
2875  * Returns number of edges for given element
2876  */
2877 //=============================================================================
2878
2879 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
2880 {
2881   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2882   if ( aSMESHDS_Mesh == NULL ) return -1;
2883   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2884   if(!elem) return -1;
2885   return elem->NbEdges();
2886 }
2887
2888
2889 //=============================================================================
2890 /*!
2891  * Returns number of faces for given element
2892  */
2893 //=============================================================================
2894
2895 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
2896 {
2897   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2898   if ( aSMESHDS_Mesh == NULL ) return -1;
2899   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2900   if(!elem) return -1;
2901   return elem->NbFaces();
2902 }
2903
2904
2905 //=============================================================================
2906 /*!
2907  * Returns true if given element is polygon
2908  */
2909 //=============================================================================
2910
2911 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
2912 {
2913   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2914   if ( aSMESHDS_Mesh == NULL ) return false;
2915   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2916   if(!elem) return false;
2917   return elem->IsPoly();
2918 }
2919
2920
2921 //=============================================================================
2922 /*!
2923  * Returns true if given element is quadratic
2924  */
2925 //=============================================================================
2926
2927 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
2928 {
2929   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2930   if ( aSMESHDS_Mesh == NULL ) return false;
2931   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2932   if(!elem) return false;
2933   return elem->IsQuadratic();
2934 }
2935
2936
2937 //=============================================================================
2938 /*!
2939  * Returns bary center for given element
2940  */
2941 //=============================================================================
2942
2943 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
2944 {
2945   SMESH::double_array_var aResult = new SMESH::double_array();
2946   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2947   if ( aSMESHDS_Mesh == NULL )
2948     return aResult._retn();
2949
2950   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2951   if(!elem)
2952     return aResult._retn();
2953
2954   if(elem->GetType()==SMDSAbs_Volume) {
2955     SMDS_VolumeTool aTool;
2956     if(aTool.Set(elem)) {
2957       aResult->length(3);
2958       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
2959         aResult->length(0);
2960     }
2961   }
2962   else {
2963     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
2964     int nbn = 0;
2965     double x=0., y=0., z=0.;
2966     for(; anIt->more(); ) {
2967       nbn++;
2968       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
2969       x += aNode->X();
2970       y += aNode->Y();
2971       z += aNode->Z();
2972     }
2973     if(nbn>0) {
2974       // add coordinates
2975       aResult->length(3);
2976       aResult[0] = x/nbn;
2977       aResult[1] = y/nbn;
2978       aResult[2] = z/nbn;
2979     }
2980   }
2981
2982   return aResult._retn();
2983 }
2984
2985
2986 //=============================================================================
2987 /*!
2988  * Create and publish group servants if any groups were imported or created anyhow
2989  */
2990 //=============================================================================
2991
2992 void SMESH_Mesh_i::CreateGroupServants() 
2993 {
2994   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2995
2996   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
2997   while ( groupIt->more() )
2998   {
2999     ::SMESH_Group* group = groupIt->next();
3000     int            anId = group->GetGroupDS()->GetID();
3001
3002     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
3003     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3004       continue;
3005
3006     SMESH_GroupBase_i* aGroupImpl;
3007     TopoDS_Shape       shape;
3008     if ( SMESHDS_GroupOnGeom* groupOnGeom =
3009          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
3010     {
3011       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3012       shape      = groupOnGeom->GetShape();
3013     }
3014     else {
3015       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3016     }
3017
3018     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
3019     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
3020     aGroupImpl->Register();
3021
3022     SMESH::SMESH_GroupBase_var groupVar =
3023       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
3024     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
3025
3026     // register CORBA object for persistence
3027     int nextId = _gen_i->RegisterObject( groupVar );
3028     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
3029
3030     // publishing of the groups in the study
3031     if ( !aStudy->_is_nil() ) {
3032       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
3033       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
3034     }
3035   }
3036 }
3037
3038 //=============================================================================
3039 /*!
3040  * \brief Return groups cantained in _mapGroups by their IDs
3041  */
3042 //=============================================================================
3043
3044 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
3045 {
3046   int nbGroups = groupIDs.size();
3047   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
3048   aList->length( nbGroups );
3049
3050   list<int>::const_iterator ids = groupIDs.begin();
3051   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
3052   {
3053     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
3054     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3055       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
3056   }
3057   aList->length( nbGroups );
3058   return aList._retn();
3059 }
3060
3061 //=============================================================================
3062 /*!
3063  * \brief Return information about imported file
3064  */
3065 //=============================================================================
3066
3067 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
3068 {
3069   SALOME_MED::MedFileInfo_var res( myFileInfo );
3070   if ( !res.operator->() ) {
3071     res = new SALOME_MED::MedFileInfo;
3072     res->fileName = "";
3073     res->fileSize = res->major = res->minor = res->release = -1;
3074   }
3075   return res._retn();
3076 }
3077
3078 //=============================================================================
3079 /*!
3080  * \brief Check and correct names of mesh groups
3081  */
3082 //=============================================================================
3083
3084 void SMESH_Mesh_i::checkGroupNames()
3085 {
3086   int nbGrp = NbGroups();
3087   if ( !nbGrp )
3088     return;
3089
3090   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3091   if ( aStudy->_is_nil() )
3092     return; // nothing to do
3093   
3094   SMESH::ListOfGroups* grpList = 0;
3095   // avoid dump of "GetGroups"
3096   {
3097     // store python dump into a local variable inside local scope
3098     SMESH::TPythonDump pDump; // do not delete this line of code
3099     grpList = GetGroups();
3100   }
3101
3102   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
3103     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
3104     if ( !aGrp )
3105       continue;
3106     SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
3107     if ( aGrpSO->_is_nil() )
3108       continue;
3109     // correct name of the mesh group if necessary
3110     const char* guiName = aGrpSO->GetName();
3111     if ( strcmp(guiName, aGrp->GetName()) )
3112       aGrp->SetName( guiName );
3113   }
3114 }
3115
3116 //=============================================================================
3117 /*!
3118  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
3119  */
3120 //=============================================================================
3121 void SMESH_Mesh_i::SetParameters(const char* theParameters)
3122 {
3123   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
3124                                                CORBA::string_dup(theParameters));
3125 }
3126
3127 //=============================================================================
3128 /*!
3129  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
3130  */
3131 //=============================================================================
3132 char* SMESH_Mesh_i::GetParameters()
3133 {
3134   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3135   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
3136 }
3137
3138 //=============================================================================
3139 /*!
3140  * \brief Returns list of notebook variables used for last Mesh operation
3141  */
3142 //=============================================================================
3143 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
3144 {
3145   SMESH::string_array_var aResult = new SMESH::string_array();
3146   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3147   if(gen) {
3148     char *aParameters = GetParameters();
3149     SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
3150     if(!aStudy->_is_nil()) {
3151       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
3152       if(aSections->length() > 0) {
3153         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
3154         aResult->length(aVars.length());
3155         for(int i = 0;i < aVars.length();i++)
3156           aResult[i] = CORBA::string_dup( aVars[i]);
3157       }
3158     }
3159   }
3160   return aResult._retn();
3161 }