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