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