From: eap Date: Fri, 24 Feb 2012 10:42:10 +0000 (+0000) Subject: 0021208: Performance issue when loading SMESH with an hdf file containing a big mesh X-Git-Tag: V6_5_0a1~111 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=feb9a2ff2ebfddb1b320d7f42c5b176a2aba26ec;hp=656d6656d48e949cb5493e4860c9837e71b4e0f6 0021208: Performance issue when loading SMESH with an hdf file containing a big mesh + SMESH_PreMeshInfo.hxx \ --- diff --git a/src/SMESH_I/Makefile.am b/src/SMESH_I/Makefile.am index a7862f5b4..322a38f0c 100644 --- a/src/SMESH_I/Makefile.am +++ b/src/SMESH_I/Makefile.am @@ -47,6 +47,7 @@ salomeinclude_HEADERS = \ SMESH_2smeshpy.hxx \ SMESH_NoteBook.hxx \ SMESH_Measurements_i.hxx \ + SMESH_PreMeshInfo.hxx \ SMESH.hxx # Scripts to be installed. @@ -78,7 +79,8 @@ dist_libSMESHEngine_la_SOURCES = \ SMESH_Pattern_i.cxx \ SMESH_2smeshpy.cxx \ SMESH_NoteBook.cxx \ - SMESH_Measurements_i.cxx + SMESH_Measurements_i.cxx \ + SMESH_PreMeshInfo.cxx # Executables targets bin_PROGRAMS = SMESHEngine diff --git a/src/SMESH_I/SMESH_PreMeshInfo.cxx b/src/SMESH_I/SMESH_PreMeshInfo.cxx new file mode 100644 index 000000000..e548f1f94 --- /dev/null +++ b/src/SMESH_I/SMESH_PreMeshInfo.cxx @@ -0,0 +1,1268 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_PreMeshInfo.cxx +// Created : Fri Feb 10 17:36:39 2012 +// Author : Edward AGAPOV (eap) +// + +#include "SMESH_PreMeshInfo.hxx" + +#include "DriverMED_R_SMESHDS_Mesh.h" +#include "SMDS_EdgePosition.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_SpacePosition.hxx" +#include "SMDS_VertexPosition.hxx" +#include "SMESHDS_Group.hxx" +#include "SMESHDS_GroupOnFilter.hxx" +#include "SMESH_Gen_i.hxx" +#include "SMESH_Group_i.hxx" +#include "SMESH_Mesh_i.hxx" +#include "SMESH_subMesh_i.hxx" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include CORBA_SERVER_HEADER(SALOME_Session) + +#define MYDEBUGOUT(msg) //std::cout << msg << std::endl; + +//================================================================================ +#define PreMeshInfo_TRY \ + try { OCC_CATCH_SIGNALS +//================================================================================ +#define PreMeshInfo_CATCH } \ + catch (Standard_Failure& ex) { \ + onExceptionCaught(SMESH_Comment("OCC Exception caught: \t")< theStudyIDToMeshCounter; + + //================================================================================ + /*! + * \brief Counts not fully loaded meshes + */ + //================================================================================ + + void meshInfoLoaded( SMESH_Mesh_i* mesh ) + { + map< int, int >::iterator id2counter = + theStudyIDToMeshCounter.insert( make_pair( (int) mesh->GetStudyId(), 0 )).first; + id2counter->second++; + } + //================================================================================ + /*! + * \brief Removes temporary files if none of meshes needs them + */ + //================================================================================ + + void filesNoMoreNeeded(SMESH_Mesh_i* mesh, + std::string medFile, + std::string hdfFile) + { + if ( --theStudyIDToMeshCounter[ (int) mesh->GetStudyId() ] == 0 ) + { + string tmpDir = SALOMEDS_Tool::GetDirFromPath( hdfFile ); + + SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames; + aFiles->length(2); + medFile = SALOMEDS_Tool::GetNameFromPath( medFile ) + ".med"; + hdfFile = SALOMEDS_Tool::GetNameFromPath( hdfFile ) + ".hdf"; + aFiles[0] = medFile.c_str(); + aFiles[1] = hdfFile.c_str(); + + SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true ); + } + } + + //================================================================================ + /*! + * \brief Method useful only to set a breakpoint to debug in case of exception + */ + //================================================================================ + + void onExceptionCaught(const string& msg) + { + INFOS( msg ); + MYDEBUGOUT( msg ); + } + + //============================================================================= + /*! + * \brief Class sending signals on start and finish of loading + */ + //============================================================================= + + class SignalToGUI + { + string _messagePrefix; + SALOME::Session_var _session; + public: + SignalToGUI( SMESH_Mesh_i* mesh ) + { + SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen(); + SALOMEDS::Study_var study = gen->GetCurrentStudy(); + if ( !study->_is_nil() && study->StudyId() == mesh->GetStudyId() ) + { + SALOMEDS::SObject_var meshSO = gen->ObjectToSObject(study, mesh->_this() ); + CORBA::Object_var obj = gen->GetNS()->Resolve( "/Kernel/Session" ); + _session = SALOME::Session::_narrow( obj ); + if ( !meshSO->_is_nil() && !_session->_is_nil() ) + { + CORBA::String_var meshEntry = meshSO->GetID(); + _messagePrefix = "mesh_loading/"; + _messagePrefix += meshEntry.in(); + + string msgToGUI = _messagePrefix + "/"; + msgToGUI += SMESH_Comment( mesh->NbNodes() ); + msgToGUI += "/"; + msgToGUI += SMESH_Comment( mesh->NbElements() ); + + _session->emitMessageOneWay( msgToGUI.c_str()); + } + } + } + void sendStop() + { + if ( !_messagePrefix.empty() ) + { + string msgToGUI = _messagePrefix + "/stop"; + _session->emitMessageOneWay( msgToGUI.c_str()); + _messagePrefix.clear(); + } + } + ~SignalToGUI() { sendStop(); } + }; + + //============================================================================= + /*! + * \brief Creates SMDS_Position according to shape type + */ + //============================================================================= + + class PositionCreator { + public: + SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) { + return (this->*myFuncTable[ type ])(); + } + PositionCreator() { + myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition ); + myFuncTable[ TopAbs_SOLID ] = & PositionCreator::volumePosition; + myFuncTable[ TopAbs_FACE ] = & PositionCreator::facePosition; + myFuncTable[ TopAbs_EDGE ] = & PositionCreator::edgePosition; + myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition; + } + private: + SMDS_PositionPtr edgePosition() const { return SMDS_PositionPtr( new SMDS_EdgePosition ); } + SMDS_PositionPtr facePosition() const { return SMDS_PositionPtr( new SMDS_FacePosition ); } + SMDS_PositionPtr volumePosition() const { return SMDS_PositionPtr( new SMDS_SpacePosition ); } + SMDS_PositionPtr vertexPosition() const { return SMDS_PositionPtr( new SMDS_VertexPosition); } + SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition(); } + typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const; + vector myFuncTable; + }; + + //================================================================================ + /*! + * \brief Returns ids of simple shapes composing a complex one + */ + //================================================================================ + + vector getSimpleSubMeshIds( SMESHDS_Mesh* meshDS, int shapeId ) + { + vector ids; + + list shapeQueue( 1, meshDS->IndexToShape( shapeId )); + list::iterator shape = shapeQueue.begin(); + for ( ; shape != shapeQueue.end(); ++shape ) + { + if ( shape->IsNull() ) continue; + if ( shape->ShapeType() == TopAbs_COMPOUND || + shape->ShapeType() == TopAbs_COMPSOLID ) + { + for ( TopoDS_Iterator it( *shape ); it.More(); it.Next() ) + shapeQueue.push_back( it.Value() ); + } + else + { + ids.push_back( meshDS->ShapeToIndex( *shape )); + } + } + return ids; + } + + //================================================================================ + /*! + * \brief Return a map< EGeometrieElement, SMDSAbs_EntityType > + */ + //================================================================================ + + typedef map< MED::EGeometrieElement, SMDSAbs_EntityType > Tmed2smeshElemTypeMap; + const Tmed2smeshElemTypeMap& med2smeshElemTypeMap() + { + static map< MED::EGeometrieElement, SMDSAbs_EntityType> med2smeshTypes; + if ( med2smeshTypes.empty() ) + { + med2smeshTypes[ MED::ePOINT1 ] = SMDSEntity_0D ; + med2smeshTypes[ MED::eSEG2 ] = SMDSEntity_Edge ; + med2smeshTypes[ MED::eSEG3 ] = SMDSEntity_Quad_Edge ; + med2smeshTypes[ MED::eTRIA3 ] = SMDSEntity_Triangle ; + med2smeshTypes[ MED::eTRIA6 ] = SMDSEntity_Quad_Triangle ; + med2smeshTypes[ MED::eQUAD4 ] = SMDSEntity_Quadrangle ; + med2smeshTypes[ MED::eQUAD8 ] = SMDSEntity_Quad_Quadrangle ; + med2smeshTypes[ MED::eQUAD9 ] = SMDSEntity_BiQuad_Quadrangle ; + med2smeshTypes[ MED::eTETRA4 ] = SMDSEntity_Tetra ; + med2smeshTypes[ MED::ePYRA5 ] = SMDSEntity_Pyramid ; + med2smeshTypes[ MED::ePENTA6 ] = SMDSEntity_Penta ; + med2smeshTypes[ MED::eHEXA8 ] = SMDSEntity_Hexa ; + med2smeshTypes[ MED::eOCTA12 ] = SMDSEntity_Hexagonal_Prism ; + med2smeshTypes[ MED::eTETRA10 ] = SMDSEntity_Quad_Tetra ; + med2smeshTypes[ MED::ePYRA13 ] = SMDSEntity_Quad_Pyramid ; + med2smeshTypes[ MED::ePENTA15 ] = SMDSEntity_Quad_Penta ; + med2smeshTypes[ MED::eHEXA20 ] = SMDSEntity_Quad_Hexa ; + med2smeshTypes[ MED::eHEXA27 ] = SMDSEntity_TriQuad_Hexa ; + med2smeshTypes[ MED::ePOLYGONE ] = SMDSEntity_Polygon ; + med2smeshTypes[ MED::ePOLYEDRE ] = SMDSEntity_Polyhedra ; + med2smeshTypes[ MED::eNONE ] = SMDSEntity_Node ; + } + return med2smeshTypes; + } + + //================================================================================ + /*! + * \brief Return a vector intended to retrieve + * MED::EGeometrieElement by SMDSAbs_EntityType + */ + //================================================================================ + + const vector& mesh2medElemType() + { + static vector mesh2medElemTypes; + if ( mesh2medElemTypes.empty() ) + { + mesh2medElemTypes.resize( SMDSEntity_Last + 1 ); + Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin(); + Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end(); + for ( ; me2sme != me2smeEnd; ++me2sme ) + mesh2medElemTypes[ me2sme->second ] = me2sme->first; + } + return mesh2medElemTypes; + } + + //================================================================================ + /*! + * \brief Writes meshInfo into a HDF file + */ + //================================================================================ + + void meshInfo2hdf( SMESH::long_array_var meshInfo, + const std::string& name, + HDFgroup* hdfGroup) + { + // we use med identification of element (MED::EGeometrieElement>) types + // but not enum SMDSAbs_EntityType because values of SMDSAbs_EntityType may + // change at insertion of new items in the middle. + const vector& medTypes = mesh2medElemType(); + + vector data; + + for ( size_t i = 0; i < meshInfo->length(); ++i ) + if ( meshInfo[i] > 0 ) + { + data.push_back( medTypes[ i ] ); + data.push_back( meshInfo[ i ] ); + } + + if ( !data.empty() ) + { + hdf_size datasetSize[] = { data.size() }; + HDFarray* anArray = new HDFarray(0, HDF_INT32, 1, datasetSize); + anArray->CreateOnDisk(); + datasetSize[0] = 1; + HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup, HDF_ARRAY, datasetSize, 1 ); + dataset->SetArrayId(anArray->GetId()); + dataset->CreateOnDisk(); + dataset->WriteOnDisk( & data[0] ); + dataset->CloseOnDisk(); + anArray->CloseOnDisk(); + } + } +} + +//================================================================================ +/*! + * \brief Reads meshInfo from a HDF file + */ +//================================================================================ + +void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name, + HDFgroup* hdfGroup) +{ + if ( hdfGroup->ExistInternalObject( name.c_str()) ) + { + HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup ); + dataset->OpenOnDisk(); + + // hdf_size datasetSize[ 1 ]; + // HDFarray *array = new HDFarray(dataset); + // array->GetDim( datasetSize ); + int size = dataset->GetSize(); + + int info[ SMDSEntity_Last * 2 ]; + dataset->ReadFromDisk( info ); + dataset->CloseOnDisk(); + + const Tmed2smeshElemTypeMap& med2smesh = med2smeshElemTypeMap(); + Tmed2smeshElemTypeMap::const_iterator me2sme, me2smeEnd = med2smesh.end(); + for ( int i = 0; i < size /**datasetSize*/; ) + { + int medType = info[i++]; + int nbElems = info[i++]; + me2sme = med2smesh.find( (MED::EGeometrieElement) medType ); + if ( me2sme != me2smeEnd ) + setNb( me2sme->second, nbElems ); + } + } + _isInfoOk = true; + + if ( NbNodes() == GroupOnFilter_OutOfDate ) // case of !SMESHDS_GroupOnFilter::IsUpToDate() + { + _isInfoOk = false; + setNb( SMDSEntity_Node, 0 ); + } +} + +//================================================================================ +/*! + * \brief Constructor callable by SMESH_PreMeshInfo only + */ +//================================================================================ + +SMESH_PreMeshInfo::SMESH_PreMeshInfo(SMESH_Mesh_i* mesh, + const int meshID, + const std::string& medFile, + const std::string& hdfFile) + : _medFileName( medFile ), + _hdfFileName( hdfFile ), + _toRemoveFiles( false ), + _meshID( meshID ), + _mesh( mesh ), + _isInfoOk( false ), + _elemCounter( 0 ) +{ +} + +//================================================================================ +/*! + * \brief Release temporary files + */ +//================================================================================ + +SMESH_PreMeshInfo::~SMESH_PreMeshInfo() +{ + if ( _toRemoveFiles ) // it can be true only for SMESH_PreMeshInfo of the mesh + filesNoMoreNeeded( _mesh, _medFileName, _hdfFileName ); + + _toRemoveFiles = false; +} + +//================================================================================ +/*! + * \brief fills SMESH_PreMeshInfo field of all objects of mesh + */ +//================================================================================ + +void SMESH_PreMeshInfo::LoadFromFile( SMESH_Mesh_i* mesh, + const int meshID, + const std::string& medFile, + const std::string& hdfFile, + const bool toRemoveFiles) +{ + PreMeshInfo_TRY; + + SMESH_PreMeshInfo* meshPreInfo = new SMESH_PreMeshInfo( mesh,meshID,medFile,hdfFile ); + mesh->changePreMeshInfo() = meshPreInfo; + + meshPreInfo->_toRemoveFiles = toRemoveFiles; + if ( toRemoveFiles ) + meshInfoLoaded( mesh ); + + if ( meshPreInfo->readPreInfoFromHDF() ) + // all SMESH_PreMeshInfo's are stored in HDF file (written after + // implementing SMESH_PreMeshInfo) + return; + + // try to read SMESH_PreMeshInfo from med file (as study is older than SMESH_PreMeshInfo) + if ( meshPreInfo->readMeshInfo() ) + { + meshPreInfo->readGroupInfo(); + meshPreInfo->readSubMeshInfo(); + } + else + { + meshPreInfo->FullLoadFromFile(); + } + PreMeshInfo_CATCH; +} + +//================================================================================ +/*! + * \brief Tries to read all SMESH_PreMeshInfo from a HDF file + * \retval bool - true if succeeded + * + * This method is symmetrical to SaveToFile() + */ +//================================================================================ + +bool SMESH_PreMeshInfo::readPreInfoFromHDF() +{ + HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() ); + aFile->OpenOnDisk( HDF_RDONLY ); + + SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << _meshID; + const bool infoAvailable = aFile->ExistInternalObject( hdfGroupName ); + if ( infoAvailable ) + { + + HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile ); + infoHdfGroup->OpenOnDisk(); + + _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup ); + + // read SMESH_PreMeshInfo of groups + map::const_iterator i2group = _mesh->_mapGroups.begin(); + for ( ; i2group != _mesh->_mapGroups.end(); ++i2group ) + { + if ( SMESH_GroupBase_i* group_i = + SMESH::DownCast( i2group->second )) + { + group_i->changePreMeshInfo() = newInstance(); + if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() ) + { + const string name = group->GetStoreName(); + group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup ); + } + } + } + + // read SMESH_PreMeshInfo of sub-meshes + map::iterator id2sm = _mesh->_mapSubMeshIor.begin(); + for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm ) + { + if ( SMESH_subMesh_i* sm = SMESH::DownCast( id2sm->second )) + { + sm->changePreMeshInfo() = newInstance(); + sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()), infoHdfGroup ); + } + } + } + + aFile->CloseOnDisk(); + delete aFile; + + return infoAvailable; +} + +//================================================================================ +/*! + * \brief Reads mesh info of mesh from the med file + */ +//================================================================================ + +bool SMESH_PreMeshInfo::readMeshInfo() +{ + _isInfoOk = true; + + MED::PWrapper aMed = MED::CrWrapper(_medFileName,true); + // if ( aMed->GetVersion() != MED::eV2_2 ) + // return false; + + MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID )); + + // read nb nodes + int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo )); + if ( nbNodes > 0 ) + { + setNb( SMDSEntity_Node, nbNodes); + + // read nb of elements + Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin(); + Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end(); + for ( ; me2sme != me2smeEnd; ++me2sme ) + { + int nbElems = aMed->GetNbCells( medMeshInfo, MED::eMAILLE, me2sme->first ); + if ( nbElems > 0 ) + setNb( me2sme->second, nbElems ); + } + } + return true; +} + +//================================================================================ +/*! + * \brief Reads info of groups from the med file + */ +//================================================================================ + +void SMESH_PreMeshInfo::readGroupInfo() +{ + if ( _mesh->_mapGroups.empty() ) return; + + // make SMESH_PreMeshInfo of groups + map< string, SMESH_PreMeshInfo* > name2GroupInfo; + map::const_iterator i2group = _mesh->_mapGroups.begin(); + for ( ; i2group != _mesh->_mapGroups.end(); ++i2group ) + { + if ( SMESH_GroupBase_i* group_i = + SMESH::DownCast( i2group->second )) + { + SMESH_PreMeshInfo* info = newInstance(); + group_i->changePreMeshInfo() = info; + if ( SMESHDS_Group* group = dynamic_cast< SMESHDS_Group* >( group_i->GetGroupDS() )) + { + string name = group->GetStoreName(); + name2GroupInfo.insert( make_pair( name, info )); + info->_isInfoOk = true; + } + } + } + + map< int, vector< SMESH_PreMeshInfo* > > famId2grInfo; + + MED::PWrapper aMed = MED::CrWrapper(_medFileName,false); + MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID )); + + // read families to fill in famId2grInfo + int nbFams = aMed->GetNbFamilies( medMeshInfo ); + if ( nbFams <= 1 ) return; // zero family is always present + for ( int iF = 0; iF <= nbFams; ++iF ) + { + int nbGroups = aMed->GetNbFamGroup( iF, medMeshInfo ); + if ( nbGroups < 1 ) continue; + MED::PFamilyInfo medFamInfo = aMed->CrFamilyInfo( medMeshInfo, nbGroups, nbGroups ); + aMed->GetFamilyInfo( iF, medFamInfo ); // read groups of a family + vector< SMESH_PreMeshInfo* >& grInfoVec = famId2grInfo[ medFamInfo->GetId() ]; + for ( int iG = 0; iG < nbGroups; ++iG ) + { + const string grName = medFamInfo->GetGroupName( iG ); + map< string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.find( grName ); + if ( n2i != name2GroupInfo.end() ) + grInfoVec.push_back( n2i->second ); + } + } + + // read family numbers of elements + Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin(); + Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end(); + MED::PElemInfo medElemInfo = aMed->CrElemInfo( medMeshInfo, 0 ); + MED::TIntVector& famNums = medElemInfo->myFamNum; + for ( ; me2sme != me2smeEnd; ++me2sme ) // loop on elem types + { + famNums.resize( NbEntities( me2sme->second )); + if ( famNums.empty() ) continue; + aMed->GetFamilies( medElemInfo, famNums.size(), MED::eMAILLE, me2sme->first ); + // distribute elements of a type among groups + map< int, vector< SMESH_PreMeshInfo* > >::iterator f2infos = famId2grInfo.begin(); + for ( size_t i = 0; i < famNums.size(); ++i ) + { + if ( famNums[i] != f2infos->first ) + { + f2infos = famId2grInfo.find( famNums[i] ); + if ( f2infos == famId2grInfo.end() ) + f2infos = famId2grInfo.insert + ( make_pair( famNums[i], vector< SMESH_PreMeshInfo*>())).first; + } + vector< SMESH_PreMeshInfo* >& infoVec = f2infos->second ; + for ( size_t j = 0; j < infoVec.size(); ++j ) + infoVec[j]->_elemCounter++; + } + // pass _elemCounter to a real elem type + map< string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.begin(); + for ( ; n2i != name2GroupInfo.end(); ++n2i ) + { + SMESH_PreMeshInfo* info = n2i->second; + info->setNb( me2sme->second, info->_elemCounter ); + info->_elemCounter = 0; + } + } +} + +//================================================================================ +/*! + * \brief Reads info of sub-meshes from hdf file of old study + */ +//================================================================================ + +void SMESH_PreMeshInfo::readSubMeshInfo() +{ + if ( _mesh->_mapSubMeshIor.empty() ) return; + + // create SMESH_PreMeshInfo of sub-meshes + map::iterator id2sm = _mesh->_mapSubMeshIor.begin(); + for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm ) + { + if ( SMESH_subMesh_i* sm = SMESH::DownCast( id2sm->second )) + { + sm->changePreMeshInfo() = newInstance(); + sm->changePreMeshInfo()->_isInfoOk = true; + } + } + + // try to read + HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() ); + aFile->OpenOnDisk( HDF_RDONLY ); + + char meshGrpName[ 30 ]; + sprintf( meshGrpName, "Mesh %d", _meshID ); + if ( aFile->ExistInternalObject( meshGrpName ) ) + { + HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile ); + aTopGroup->OpenOnDisk(); + if ( aTopGroup->ExistInternalObject( "Submeshes" )) + { + HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup ); + aGroup->OpenOnDisk(); + + SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS(); + int maxSmId = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() ); + + for ( int isNode = 0; isNode < 2; ++isNode ) + { + string aDSName( isNode ? "Node Submeshes" : "Element Submeshes"); + if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() )) + { + // read sub-mesh id of all nodes or elems + HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup ); + aDataset->OpenOnDisk(); + int nbElems = aDataset->GetSize(); + int* smIDs = new int [ nbElems ]; + aDataset->ReadFromDisk( smIDs ); + aDataset->CloseOnDisk(); + // count nb elems in each sub-mesh + vector nbBySubmeshId( maxSmId + 1, 0 ); + for ( int i = 0; i < nbElems; ++i ) + { + const int smID = smIDs[ i ]; + if ( smID < (int) nbBySubmeshId.size() ) + nbBySubmeshId[ smID ]++; + } + delete [] smIDs; + + // store nb elems in SMESH_PreMeshInfo of sub-meshes + map::iterator id2sm = _mesh->_mapSubMeshIor.begin(); + for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm ) + { + if ( SMESH_subMesh_i* sm = SMESH::DownCast( id2sm->second )) + { + SMESH_PreMeshInfo* & info = sm->changePreMeshInfo(); + + vector smIds = getSimpleSubMeshIds( meshDS, id2sm->first ); + for ( size_t i = 0; i < smIds.size(); ++i ) + info->_elemCounter += nbBySubmeshId[ smIds[i] ]; + + SMDSAbs_EntityType elemType; + if ( isNode ) + { + elemType = SMDSEntity_Node; + } + else + { + bool koElemType = false; + const TopoDS_Shape& shape = meshDS->IndexToShape( smIds[0] ); + elemType = getElemType( shape.ShapeType(), info->_elemCounter, koElemType ); + info->_isInfoOk = !koElemType; + } + info->setNb( elemType, info->_elemCounter ); + } + } + } // if ( aGroup->ExistInternalObject( aDSName )) + } // for ( int isNode = 0; isNode < 2; ++isNode ) + + aGroup->CloseOnDisk(); + } // if ( aTopGroup->ExistInternalObject( "Submeshes" )) + + aTopGroup->CloseOnDisk(); + } // if ( aFile->ExistInternalObject( meshGrpName ) ) + + aFile->CloseOnDisk(); + delete aFile; +} + +//================================================================================ +/*! + * \brief Return type of element for sub-mesh on a shape of given type + */ +//================================================================================ + +SMDSAbs_EntityType SMESH_PreMeshInfo::getElemType( const TopAbs_ShapeEnum shapeType, + const int nbElemsInSubMesh, + bool& isKoType) const +{ + isKoType = false; + int type, typeEnd; + SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo(); + + switch ( shapeType ) + { + case TopAbs_SOLID: + type = SMDSEntity_Tetra; + typeEnd = SMDSEntity_Last; + isKoType = ( meshInfo->NbVolumes() != nbElemsInSubMesh ); + break; + case TopAbs_FACE: + case TopAbs_SHELL: + type = SMDSEntity_Triangle; + typeEnd = SMDSEntity_Tetra; + isKoType = ( meshInfo->NbFaces() != nbElemsInSubMesh ); + break; + case TopAbs_WIRE: + case TopAbs_EDGE: return SMDSEntity_Edge; + case TopAbs_VERTEX: return SMDSEntity_0D; + default: return SMDSEntity_Last; + } + + if ( !isKoType ) + { + for ( int t = type; t < typeEnd; ++t ) + if ( nbElemsInSubMesh == meshInfo->NbEntities( SMDSAbs_EntityType( t ))) + return SMDSAbs_EntityType( t ); + } + isKoType = true; + return SMDSAbs_EntityType( type ); +} + +//================================================================================ +/*! + * \brief Saves SMESH_PreMeshInfo to the study file + */ +//================================================================================ + +void SMESH_PreMeshInfo::SaveToFile( SMESH_Mesh_i* mesh, + const int meshID, + HDFfile* hdfFile) +{ + // create a HDF group for SMESH_PreMeshInfo of this mesh + SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << meshID; + HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, hdfFile ); + infoHdfGroup->CreateOnDisk(); + + PreMeshInfo_TRY; + + // info of mesh + meshInfo2hdf( mesh->GetMeshInfo(), "Mesh", infoHdfGroup ); + + // info of groups + SMESH_PreMeshInfo incompleteInfo( 0,0,"",""); + incompleteInfo.setNb( SMDSEntity_Node, GroupOnFilter_OutOfDate ); + SMESHDS_Mesh* meshDS = mesh->GetImpl().GetMeshDS(); + + map::const_iterator i2group = mesh->_mapGroups.begin(); + for ( ; i2group != mesh->_mapGroups.end(); ++i2group ) + { + if ( SMESH_GroupBase_i* group_i = SMESH::DownCast( i2group->second )) + { + SMESHDS_GroupBase * group = group_i->GetGroupDS(); + if ( SMESHDS_GroupOnFilter* gof = dynamic_cast(group)) + { + // prevent too long storage time due to applying filter to many elements + if ( !gof->IsUpToDate() && meshDS->GetMeshInfo().NbElements( gof->GetType() ) > 1e5 ) + { + meshInfo2hdf( incompleteInfo.GetMeshInfo(), + group->GetStoreName(), + infoHdfGroup); + continue; + } + } + meshInfo2hdf( group_i->GetMeshInfo(), group->GetStoreName(), infoHdfGroup); + } + } + + // info of sub-meshes + map::iterator id2sm = mesh->_mapSubMeshIor.begin(); + for ( ; id2sm != mesh->_mapSubMeshIor.end(); ++id2sm ) + { + if ( SMESH_subMesh_i* sm = SMESH::DownCast( id2sm->second )) + { + meshInfo2hdf( sm->GetMeshInfo(), + SMESH_Comment( sm->GetId() ), + infoHdfGroup); + } + } + + PreMeshInfo_CATCH; + + infoHdfGroup->CloseOnDisk(); +} + +//================================================================================ +/*! + * \brief Reads all data and remove all SMESH_PreMeshInfo fields from objects + */ +//================================================================================ + +void SMESH_PreMeshInfo::FullLoadFromFile() const +{ + SignalToGUI signalOnLoading( _mesh ); + + SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo(); + _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info + + ::SMESH_Mesh& mesh = _mesh->GetImpl(); + SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); + + PreMeshInfo_TRY; + + MYDEBUGOUT( "BEG FullLoadFromFile() " << _meshID ); + + // load mesh + DriverMED_R_SMESHDS_Mesh myReader; + myReader.SetFile( _medFileName.c_str() ); + myReader.SetMesh( meshDS ); + myReader.SetMeshId( _meshID ); + myReader.Perform(); + + // load groups + const set& groups = meshDS->GetGroups(); + set::const_iterator groupIt = groups.begin(); + for ( ; groupIt != groups.end(); ++groupIt ) + if ( SMESHDS_Group* aGrp = dynamic_cast( *groupIt )) + myReader.GetGroup( aGrp ); + + // load sub-meshes + readSubMeshes( &myReader ); + + PreMeshInfo_CATCH; + + _mesh->changePreMeshInfo() = meshInfo; + + ForgetAllData(); + + signalOnLoading.sendStop(); + + meshDS->Modified(); + + // load dependent meshes referring/referred via hypotheses + mesh.GetSubMesh( mesh.GetShapeToMesh() )-> + ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED); + + MYDEBUGOUT( "END FullLoadFromFile()" ); +} + +//================================================================================ +/*! + * \brief Reads full data of sub-meshes + */ +//================================================================================ + +void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const +{ + HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() ); + aFile->OpenOnDisk( HDF_RDONLY ); + + char meshGrpName[ 30 ]; + sprintf( meshGrpName, "Mesh %d", _meshID ); + if ( aFile->ExistInternalObject( meshGrpName ) ) + { + HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile ); + aTopGroup->OpenOnDisk(); + + SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS(); + + bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" )); + if ( submeshesInFamilies ) // from MED + { + // old way working before fix of PAL 12992 + reader->CreateAllSubMeshes(); + } + else + { + // open a group + HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup ); + aGroup->OpenOnDisk(); + + int maxID = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() ); + vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 ); + vector< TopAbs_ShapeEnum > smType ( maxID + 1, TopAbs_SHAPE ); + + PositionCreator aPositionCreator; + + SMDS_NodeIteratorPtr nIt = meshDS->nodesIterator(); + SMDS_ElemIteratorPtr eIt = meshDS->elementsIterator(); + for ( int isNode = 0; isNode < 2; ++isNode ) + { + string aDSName( isNode ? "Node Submeshes" : "Element Submeshes"); + if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() )) + { + HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup ); + aDataset->OpenOnDisk(); + // read submesh IDs for all elements sorted by ID + int nbElems = aDataset->GetSize(); + int* smIDs = new int [ nbElems ]; + aDataset->ReadFromDisk( smIDs ); + aDataset->CloseOnDisk(); + + // get elements sorted by ID + TIDSortedElemSet elemSet; + if ( isNode ) + while ( nIt->more() ) elemSet.insert( elemSet.end(), nIt->next() ); + else + while ( eIt->more() ) elemSet.insert( elemSet.end(), eIt->next() ); + //ASSERT( elemSet.size() == nbElems ); -- issue 20182 + // -- Most probably a bad study was saved when there were + // not fixed bugs in SMDS_MeshInfo + if ( elemSet.size() < nbElems ) { +#ifdef _DEBUG_ + cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl; +#endif + nbElems = elemSet.size(); + } + // add elements to submeshes + TIDSortedElemSet::iterator iE = elemSet.begin(); + for ( int i = 0; i < nbElems; ++i, ++iE ) + { + int smID = smIDs[ i ]; + if ( smID == 0 ) continue; + const SMDS_MeshElement* elem = *iE; + if ( smID > maxID ) { + // corresponding subshape no longer exists: maybe geom group has been edited + if ( _mesh->GetImpl().HasShapeToMesh() ) + meshDS->RemoveElement( elem ); + continue; + } + // get or create submesh + SMESHDS_SubMesh* & sm = subMeshes[ smID ]; + if ( ! sm ) { + sm = meshDS->NewSubMesh( smID ); + smType[ smID ] = meshDS->IndexToShape( smID ).ShapeType(); + } + // add + if ( isNode ) { + SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]); + SMDS_MeshNode* node = const_cast( static_cast( elem )); + node->SetPosition( pos ); + sm->AddNode( node ); + } else { + sm->AddElement( elem ); + } + } + delete [] smIDs; + } + } + } // end reading submeshes + + // Read node positions on sub-shapes (SMDS_Position) + + if ( aTopGroup->ExistInternalObject( "Node Positions" )) + { + // There are 5 datasets to read: + // "Nodes on Edges" - ID of node on edge + // "Edge positions" - U parameter on node on edge + // "Nodes on Faces" - ID of node on face + // "Face U positions" - U parameter of node on face + // "Face V positions" - V parameter of node on face + const char* aEid_DSName = "Nodes on Edges"; + const char* aEu_DSName = "Edge positions"; + const char* aFu_DSName = "Face U positions"; + //char* aFid_DSName = "Nodes on Faces"; + //char* aFv_DSName = "Face V positions"; + + // data to retrieve + int nbEids = 0, nbFids = 0; + int *aEids = 0, *aFids = 0; + double *aEpos = 0, *aFupos = 0, *aFvpos = 0; + + // open a group + HDFgroup* aGroup = new HDFgroup( "Node Positions", aTopGroup ); + aGroup->OpenOnDisk(); + + // loop on 5 data sets + int aNbObjects = aGroup->nInternalObjects(); + for ( int i = 0; i < aNbObjects; i++ ) + { + // identify dataset + char aDSName[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( i, aDSName ); + // read data + HDFdataset* aDataset = new HDFdataset( aDSName, aGroup ); + aDataset->OpenOnDisk(); + if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions + { + double* pos = new double [ aDataset->GetSize() ]; + aDataset->ReadFromDisk( pos ); + // which one? + if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 ) + aEpos = pos; + else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 ) + aFupos = pos; + else + aFvpos = pos; + } + else // NODE IDS + { + int aSize = aDataset->GetSize(); + + // for reading files, created from 18.07.2005 till 10.10.2005 + if (aDataset->GetType() == HDF_STRING) + aSize /= sizeof(int); + + int* ids = new int [aSize]; + aDataset->ReadFromDisk( ids ); + // on face or nodes? + if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) { + aEids = ids; + nbEids = aSize; + } + else { + aFids = ids; + nbFids = aSize; + } + } + aDataset->CloseOnDisk(); + } // loop on 5 datasets + + // Set node positions on edges or faces + for ( int onFace = 0; onFace < 2; onFace++ ) + { + int nbNodes = ( onFace ? nbFids : nbEids ); + if ( nbNodes == 0 ) continue; + int* aNodeIDs = ( onFace ? aFids : aEids ); + double* aUPos = ( onFace ? aFupos : aEpos ); + double* aVPos = ( onFace ? aFvpos : 0 ); + // loop on node IDs + for ( int iNode = 0; iNode < nbNodes; iNode++ ) + { + const SMDS_MeshNode* node = meshDS->FindNode( aNodeIDs[ iNode ]); + if ( !node ) continue; // maybe removed while Loading() if geometry changed + SMDS_PositionPtr aPos = node->GetPosition(); + ASSERT( aPos ); + if ( onFace ) { + // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182 + // -- Most probably a bad study was saved when there were + // not fixed bugs in SMDS_MeshInfo + if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) { + SMDS_FacePosition* fPos = const_cast + ( static_cast( aPos )); + fPos->SetUParameter( aUPos[ iNode ]); + fPos->SetVParameter( aVPos[ iNode ]); + } + } + else { + // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182 + if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) { + SMDS_EdgePosition* fPos = const_cast + ( static_cast( aPos )); + fPos->SetUParameter( aUPos[ iNode ]); + } + } + } + } + if ( aEids ) delete [] aEids; + if ( aFids ) delete [] aFids; + if ( aEpos ) delete [] aEpos; + if ( aFupos ) delete [] aFupos; + if ( aFvpos ) delete [] aFvpos; + + aGroup->CloseOnDisk(); + + } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) ) + + aTopGroup->CloseOnDisk(); + } // if ( aFile->ExistInternalObject( meshGrpName ) ) + + aFile->CloseOnDisk(); + delete aFile; +} + +//================================================================================ +/*! + * \brief Remove all SMESH_PreMeshInfo fields from objects w/o data loading + */ +//================================================================================ + +void SMESH_PreMeshInfo::ForgetAllData() const +{ + PreMeshInfo_TRY; + + if ( _mesh->changePreMeshInfo() != this ) + return _mesh->changePreMeshInfo()->ForgetAllData(); + + // remove SMESH_PreMeshInfo from groups + map::const_iterator i2group = _mesh->_mapGroups.begin(); + for ( ; i2group != _mesh->_mapGroups.end(); ++i2group ) + { + if ( SMESH_GroupBase_i* group_i = + SMESH::DownCast( i2group->second )) + { + SMESH_PreMeshInfo* & info = group_i->changePreMeshInfo(); + delete info; + info = NULL; + } + } + // remove SMESH_PreMeshInfo from sub-meshes + map::iterator id2sm = _mesh->_mapSubMeshIor.begin(); + for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm ) + { + if ( SMESH_subMesh_i* sm = SMESH::DownCast( id2sm->second )) + { + SMESH_PreMeshInfo* & info = sm->changePreMeshInfo(); + delete info; + info = NULL; + } + } + // remove SMESH_PreMeshInfo from the mesh + _mesh->changePreMeshInfo() = NULL; + delete this; + + PreMeshInfo_CATCH; + + + // Finalize loading + + // PreMeshInfo_TRY; + + // ::SMESH_Mesh& mesh = _mesh->GetImpl(); + + // // update hyps needing full mesh data restored (issue 20918) + // // map::iterator id2hyp= _mesh->_mapHypo.begin(); + // // for ( ; id2hyp != _mesh->_mapHypo.end(); ++id2hyp ) + // // if ( SMESH_Hypothesis_i* hyp = SMESH::DownCast( id2hyp->second )) + // // hyp->UpdateAsMeshesRestored(); + + + // PreMeshInfo_CATCH; +} + +//================================================================================ +/*! + * \brief Calls either FullLoadFromFile() or ForgetAllData() depending on preferences + */ +//================================================================================ + +void SMESH_PreMeshInfo::ForgetOrLoad() const +{ + if ( SMESH_Gen_i::GetSMESHGen()->ToForgetMeshDataOnHypModif() ) + ForgetAllData(); + else + FullLoadFromFile(); +} + +//================================================================================ +/*! + * \brief Method of SMESH_IDSource interface + */ +//================================================================================ + +SMESH::array_of_ElementType* SMESH_PreMeshInfo::GetTypes() const +{ + SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType; + + types->length( 4 ); + int nbTypes = 0; + if (NbEdges()) + types[nbTypes++] = SMESH::EDGE; + if (NbFaces()) + types[nbTypes++] = SMESH::FACE; + if (NbVolumes()) + types[nbTypes++] = SMESH::VOLUME; + if (Nb0DElements()) + types[nbTypes++] = SMESH::ELEM0D; + types->length( nbTypes ); + + return types._retn(); +} + +//================================================================================ +/*! + * \brief Method of SMESH_IDSource interface returning nb elements by element type + */ +//================================================================================ + +SMESH::long_array* SMESH_PreMeshInfo::GetMeshInfo() const +{ + SMESH::long_array_var aRes = new SMESH::long_array(); + aRes->length(SMESH::Entity_Last); + for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++) + aRes[i] = 0; + + for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++) + aRes[i] = NbEntities((SMDSAbs_EntityType)i); + return aRes._retn(); +} + +//================================================================================ +/*! + * Returns false if GetMeshInfo() returns incorrect information that may + * happen if mesh data is not yet fully loaded from the file of study. + */ +//================================================================================ + +bool SMESH_PreMeshInfo::IsMeshInfoCorrect() const +{ + return _isInfoOk; +} + +//================================================================================ +/*! + * \brief TEMPORARY method to remove study files on closing study; + * RIGHT WAY: study files are remove automatically when meshes are destroyed + */ +//================================================================================ + +void SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp) +{ + SALOMEDS::Study_var study = smeshComp->GetStudy(); + if ( theStudyIDToMeshCounter[ (int) study->StudyId() ] > 0 ) + { + SALOMEDS::ChildIterator_var itBig = study->NewChildIterator( smeshComp ); + for ( ; itBig->More(); itBig->Next() ) { + SALOMEDS::SObject_var gotBranch = itBig->Value(); + CORBA::Object_var anObject = SMESH_Gen_i::SObjectToObject( gotBranch ); + if ( SMESH_Mesh_i* mesh = SMESH::DownCast( anObject )) + { + if ( mesh->changePreMeshInfo() ) + { + mesh->changePreMeshInfo()->ForgetAllData(); + } + } + } + } +} diff --git a/src/SMESH_I/SMESH_PreMeshInfo.hxx b/src/SMESH_I/SMESH_PreMeshInfo.hxx new file mode 100644 index 000000000..5b52f157a --- /dev/null +++ b/src/SMESH_I/SMESH_PreMeshInfo.hxx @@ -0,0 +1,125 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_PreMeshInfo.hxx +// Created : Fri Feb 10 13:25:02 2012 +// Author : Edward AGAPOV (eap) + + +#ifndef __SMESH_PreMeshInfo_HXX__ +#define __SMESH_PreMeshInfo_HXX__ + +#include "SMDS_MeshInfo.hxx" + +#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include CORBA_SERVER_HEADER(SALOMEDS) + +#include + +class DriverMED_R_SMESHDS_Mesh; +class HDFfile; +class HDFgroup; +class SMESH_Mesh_i; + +/*! + * \brief Class loading and holding information of a mesh object (mesh, group, submesh) + * not yet loaded from HDF file of study. + * + * Usage scenario: + * - SMESH_PreMeshInfo::LoadFromFile() // reads info of all objects + * - if ( myPreInfo ) myPreInfo->NbElements() // access to info by objects + * - myPreInfo->FullLoadFromFile() // reads all mesh data and resets myPreInfo=NULL + */ + +class SMESH_PreMeshInfo : public SMDS_MeshInfo +{ +public: + // fills SMESH_PreMeshInfo field of all objects of mesh + static void LoadFromFile( SMESH_Mesh_i* mesh, + const int meshID, + const std::string& medFile, + const std::string& hdfFile, + const bool toRemoveFiles); + + // saves SMESH_PreMeshInfo to the study file + static void SaveToFile( SMESH_Mesh_i* mesh, + const int meshID, + HDFfile* hdfFile); + + // reads all data and remove all SMESH_PreMeshInfo fields from objects + void FullLoadFromFile() const; + + // remove all SMESH_PreMeshInfo fields from objects w/o data loading + void ForgetAllData() const; + + // calls either FullLoadFromFile() or ForgetAllData() depending on preferences; + // is called on hypothesis modification + void ForgetOrLoad() const; + + // meshods of SMESH_IDSource interface + SMESH::array_of_ElementType* GetTypes() const; + SMESH::long_array* GetMeshInfo() const; + bool IsMeshInfoCorrect() const; + + ~SMESH_PreMeshInfo(); + + // TEMPORARY method to remove study files on closing study; + // RIGHT WAY: study files are remove automatically when meshes are destroyed + static void RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp); + +private: + + // creation by LoadFromFile() only + SMESH_PreMeshInfo(SMESH_Mesh_i* mesh, + const int meshID, + const std::string& medFile, + const std::string& hdfFile); + + SMESH_PreMeshInfo* newInstance() + { return new SMESH_PreMeshInfo( _mesh,_meshID,_medFileName,_hdfFileName ); } + + // reading from the new study, for which SaveToFile() was called + bool readPreInfoFromHDF(); + void hdf2meshInfo( const std::string& dataSetName, HDFgroup* infoHdfGroup ); + + // reading from the old study, for which SaveToFile() was not called + bool readMeshInfo(); + void readGroupInfo(); + void readSubMeshInfo(); + SMDSAbs_EntityType getElemType( const TopAbs_ShapeEnum shapeType, + const int nbElemsInSubMesh, + bool& isKoType) const; + + void readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const; + + // general data + std::string _medFileName, _hdfFileName; + bool _toRemoveFiles; + int _meshID; + SMESH_Mesh_i* _mesh; + bool _isInfoOk; + + int _elemCounter; /* used as a counter while mesh info reading and + as a signal that mesh info is incorrect after reading + */ +}; + +#endif