Salome HOME
0023505: Sigsegv with fuse on cylinder and cone
[modules/smesh.git] / src / SMESH_I / SMESH_PreMeshInfo.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File      : SMESH_PreMeshInfo.cxx
23 // Created   : Fri Feb 10 17:36:39 2012
24 // Author    : Edward AGAPOV (eap)
25 //
26
27 #include "SMESH_PreMeshInfo.hxx"
28
29 #include "DriverMED.hxx"
30 #include "DriverMED_R_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_EdgePosition.hxx"
33 #include "SMDS_FacePosition.hxx"
34 #include "SMDS_SpacePosition.hxx"
35 #include "SMDS_VertexPosition.hxx"
36 #include "SMESHDS_Group.hxx"
37 #include "SMESHDS_GroupOnFilter.hxx"
38 #include "SMESHDS_Mesh.hxx"
39 #include "SMESH_Gen_i.hxx"
40 #include "SMESH_Group_i.hxx"
41 #include "SMESH_Mesh_i.hxx"
42 #include "SMESH_subMesh_i.hxx"
43
44 #include <HDFarray.hxx>
45 #include <HDFdataset.hxx>
46 #include <HDFfile.hxx>
47 #include <HDFgroup.hxx>
48 #include <SALOMEDS_Tool.hxx>
49 #include <SALOMEDS_wrap.hxx>
50
51 #include <TopoDS_Iterator.hxx>
52 #include <TopoDS_Shape.hxx>
53
54 #include "SMESH_TryCatch.hxx"
55
56 #include CORBA_SERVER_HEADER(SALOME_Session)
57
58 using namespace std;
59
60 #define MYDEBUGOUT(msg) //std::cout << msg << std::endl;
61
62 namespace
63 {
64   enum {  GroupOnFilter_OutOfDate = -1 };
65
66   // a map to count not yet loaded meshes 
67   static std::map< int, int > theStudyIDToMeshCounter;
68
69   //================================================================================
70   /*!
71    * \brief Counts not fully loaded meshes
72    */
73   //================================================================================
74
75   void meshInfoLoaded( SMESH_Mesh_i* mesh )
76   {
77     std::map< int, int >::iterator id2counter =
78       theStudyIDToMeshCounter.insert( std::make_pair( (int) mesh->GetStudyId(), 0 )).first;
79     id2counter->second++;
80   }
81   //================================================================================
82   /*!
83    * \brief Removes temporary files if none of meshes needs them
84    */
85   //================================================================================
86
87   void filesNoMoreNeeded(SMESH_Mesh_i* mesh,
88                          std::string   medFile,
89                          std::string   hdfFile)
90   {
91     if ( --theStudyIDToMeshCounter[ (int) mesh->GetStudyId() ] == 0 )
92     {
93       std::string tmpDir = SALOMEDS_Tool::GetDirFromPath( hdfFile );
94
95       SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames;
96       aFiles->length(2);
97       medFile = SALOMEDS_Tool::GetNameFromPath( medFile ) + ".med";
98       hdfFile = SALOMEDS_Tool::GetNameFromPath( hdfFile ) + ".hdf";
99       aFiles[0] = medFile.c_str();
100       aFiles[1] = hdfFile.c_str();
101
102       SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true );
103     }
104   }
105
106   //=============================================================================
107   /*!
108    * \brief Class sending signals on start and finish of loading
109    */
110   //=============================================================================
111
112   class SignalToGUI
113   {
114     std::string         _messagePrefix;
115     SALOME::Session_var _session;
116   public:
117     SignalToGUI( SMESH_Mesh_i* mesh )
118     {
119       SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
120       SALOMEDS::Study_var study = gen->GetCurrentStudy();
121       if ( !study->_is_nil() && study->StudyId() == mesh->GetStudyId() )
122       {
123         SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject(study, mesh->_this() );
124         CORBA::Object_var        obj = gen->GetNS()->Resolve( "/Kernel/Session" );
125         _session = SALOME::Session::_narrow( obj );
126         if ( !meshSO->_is_nil() && !_session->_is_nil() )
127         {
128           CORBA::String_var meshEntry = meshSO->GetID();
129           _messagePrefix = "SMESH/mesh_loading/";
130           _messagePrefix += meshEntry.in();
131
132           std::string msgToGUI = _messagePrefix + "/";
133           msgToGUI += SMESH_Comment( mesh->NbNodes() );
134           msgToGUI += "/";
135           msgToGUI += SMESH_Comment( mesh->NbElements() );
136
137           _session->emitMessageOneWay( msgToGUI.c_str());
138         }
139       }
140     }
141     void sendStop()
142     {
143       if ( !_messagePrefix.empty() )
144       {
145         std::string msgToGUI = _messagePrefix + "/stop";
146         _session->emitMessageOneWay( msgToGUI.c_str());
147         _messagePrefix.clear();
148       }
149     }
150     ~SignalToGUI() { sendStop(); }
151   };
152
153   //=============================================================================
154   /*!
155    * \brief Creates SMDS_Position according to shape type
156    */
157   //=============================================================================
158
159   class PositionCreator {
160   public:
161     SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
162       return (this->*myFuncTable[ type ])();
163     }
164     PositionCreator() {
165       myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition );
166       myFuncTable[ TopAbs_SOLID  ] = & PositionCreator::volumePosition;
167       myFuncTable[ TopAbs_FACE   ] = & PositionCreator::facePosition;
168       myFuncTable[ TopAbs_EDGE   ] = & PositionCreator::edgePosition;
169       myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition;
170     }
171   private:
172     SMDS_PositionPtr edgePosition()    const { return SMDS_PositionPtr( new SMDS_EdgePosition  ); }
173     SMDS_PositionPtr facePosition()    const { return SMDS_PositionPtr( new SMDS_FacePosition  ); }
174     SMDS_PositionPtr volumePosition()  const { return SMDS_PositionPtr( new SMDS_SpacePosition ); }
175     SMDS_PositionPtr vertexPosition()  const { return SMDS_PositionPtr( new SMDS_VertexPosition); }
176     SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition();  }
177     typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const;
178     std::vector<FmakePos> myFuncTable;
179   };
180
181   //================================================================================
182   /*!
183    * \brief Returns ids of simple shapes composing a complex one
184    */
185   //================================================================================
186
187   std::vector<int> getSimpleSubMeshIds( SMESHDS_Mesh* meshDS, int shapeId )
188   {
189     std::vector<int> ids;
190
191     std::list<TopoDS_Shape> shapeQueue( 1, meshDS->IndexToShape( shapeId ));
192     std::list<TopoDS_Shape>::iterator shape = shapeQueue.begin();
193     for ( ; shape != shapeQueue.end(); ++shape )
194     {
195       if ( shape->IsNull() ) continue;
196       if ( shape->ShapeType() == TopAbs_COMPOUND ||
197            shape->ShapeType() == TopAbs_COMPSOLID )
198       {
199         for ( TopoDS_Iterator it( *shape ); it.More(); it.Next() )
200           shapeQueue.push_back( it.Value() );
201       }
202       else
203       {
204         ids.push_back( meshDS->ShapeToIndex( *shape ));
205       }
206     }
207     return ids;
208   }
209
210   //================================================================================
211   /*!
212    * \brief Return EEntiteMaillage by EGeometrieElement
213    */
214   //================================================================================
215
216   MED::EEntiteMaillage entityByGeom(const MED::EGeometrieElement geom )
217   {
218     return geom == MED::eBALL ? MED::eSTRUCT_ELEMENT : MED::eMAILLE;
219   }
220
221   //================================================================================
222   /*!
223    * \brief Return a map< EGeometrieElement, SMDSAbs_EntityType >
224    */
225   //================================================================================
226
227   typedef std::map< MED::EGeometrieElement, SMDSAbs_EntityType > Tmed2smeshElemTypeMap;
228   const Tmed2smeshElemTypeMap& med2smeshElemTypeMap()
229   {
230     static Tmed2smeshElemTypeMap med2smeshTypes;
231     if ( med2smeshTypes.empty() )
232     {
233       for  ( int iG = 0; iG < SMDSEntity_Last; ++iG )
234       {
235         SMDSAbs_EntityType    smdsType = (SMDSAbs_EntityType) iG;
236         MED::EGeometrieElement medType =
237           (MED::EGeometrieElement) DriverMED::GetMedGeoType( smdsType );
238         med2smeshTypes.insert( std::make_pair( medType, smdsType ));
239       }
240     }
241     return med2smeshTypes;
242   }
243
244   //================================================================================
245   /*!
246    * \brief Writes meshInfo into a HDF file
247    */
248   //================================================================================
249
250   void meshInfo2hdf( SMESH::long_array_var meshInfo,
251                      const std::string&    name,
252                      HDFgroup*             hdfGroup)
253   {
254     // we use med identification of element (MED::EGeometrieElement) types
255     // but not enum SMDSAbs_EntityType because values of SMDSAbs_EntityType may
256     // change at insertion of new items in the middle.
257     //const vector<MED::EGeometrieElement>& medTypes = mesh2medElemType();
258
259     std::vector<int> data;
260
261     for ( size_t i = 0; i < meshInfo->length(); ++i )
262       if ( meshInfo[i] > 0 )
263       {
264         data.push_back( DriverMED::GetMedGeoType( SMDSAbs_EntityType( i ))); //medTypes[ i ] );
265         data.push_back( meshInfo[ i ] );
266       }
267
268     if ( !data.empty() )
269     {
270       hdf_size datasetSize[] = { data.size() };
271       HDFarray* anArray = new HDFarray(0, HDF_INT32, 1, datasetSize);
272       anArray->CreateOnDisk();
273       datasetSize[0] = 1;
274       HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup, HDF_ARRAY, datasetSize, 1 );
275       dataset->SetArrayId(anArray->GetId());
276       dataset->CreateOnDisk();
277       dataset->WriteOnDisk( & data[0]  );
278       dataset->CloseOnDisk();
279       anArray->CloseOnDisk();
280     }
281   }
282 }
283
284 //================================================================================
285 /*!
286  * \brief Reads meshInfo from a HDF file
287  */
288 //================================================================================
289
290 void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name,
291                                       HDFgroup*          hdfGroup)
292 {
293   if ( hdfGroup->ExistInternalObject( name.c_str()) )
294   {
295     HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup );
296     dataset->OpenOnDisk();
297
298     // // hdf_size datasetSize[ 1 ];
299     // // HDFarray *array = new HDFarray(dataset);
300     // // array->GetDim( datasetSize );
301     // int size = dataset->GetSize();
302
303     std::vector<int> info( SMDSEntity_Last * 2, 0 );
304     dataset->ReadFromDisk( &info[0] );
305     dataset->CloseOnDisk();
306
307     const Tmed2smeshElemTypeMap& med2smesh = med2smeshElemTypeMap();
308     Tmed2smeshElemTypeMap::const_iterator me2sme, me2smeEnd = med2smesh.end();
309     for ( size_t i = 0; i < info.size(); )
310     {
311       int medType = info[i++];
312       int nbElems = info[i++];
313       if ( !nbElems ) break;
314       me2sme = med2smesh.find( (MED::EGeometrieElement) medType );
315       if ( me2sme != me2smeEnd )
316         setNb( me2sme->second, nbElems );
317     }
318   }
319   _isInfoOk = true;
320
321   if ( NbNodes() == GroupOnFilter_OutOfDate ) // case of !SMESHDS_GroupOnFilter::IsUpToDate()
322   {
323     _isInfoOk = false;
324     setNb( SMDSEntity_Node, 0 );
325   }
326 }
327
328 //================================================================================
329 /*!
330  * \brief Constructor callable by SMESH_PreMeshInfo only
331  */
332 //================================================================================
333
334 SMESH_PreMeshInfo::SMESH_PreMeshInfo(SMESH_Mesh_i*      mesh,
335                                      const int          meshID,
336                                      const std::string& medFile,
337                                      const std::string& hdfFile)
338   : _medFileName( medFile ),
339     _hdfFileName( hdfFile ),
340     _toRemoveFiles( false ),
341     _meshID( meshID ),
342     _mesh( mesh ),
343     _isInfoOk( false ),
344     _elemCounter( 0 )
345 {
346 }
347
348 //================================================================================
349 /*!
350  * \brief Release temporary files
351  */
352 //================================================================================
353
354 SMESH_PreMeshInfo::~SMESH_PreMeshInfo()
355 {
356   if ( _toRemoveFiles ) // it can be true only for SMESH_PreMeshInfo of the mesh
357     filesNoMoreNeeded( _mesh, _medFileName, _hdfFileName );
358
359   _toRemoveFiles = false;
360 }
361
362 //================================================================================
363 /*!
364  * \brief fills SMESH_PreMeshInfo field of all objects of mesh
365  */
366 //================================================================================
367
368 void SMESH_PreMeshInfo::LoadFromFile( SMESH_Mesh_i*      mesh,
369                                       const int          meshID,
370                                       const std::string& medFile,
371                                       const std::string& hdfFile,
372                                       const bool         toRemoveFiles)
373 {
374   SMESH_TRY;
375
376   SMESH_PreMeshInfo* meshPreInfo = new SMESH_PreMeshInfo( mesh,meshID,medFile,hdfFile );
377   mesh->changePreMeshInfo() = meshPreInfo;
378
379   meshPreInfo->_toRemoveFiles = toRemoveFiles;
380   if ( toRemoveFiles )
381     meshInfoLoaded( mesh );
382
383   if ( meshPreInfo->readPreInfoFromHDF() )
384     // all SMESH_PreMeshInfo's are stored in HDF file (written after
385     // implementing SMESH_PreMeshInfo)
386     return;
387
388   // try to read SMESH_PreMeshInfo from med file (as study is older than SMESH_PreMeshInfo)
389   if ( meshPreInfo->readMeshInfo() )
390   {
391     meshPreInfo->readGroupInfo();
392     meshPreInfo->readSubMeshInfo();
393   }
394   else
395   {
396     meshPreInfo->FullLoadFromFile();
397   }
398   SMESH_CATCH( SMESH::doNothing );
399 }
400
401 //================================================================================
402 /*!
403  * \brief Tries to read all SMESH_PreMeshInfo from a HDF file
404  *  \retval bool - true if succeeded
405  *
406  * This method is symmetrical to SaveToFile()
407  */
408 //================================================================================
409
410 bool SMESH_PreMeshInfo::readPreInfoFromHDF()
411 {
412   HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
413   aFile->OpenOnDisk( HDF_RDONLY );
414
415   SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << _meshID;
416   const bool infoAvailable = aFile->ExistInternalObject( hdfGroupName );
417   if ( infoAvailable )
418   {
419     HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile );
420     infoHdfGroup->OpenOnDisk();
421
422     _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup );
423
424     // read SMESH_PreMeshInfo of groups
425     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
426     for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
427     {
428       if ( SMESH_GroupBase_i* group_i =
429            SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
430       {
431         group_i->changePreMeshInfo() = newInstance();
432         if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() )
433         {
434           const std::string name = group->GetStoreName();
435           group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup );
436         }
437       }
438     }
439
440     // read SMESH_PreMeshInfo of sub-meshes
441     map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
442     for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
443     {
444       if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
445       {
446         sm->changePreMeshInfo() = newInstance();
447         sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()), infoHdfGroup );
448       }
449     }
450   }
451
452   aFile->CloseOnDisk();
453   delete aFile;
454
455   return infoAvailable;
456 }
457
458 //================================================================================
459 /*!
460  * \brief Reads mesh info of mesh from the med file
461  */
462 //================================================================================
463
464 bool SMESH_PreMeshInfo::readMeshInfo()
465 {
466   _isInfoOk = true;
467
468   MED::PWrapper aMed = MED::CrWrapper(_medFileName,true);
469   // if ( aMed->GetVersion() != MED::eV2_2 )
470   //   return false;
471
472   MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
473
474   // read nb nodes
475   int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo ));
476   if ( nbNodes > 0 )
477   {
478     setNb( SMDSEntity_Node, nbNodes);
479
480     // read nb of elements
481     Tmed2smeshElemTypeMap::const_iterator me2sme    = med2smeshElemTypeMap().begin();
482     Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
483     for ( ; me2sme != me2smeEnd; ++me2sme )
484     {
485       int nbElems = aMed->GetNbCells( medMeshInfo, entityByGeom(me2sme->first), me2sme->first );
486       if ( nbElems > 0 )
487         setNb( me2sme->second, nbElems );
488     }
489   }
490   return true;
491 }
492
493 //================================================================================
494 /*!
495  * \brief Reads info of groups from the med file
496  */
497 //================================================================================
498
499 void SMESH_PreMeshInfo::readGroupInfo()
500 {
501   if ( _mesh->_mapGroups.empty() ) return;
502
503   // make SMESH_PreMeshInfo of groups
504   map< std::string, SMESH_PreMeshInfo* > name2GroupInfo;
505   map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
506   for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
507   {
508     if ( SMESH_GroupBase_i* group_i =
509          SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
510     {
511       SMESH_PreMeshInfo* info = newInstance();
512       group_i->changePreMeshInfo() = info;
513       if ( SMESHDS_Group* group = dynamic_cast< SMESHDS_Group* >( group_i->GetGroupDS() ))
514       {
515         std::string name = group->GetStoreName();
516         name2GroupInfo.insert( std::make_pair( name, info ));
517         info->_isInfoOk = true;
518       }
519     }
520   }
521
522   map< int, vector< SMESH_PreMeshInfo* > > famId2grInfo;
523
524   MED::PWrapper aMed = MED::CrWrapper(_medFileName,false);
525   MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
526
527   // read families to fill in famId2grInfo
528   int nbFams = aMed->GetNbFamilies( medMeshInfo );
529   if ( nbFams <= 1 ) return; // zero family is always present
530   for ( int iF = 0; iF <= nbFams; ++iF )
531   {
532     int nbGroups = aMed->GetNbFamGroup( iF, medMeshInfo );
533     if ( nbGroups < 1 ) continue;
534     MED::PFamilyInfo medFamInfo = aMed->CrFamilyInfo( medMeshInfo, nbGroups, nbGroups );
535     aMed->GetFamilyInfo( iF, medFamInfo ); // read groups of a family
536     vector< SMESH_PreMeshInfo* >& grInfoVec = famId2grInfo[ medFamInfo->GetId() ];
537     for ( int iG = 0; iG < nbGroups; ++iG )
538     {
539       const std::string grName = medFamInfo->GetGroupName( iG );
540       map< std::string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.find( grName );
541       if ( n2i != name2GroupInfo.end() )
542         grInfoVec.push_back( n2i->second );
543     }
544   }
545
546   // read family numbers of elements
547   Tmed2smeshElemTypeMap::const_iterator me2sme    = med2smeshElemTypeMap().begin();
548   Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
549   MED::PElemInfo medElemInfo = aMed->CrElemInfo( medMeshInfo, 0 );
550   MED::TIntVector& famNums = medElemInfo->myFamNum;
551   for ( ; me2sme != me2smeEnd; ++me2sme ) // loop on elem types
552   {
553     famNums.resize( NbEntities( me2sme->second ));
554     if ( famNums.empty() ) continue;
555     aMed->GetFamilies( medElemInfo, famNums.size(), entityByGeom(me2sme->first), me2sme->first );
556     // distribute elements of a type among groups
557     map< int, vector< SMESH_PreMeshInfo* > >::iterator f2infos = famId2grInfo.begin();
558     for ( size_t i = 0; i < famNums.size(); ++i )
559     {
560       if ( famNums[i] != f2infos->first )
561       {
562         f2infos = famId2grInfo.find( famNums[i] );
563         if ( f2infos == famId2grInfo.end() )
564           f2infos = famId2grInfo.insert
565             ( std::make_pair( famNums[i], vector< SMESH_PreMeshInfo*>())).first;
566       }
567       vector< SMESH_PreMeshInfo* >& infoVec = f2infos->second ;
568       for ( size_t j = 0; j < infoVec.size(); ++j )
569         infoVec[j]->_elemCounter++;
570     }
571     // pass _elemCounter to a real elem type
572     map< std::string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.begin();
573     for ( ; n2i != name2GroupInfo.end(); ++n2i )
574     {
575       SMESH_PreMeshInfo* info = n2i->second;
576       info->setNb( me2sme->second, info->_elemCounter );
577       info->_elemCounter = 0;
578     }
579   }
580 }
581
582 //================================================================================
583 /*!
584  * \brief Reads info of sub-meshes from hdf file of old study
585  */
586 //================================================================================
587
588 void SMESH_PreMeshInfo::readSubMeshInfo()
589 {
590   if ( _mesh->_mapSubMeshIor.empty() ) return;
591
592   // create SMESH_PreMeshInfo of sub-meshes
593   map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
594   for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
595   {
596     if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
597     {
598       sm->changePreMeshInfo() = newInstance();
599       sm->changePreMeshInfo()->_isInfoOk = true;
600     }
601   }
602
603   // try to read 
604   HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
605   aFile->OpenOnDisk( HDF_RDONLY );
606
607   char meshGrpName[ 30 ];
608   sprintf( meshGrpName, "Mesh %d", _meshID );
609   if ( aFile->ExistInternalObject( meshGrpName ) )
610   {
611     HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
612     aTopGroup->OpenOnDisk();
613     if ( aTopGroup->ExistInternalObject( "Submeshes" ))
614     {
615       HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
616       aGroup->OpenOnDisk();
617
618       SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
619       int maxSmId = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
620
621       for ( int isNode = 0; isNode < 2; ++isNode )
622       {
623         std::string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
624         if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
625         {
626           // read sub-mesh id of all nodes or elems
627           HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
628           aDataset->OpenOnDisk();
629           int nbElems = aDataset->GetSize();
630           int* smIDs = new int [ nbElems ];
631           aDataset->ReadFromDisk( smIDs );
632           aDataset->CloseOnDisk();
633           // count nb elems in each sub-mesh
634           vector<int> nbBySubmeshId( maxSmId + 1, 0 );
635           for ( int i = 0; i < nbElems; ++i )
636           {
637             const int smID = smIDs[ i ];
638             if ( smID < (int) nbBySubmeshId.size() )
639               nbBySubmeshId[ smID ]++;
640           }
641           delete [] smIDs;
642
643           // store nb elems in SMESH_PreMeshInfo of sub-meshes
644           map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
645           for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
646           {
647             if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
648             {
649               SMESH_PreMeshInfo* & info = sm->changePreMeshInfo();
650
651               vector<int> smIds = getSimpleSubMeshIds( meshDS, id2sm->first );
652               for ( size_t i = 0; i < smIds.size(); ++i )
653                 info->_elemCounter += nbBySubmeshId[ smIds[i] ];
654
655               SMDSAbs_EntityType elemType;
656               if ( isNode )
657               {
658                 elemType = SMDSEntity_Node;
659               }
660               else
661               {
662                 bool koElemType = false;
663                 const TopoDS_Shape& shape = meshDS->IndexToShape( smIds[0] );
664                 elemType = getElemType( shape.ShapeType(), info->_elemCounter, koElemType );
665                 info->_isInfoOk = !koElemType;
666               }
667               info->setNb( elemType, info->_elemCounter );
668             }
669           }
670         } // if ( aGroup->ExistInternalObject( aDSName ))
671       } // for ( int isNode = 0; isNode < 2; ++isNode )
672
673       aGroup->CloseOnDisk();
674     } // if ( aTopGroup->ExistInternalObject( "Submeshes" ))
675
676     aTopGroup->CloseOnDisk();
677   } // if ( aFile->ExistInternalObject( meshGrpName ) )
678
679   aFile->CloseOnDisk();
680   delete aFile;
681 }
682
683 //================================================================================
684 /*!
685  * \brief Return type of element for sub-mesh on a shape of given type
686  */
687 //================================================================================
688
689 SMDSAbs_EntityType SMESH_PreMeshInfo::getElemType( const TopAbs_ShapeEnum shapeType,
690                                                    const int              nbElemsInSubMesh,
691                                                    bool&                  isKoType) const
692 {
693   isKoType = false;
694   int type, typeEnd;
695   SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
696
697   switch ( shapeType )
698   {
699   case TopAbs_SOLID:
700     type = SMDSEntity_Tetra;
701     typeEnd = SMDSEntity_Last;
702     isKoType = ( meshInfo->NbVolumes() != nbElemsInSubMesh );
703     break;
704   case TopAbs_FACE:
705   case TopAbs_SHELL:  
706     type = SMDSEntity_Triangle;
707     typeEnd = SMDSEntity_Tetra;
708     isKoType = ( meshInfo->NbFaces() != nbElemsInSubMesh );
709     break;
710   case TopAbs_WIRE:
711   case TopAbs_EDGE:   return SMDSEntity_Edge;
712   case TopAbs_VERTEX: return SMDSEntity_0D;
713   default:            return SMDSEntity_Last;
714   }
715
716   if ( !isKoType )
717   {
718     for ( int t = type; t < typeEnd; ++t )
719       if ( nbElemsInSubMesh == meshInfo->NbEntities( SMDSAbs_EntityType( t )))
720         return SMDSAbs_EntityType( t );
721   }
722   isKoType = true;
723   return SMDSAbs_EntityType( type );
724 }
725
726 //================================================================================
727 /*!
728  * \brief Saves SMESH_PreMeshInfo to the study file
729  */
730 //================================================================================
731
732 void SMESH_PreMeshInfo::SaveToFile( SMESH_Mesh_i* mesh,
733                                     const int     meshID,
734                                     HDFfile*      hdfFile)
735 {
736   // create a HDF group for SMESH_PreMeshInfo of this mesh
737   SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << meshID;
738   HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, hdfFile );
739   infoHdfGroup->CreateOnDisk();
740
741   SMESH_TRY;
742
743   // info of mesh
744   meshInfo2hdf( mesh->GetMeshInfo(), "Mesh", infoHdfGroup );
745   
746   // info of groups
747   SMESH_PreMeshInfo incompleteInfo( 0,0,"","");
748   incompleteInfo.setNb( SMDSEntity_Node, GroupOnFilter_OutOfDate );
749   SMESHDS_Mesh* meshDS = mesh->GetImpl().GetMeshDS();
750
751   map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = mesh->_mapGroups.begin();
752   for ( ; i2group != mesh->_mapGroups.end(); ++i2group )
753   {
754     if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
755     {
756       SMESHDS_GroupBase * group = group_i->GetGroupDS();
757       if ( SMESHDS_GroupOnFilter* gof = dynamic_cast<SMESHDS_GroupOnFilter*>(group))
758       {
759         // prevent too long storage time due to applying filter to many elements
760         if ( !gof->IsUpToDate() && meshDS->GetMeshInfo().NbElements( gof->GetType() ) > 1e5 )
761         {
762           meshInfo2hdf( incompleteInfo.GetMeshInfo(),
763                         group->GetStoreName(),
764                         infoHdfGroup);
765           continue;
766         }
767       }
768       meshInfo2hdf( group_i->GetMeshInfo(), group->GetStoreName(), infoHdfGroup);
769     }
770   }
771
772   // info of sub-meshes
773   map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = mesh->_mapSubMeshIor.begin();
774   for ( ; id2sm != mesh->_mapSubMeshIor.end(); ++id2sm )
775   {
776     if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
777     {
778       meshInfo2hdf( sm->GetMeshInfo(),
779                     SMESH_Comment( sm->GetId() ),
780                     infoHdfGroup);
781     }
782   }
783
784   SMESH_CATCH( SMESH::doNothing );
785
786   infoHdfGroup->CloseOnDisk();
787 }
788
789 //================================================================================
790 /*!
791  * \brief Reads all data and remove all SMESH_PreMeshInfo fields from objects
792  */
793 //================================================================================
794
795 void SMESH_PreMeshInfo::FullLoadFromFile() const
796 {
797   SignalToGUI signalOnLoading( _mesh );
798
799   SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
800   _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info
801
802   ::SMESH_Mesh&   mesh = _mesh->GetImpl();
803   SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
804
805   SMESH_TRY;
806
807   MYDEBUGOUT( "BEG FullLoadFromFile() " << _meshID );
808
809   // load mesh
810   DriverMED_R_SMESHDS_Mesh myReader;
811   myReader.SetFile( _medFileName.c_str() );
812   myReader.SetMesh( meshDS );
813   myReader.SetMeshId( _meshID );
814   myReader.Perform();
815
816   // load groups
817   const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
818   set<SMESHDS_GroupBase*>::const_iterator groupIt = groups.begin();
819   for ( ; groupIt != groups.end(); ++groupIt )
820     if ( SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( *groupIt ))
821       myReader.GetGroup( aGrp );
822
823   // load sub-meshes
824   readSubMeshes( &myReader );
825
826   SMESH_CATCH( SMESH::doNothing );
827
828   _mesh->changePreMeshInfo() = meshInfo;
829
830   ForgetAllData();
831
832   signalOnLoading.sendStop();
833
834   meshDS->Modified();
835
836   // load dependent meshes referring/referred via hypotheses
837   mesh.GetSubMesh( mesh.GetShapeToMesh() )->
838     ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED);
839
840   MYDEBUGOUT( "END FullLoadFromFile()" );
841 }
842
843 //================================================================================
844 /*!
845  * \brief Reads full data of sub-meshes
846  */
847 //================================================================================
848
849 void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const
850 {
851   HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
852   aFile->OpenOnDisk( HDF_RDONLY );
853
854   char meshGrpName[ 30 ];
855   sprintf( meshGrpName, "Mesh %d", _meshID );
856   if ( aFile->ExistInternalObject( meshGrpName ) )
857   {
858     HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
859     aTopGroup->OpenOnDisk();
860
861     SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
862
863     // issue 0020693. Restore _isModified flag
864     if ( aTopGroup->ExistInternalObject( "_isModified" ))
865     {
866       HDFdataset* aDataset = new HDFdataset( "_isModified", aTopGroup );
867       aDataset->OpenOnDisk();
868       hdf_size size = aDataset->GetSize();
869       int* isModified = new int[ size ];
870       aDataset->ReadFromDisk( isModified );
871       aDataset->CloseOnDisk();
872       _mesh->GetImpl().SetIsModified( bool(*isModified));
873       delete [] isModified;
874     }
875
876     bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
877     if ( submeshesInFamilies ) // from MED
878     {
879       // old way working before fix of PAL 12992
880       reader->CreateAllSubMeshes();
881     }
882     else
883     {
884       // open a group
885       HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
886       aGroup->OpenOnDisk();
887
888       int maxID = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
889       vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 );
890       vector< TopAbs_ShapeEnum  > smType   ( maxID + 1, TopAbs_SHAPE );
891
892       PositionCreator aPositionCreator;
893
894       SMDS_NodeIteratorPtr nIt = meshDS->nodesIterator();
895       SMDS_ElemIteratorPtr eIt = meshDS->elementsIterator();
896       for ( int isNode = 0; isNode < 2; ++isNode )
897       {
898         std::string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
899         if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
900         {
901           HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
902           aDataset->OpenOnDisk();
903           // read submesh IDs for all elements sorted by ID
904           size_t nbElems = aDataset->GetSize();
905           int* smIDs = new int [ nbElems ];
906           aDataset->ReadFromDisk( smIDs );
907           aDataset->CloseOnDisk();
908
909           // get elements sorted by ID
910           TIDSortedElemSet elemSet;
911           if ( isNode )
912             while ( nIt->more() ) elemSet.insert( elemSet.end(), nIt->next() );
913           else
914             while ( eIt->more() ) elemSet.insert( elemSet.end(), eIt->next() );
915           //ASSERT( elemSet.size() == nbElems ); -- issue 20182
916           // -- Most probably a bad study was saved when there were
917           // not fixed bugs in SMDS_MeshInfo
918           if ( elemSet.size() < nbElems ) {
919 #ifdef _DEBUG_
920             cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
921 #endif
922             nbElems = elemSet.size();
923           }
924           // add elements to sub-meshes
925           TIDSortedElemSet::iterator iE = elemSet.begin();
926           for ( size_t i = 0; i < nbElems; ++i, ++iE )
927           {
928             int smID = smIDs[ i ];
929             if ( smID == 0 ) continue;
930             const SMDS_MeshElement* elem = *iE;
931             if ( smID > maxID ) {
932               // corresponding subshape no longer exists: maybe geom group has been edited
933               if ( _mesh->GetImpl().HasShapeToMesh() )
934                 meshDS->RemoveElement( elem );
935               continue;
936             }
937             // get or create submesh
938             SMESHDS_SubMesh* & sm = subMeshes[ smID ];
939             if ( ! sm ) {
940               sm = meshDS->NewSubMesh( smID );
941               smType[ smID ] = meshDS->IndexToShape( smID ).ShapeType();
942             }
943             // add
944             if ( isNode ) {
945               SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]);
946               SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( static_cast<const SMDS_MeshNode*>( elem ));
947               node->SetPosition( pos );
948               sm->AddNode( node );
949             } else {
950               sm->AddElement( elem );
951             }
952           }
953           delete [] smIDs;
954         }
955       }
956     } // end reading submeshes
957
958     // Read node positions on sub-shapes (SMDS_Position)
959
960     if ( aTopGroup->ExistInternalObject( "Node Positions" ))
961     {
962       // There are 5 datasets to read:
963       // "Nodes on Edges" - ID of node on edge
964       // "Edge positions" - U parameter on node on edge
965       // "Nodes on Faces" - ID of node on face
966       // "Face U positions" - U parameter of node on face
967       // "Face V positions" - V parameter of node on face
968       const char* aEid_DSName = "Nodes on Edges";
969       const char* aEu_DSName  = "Edge positions";
970       const char* aFu_DSName  = "Face U positions";
971       //char* aFid_DSName = "Nodes on Faces";
972       //char* aFv_DSName  = "Face V positions";
973
974       // data to retrieve
975       int nbEids = 0, nbFids = 0;
976       int *aEids = 0, *aFids  = 0;
977       double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
978
979       // open a group
980       HDFgroup* aGroup = new HDFgroup( "Node Positions", aTopGroup );
981       aGroup->OpenOnDisk();
982
983       // loop on 5 data sets
984       int aNbObjects = aGroup->nInternalObjects();
985       for ( int i = 0; i < aNbObjects; i++ )
986       {
987         // identify dataset
988         char aDSName[ HDF_NAME_MAX_LEN+1 ];
989         aGroup->InternalObjectIndentify( i, aDSName );
990         // read data
991         HDFdataset* aDataset = new HDFdataset( aDSName, aGroup );
992         aDataset->OpenOnDisk();
993         if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
994         {
995           double* pos = new double [ aDataset->GetSize() ];
996           aDataset->ReadFromDisk( pos );
997           // which one?
998           if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
999             aEpos = pos;
1000           else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
1001             aFupos = pos;
1002           else
1003             aFvpos = pos;
1004         }
1005         else // NODE IDS
1006         {
1007           int aSize = aDataset->GetSize();
1008
1009           // for reading files, created from 18.07.2005 till 10.10.2005
1010           if (aDataset->GetType() == HDF_STRING)
1011             aSize /= sizeof(int);
1012
1013           int* ids = new int [aSize];
1014           aDataset->ReadFromDisk( ids );
1015           // on face or nodes?
1016           if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
1017             aEids = ids;
1018             nbEids = aSize;
1019           }
1020           else {
1021             aFids = ids;
1022             nbFids = aSize;
1023           }
1024         }
1025         aDataset->CloseOnDisk();
1026       } // loop on 5 datasets
1027
1028       // Set node positions on edges or faces
1029       for ( int onFace = 0; onFace < 2; onFace++ )
1030       {
1031         int nbNodes = ( onFace ? nbFids : nbEids );
1032         if ( nbNodes == 0 ) continue;
1033         int* aNodeIDs = ( onFace ? aFids : aEids );
1034         double* aUPos = ( onFace ? aFupos : aEpos );
1035         double* aVPos = ( onFace ? aFvpos : 0 );
1036         // loop on node IDs
1037         for ( int iNode = 0; iNode < nbNodes; iNode++ )
1038         {
1039           const SMDS_MeshNode* node = meshDS->FindNode( aNodeIDs[ iNode ]);
1040           if ( !node ) continue; // maybe removed while Loading() if geometry changed
1041           SMDS_PositionPtr aPos = node->GetPosition();
1042           ASSERT( aPos );
1043           if ( onFace ) {
1044             // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182
1045             // -- Most probably a bad study was saved when there were
1046             // not fixed bugs in SMDS_MeshInfo
1047             if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
1048               SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
1049                 ( static_cast<const SMDS_FacePosition*>( aPos ));
1050               fPos->SetUParameter( aUPos[ iNode ]);
1051               fPos->SetVParameter( aVPos[ iNode ]);
1052             }
1053           }
1054           else {
1055             // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182
1056             if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) {
1057               SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
1058                 ( static_cast<const SMDS_EdgePosition*>( aPos ));
1059               fPos->SetUParameter( aUPos[ iNode ]);
1060             }
1061           }
1062         }
1063       }
1064       if ( aEids ) delete [] aEids;
1065       if ( aFids ) delete [] aFids;
1066       if ( aEpos ) delete [] aEpos;
1067       if ( aFupos ) delete [] aFupos;
1068       if ( aFvpos ) delete [] aFvpos;
1069
1070       aGroup->CloseOnDisk();
1071
1072     } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
1073
1074     aTopGroup->CloseOnDisk();
1075   } // if ( aFile->ExistInternalObject( meshGrpName ) )
1076   
1077   aFile->CloseOnDisk();
1078   delete aFile;
1079 }
1080
1081 //================================================================================
1082 /*!
1083  * \brief Remove all SMESH_PreMeshInfo fields from objects w/o data loading
1084  */
1085 //================================================================================
1086
1087 void SMESH_PreMeshInfo::ForgetAllData() const
1088 {
1089   SMESH_TRY;
1090
1091   if ( _mesh->changePreMeshInfo() != this )
1092     return _mesh->changePreMeshInfo()->ForgetAllData();
1093
1094   // remove SMESH_PreMeshInfo from groups
1095   map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
1096   for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
1097   {
1098     if ( SMESH_GroupBase_i* group_i =
1099          SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
1100     {
1101       SMESH_PreMeshInfo* & info = group_i->changePreMeshInfo();
1102       delete info;
1103       info = NULL;
1104     }
1105   }
1106   // remove SMESH_PreMeshInfo from sub-meshes
1107   map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
1108   for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
1109   {
1110     if ( SMESH_subMesh_i* sm_i = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
1111     {
1112       SMESH_PreMeshInfo* & info = sm_i->changePreMeshInfo();
1113       delete info;
1114       info = NULL;
1115     }
1116   }
1117   // remove SMESH_PreMeshInfo from the mesh
1118   _mesh->changePreMeshInfo() = NULL;
1119   delete this;
1120
1121   SMESH_CATCH( SMESH::doNothing );
1122
1123
1124   // Finalize loading
1125
1126   // SMESH_TRY;
1127
1128   // ::SMESH_Mesh& mesh = _mesh->GetImpl();
1129
1130   // // update hyps needing full mesh data restored (issue 20918)
1131   // // map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id2hyp= _mesh->_mapHypo.begin();
1132   // // for ( ; id2hyp != _mesh->_mapHypo.end(); ++id2hyp )
1133   // //   if ( SMESH_Hypothesis_i* hyp = SMESH::DownCast<SMESH_Hypothesis_i*>( id2hyp->second ))
1134   // //     hyp->UpdateAsMeshesRestored();
1135
1136
1137   // SMESH_CATCH( SMESH::doNothing );
1138 }
1139
1140 //================================================================================
1141 /*!
1142  * \brief remove all SMESH_PreMeshInfo fields from mesh and its child objects w/o data loading
1143  */
1144 //================================================================================
1145
1146 void SMESH_PreMeshInfo::ForgetAllData( SMESH_Mesh_i* mesh )
1147 {
1148   if ( mesh && mesh->changePreMeshInfo() )
1149     mesh->changePreMeshInfo()->ForgetAllData();
1150 }
1151
1152 //================================================================================
1153 /*!
1154  * \brief Calls either FullLoadFromFile() or ForgetAllData() depending on preferences
1155  */
1156 //================================================================================
1157
1158 void SMESH_PreMeshInfo::ForgetOrLoad() const
1159 {
1160   if ( SMESH_Gen_i::GetSMESHGen()->ToForgetMeshDataOnHypModif() &&
1161        _mesh->HasShapeToMesh())
1162     ForgetAllData();
1163   else
1164     FullLoadFromFile();
1165 }
1166
1167 //================================================================================
1168 /*!
1169  * \brief Method of SMESH_IDSource interface
1170  */
1171 //================================================================================
1172
1173 SMESH::array_of_ElementType* SMESH_PreMeshInfo::GetTypes() const
1174 {
1175   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
1176
1177   types->length( 4 );
1178   int nbTypes = 0;
1179   if (NbEdges())      types[nbTypes++] = SMESH::EDGE;
1180   if (NbFaces())      types[nbTypes++] = SMESH::FACE;
1181   if (NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
1182   if (Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
1183   if (NbBalls())      types[nbTypes++] = SMESH::BALL;
1184   types->length( nbTypes );
1185
1186   return types._retn();
1187 }
1188
1189 //================================================================================
1190 /*!
1191  * \brief Method of SMESH_IDSource interface returning nb elements by element type
1192  */
1193 //================================================================================
1194
1195 SMESH::long_array* SMESH_PreMeshInfo::GetMeshInfo() const
1196 {
1197   SMESH::long_array_var aRes = new SMESH::long_array();
1198   aRes->length(SMESH::Entity_Last);
1199   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1200     aRes[i] = 0;
1201
1202   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1203     aRes[i] = NbEntities((SMDSAbs_EntityType)i);
1204   return aRes._retn();
1205 }
1206
1207 //================================================================================
1208 /*!
1209  * Returns false if GetMeshInfo() returns incorrect information that may
1210  * happen if mesh data is not yet fully loaded from the file of study.
1211  */
1212 //================================================================================
1213
1214 bool SMESH_PreMeshInfo::IsMeshInfoCorrect() const
1215 {
1216   return _isInfoOk;
1217 }
1218
1219 //================================================================================
1220 /*!
1221  * \brief TEMPORARY method to remove study files on closing study;
1222  * RIGHT WAY: study files are remove automatically when meshes are destroyed
1223  */
1224 //================================================================================
1225
1226 void SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp)
1227 {
1228   SALOMEDS::Study_var study = smeshComp->GetStudy();
1229   if ( theStudyIDToMeshCounter[ (int) study->StudyId() ] > 0 )
1230   {
1231     SALOMEDS::ChildIterator_wrap itBig = study->NewChildIterator( smeshComp );
1232     for ( ; itBig->More(); itBig->Next() ) {
1233       SALOMEDS::SObject_wrap gotBranch = itBig->Value();
1234       CORBA::Object_var       anObject = SMESH_Gen_i::SObjectToObject( gotBranch );
1235       if ( SMESH_Mesh_i* mesh = SMESH::DownCast<SMESH_Mesh_i*>( anObject ))
1236       {
1237         if ( mesh->changePreMeshInfo() )
1238         {
1239           mesh->changePreMeshInfo()->ForgetAllData();
1240         }
1241       }
1242     }
1243   }
1244 }