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