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