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