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