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