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