1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SMESH_PreMeshInfo.cxx
23 // Created : Fri Feb 10 17:36:39 2012
24 // Author : Edward AGAPOV (eap)
27 #include "SMESH_PreMeshInfo.hxx"
29 #include "DriverMED.hxx"
30 #include "DriverMED_R_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_EdgePosition.hxx"
33 #include "SMDS_FacePosition.hxx"
34 #include "SMDS_SpacePosition.hxx"
35 #include "SMDS_VertexPosition.hxx"
36 #include "SMESHDS_Group.hxx"
37 #include "SMESHDS_GroupOnFilter.hxx"
38 #include "SMESHDS_Mesh.hxx"
39 #include "SMESH_Gen_i.hxx"
40 #include "SMESH_Group_i.hxx"
41 #include "SMESH_Mesh_i.hxx"
42 #include "SMESH_subMesh_i.hxx"
44 #include <HDFarray.hxx>
45 #include <HDFdataset.hxx>
46 #include <HDFfile.hxx>
47 #include <HDFgroup.hxx>
48 #include <SALOMEDS_Tool.hxx>
49 #include <SALOMEDS_wrap.hxx>
51 #include <TopoDS_Iterator.hxx>
52 #include <TopoDS_Shape.hxx>
54 #include "SMESH_TryCatch.hxx"
56 #include CORBA_SERVER_HEADER(SALOME_Session)
60 #define MYDEBUGOUT(msg) //std::cout << msg << std::endl;
64 enum { GroupOnFilter_OutOfDate = -1 };
66 // a map to count not yet loaded meshes
67 static std::map< int, int > theStudyIDToMeshCounter;
69 //================================================================================
71 * \brief Counts not fully loaded meshes
73 //================================================================================
75 void meshInfoLoaded( SMESH_Mesh_i* mesh )
77 std::map< int, int >::iterator id2counter =
78 theStudyIDToMeshCounter.insert( std::make_pair( (int) mesh->GetStudyId(), 0 )).first;
81 //================================================================================
83 * \brief Removes temporary files if none of meshes needs them
85 //================================================================================
87 void filesNoMoreNeeded(SMESH_Mesh_i* mesh,
91 if ( --theStudyIDToMeshCounter[ (int) mesh->GetStudyId() ] == 0 )
93 std::string tmpDir = SALOMEDS_Tool::GetDirFromPath( hdfFile );
95 SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames;
97 medFile = SALOMEDS_Tool::GetNameFromPath( medFile ) + ".med";
98 hdfFile = SALOMEDS_Tool::GetNameFromPath( hdfFile ) + ".hdf";
99 aFiles[0] = medFile.c_str();
100 aFiles[1] = hdfFile.c_str();
102 SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true );
106 //=============================================================================
108 * \brief Class sending signals on start and finish of loading
110 //=============================================================================
114 std::string _messagePrefix;
115 SALOME::Session_var _session;
117 SignalToGUI( SMESH_Mesh_i* mesh )
119 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
120 SALOMEDS::Study_var study = gen->GetCurrentStudy();
121 if ( !study->_is_nil() && study->StudyId() == mesh->GetStudyId() )
123 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject(study, mesh->_this() );
124 CORBA::Object_var obj = gen->GetNS()->Resolve( "/Kernel/Session" );
125 _session = SALOME::Session::_narrow( obj );
126 if ( !meshSO->_is_nil() && !_session->_is_nil() )
128 CORBA::String_var meshEntry = meshSO->GetID();
129 _messagePrefix = "SMESH/mesh_loading/";
130 _messagePrefix += meshEntry.in();
132 std::string msgToGUI = _messagePrefix + "/";
133 msgToGUI += SMESH_Comment( mesh->NbNodes() );
135 msgToGUI += SMESH_Comment( mesh->NbElements() );
137 _session->emitMessageOneWay( msgToGUI.c_str());
143 if ( !_messagePrefix.empty() )
145 std::string msgToGUI = _messagePrefix + "/stop";
146 _session->emitMessageOneWay( msgToGUI.c_str());
147 _messagePrefix.clear();
150 ~SignalToGUI() { sendStop(); }
153 //=============================================================================
155 * \brief Creates SMDS_Position according to shape type
157 //=============================================================================
159 class PositionCreator {
161 SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
162 return (this->*myFuncTable[ type ])();
165 myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition );
166 myFuncTable[ TopAbs_SOLID ] = & PositionCreator::volumePosition;
167 myFuncTable[ TopAbs_FACE ] = & PositionCreator::facePosition;
168 myFuncTable[ TopAbs_EDGE ] = & PositionCreator::edgePosition;
169 myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition;
172 SMDS_PositionPtr edgePosition() const { return SMDS_PositionPtr( new SMDS_EdgePosition ); }
173 SMDS_PositionPtr facePosition() const { return SMDS_PositionPtr( new SMDS_FacePosition ); }
174 SMDS_PositionPtr volumePosition() const { return SMDS_PositionPtr( new SMDS_SpacePosition ); }
175 SMDS_PositionPtr vertexPosition() const { return SMDS_PositionPtr( new SMDS_VertexPosition); }
176 SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition(); }
177 typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const;
178 std::vector<FmakePos> myFuncTable;
181 //================================================================================
183 * \brief Returns ids of simple shapes composing a complex one
185 //================================================================================
187 std::vector<int> getSimpleSubMeshIds( SMESHDS_Mesh* meshDS, int shapeId )
189 std::vector<int> ids;
191 std::list<TopoDS_Shape> shapeQueue( 1, meshDS->IndexToShape( shapeId ));
192 std::list<TopoDS_Shape>::iterator shape = shapeQueue.begin();
193 for ( ; shape != shapeQueue.end(); ++shape )
195 if ( shape->IsNull() ) continue;
196 if ( shape->ShapeType() == TopAbs_COMPOUND ||
197 shape->ShapeType() == TopAbs_COMPSOLID )
199 for ( TopoDS_Iterator it( *shape ); it.More(); it.Next() )
200 shapeQueue.push_back( it.Value() );
204 ids.push_back( meshDS->ShapeToIndex( *shape ));
210 //================================================================================
212 * \brief Return EEntiteMaillage by EGeometrieElement
214 //================================================================================
216 MED::EEntiteMaillage entityByGeom(const MED::EGeometrieElement geom )
218 return geom == MED::eBALL ? MED::eSTRUCT_ELEMENT : MED::eMAILLE;
221 //================================================================================
223 * \brief Return a map< EGeometrieElement, SMDSAbs_EntityType >
225 //================================================================================
227 typedef std::map< MED::EGeometrieElement, SMDSAbs_EntityType > Tmed2smeshElemTypeMap;
228 const Tmed2smeshElemTypeMap& med2smeshElemTypeMap()
230 static Tmed2smeshElemTypeMap med2smeshTypes;
231 if ( med2smeshTypes.empty() )
233 for ( int iG = 0; iG < SMDSEntity_Last; ++iG )
235 SMDSAbs_EntityType smdsType = (SMDSAbs_EntityType) iG;
236 MED::EGeometrieElement medType =
237 (MED::EGeometrieElement) DriverMED::GetMedGeoType( smdsType );
238 med2smeshTypes.insert( std::make_pair( medType, smdsType ));
241 return med2smeshTypes;
244 //================================================================================
246 * \brief Writes meshInfo into a HDF file
248 //================================================================================
250 void meshInfo2hdf( SMESH::long_array_var meshInfo,
251 const std::string& name,
254 // we use med identification of element (MED::EGeometrieElement) types
255 // but not enum SMDSAbs_EntityType because values of SMDSAbs_EntityType may
256 // change at insertion of new items in the middle.
257 //const vector<MED::EGeometrieElement>& medTypes = mesh2medElemType();
259 std::vector<int> data;
261 for ( size_t i = 0; i < meshInfo->length(); ++i )
262 if ( meshInfo[i] > 0 )
264 data.push_back( DriverMED::GetMedGeoType( SMDSAbs_EntityType( i ))); //medTypes[ i ] );
265 data.push_back( meshInfo[ i ] );
270 hdf_size datasetSize[] = { data.size() };
271 HDFarray* anArray = new HDFarray(0, HDF_INT32, 1, datasetSize);
272 anArray->CreateOnDisk();
274 HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup, HDF_ARRAY, datasetSize, 1 );
275 dataset->SetArrayId(anArray->GetId());
276 dataset->CreateOnDisk();
277 dataset->WriteOnDisk( & data[0] );
278 dataset->CloseOnDisk();
279 anArray->CloseOnDisk();
284 //================================================================================
286 * \brief Reads meshInfo from a HDF file
288 //================================================================================
290 void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name,
292 const TColStd_MapOfAsciiString& allHdfNames)
294 //if ( hdfGroup->ExistInternalObject( name.c_str()) ) PAL23514
295 if ( allHdfNames.Contains( name.c_str() ))
297 HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup );
298 dataset->OpenOnDisk();
300 // // hdf_size datasetSize[ 1 ];
301 // // HDFarray *array = new HDFarray(dataset);
302 // // array->GetDim( datasetSize );
303 // int size = dataset->GetSize();
305 std::vector<int> info( SMDSEntity_Last * 2, 0 );
306 dataset->ReadFromDisk( &info[0] );
307 dataset->CloseOnDisk();
309 const Tmed2smeshElemTypeMap& med2smesh = med2smeshElemTypeMap();
310 Tmed2smeshElemTypeMap::const_iterator me2sme, me2smeEnd = med2smesh.end();
311 for ( size_t i = 0; i < info.size(); )
313 int medType = info[i++];
314 int nbElems = info[i++];
315 if ( !nbElems ) break;
316 me2sme = med2smesh.find( (MED::EGeometrieElement) medType );
317 if ( me2sme != me2smeEnd )
318 setNb( me2sme->second, nbElems );
323 if ( NbNodes() == GroupOnFilter_OutOfDate ) // case of !SMESHDS_GroupOnFilter::IsUpToDate()
326 setNb( SMDSEntity_Node, 0 );
330 //================================================================================
332 * \brief Constructor callable by SMESH_PreMeshInfo only
334 //================================================================================
336 SMESH_PreMeshInfo::SMESH_PreMeshInfo(SMESH_Mesh_i* mesh,
338 const std::string& medFile,
339 const std::string& hdfFile)
340 : _medFileName( medFile ),
341 _hdfFileName( hdfFile ),
342 _toRemoveFiles( false ),
350 //================================================================================
352 * \brief Release temporary files
354 //================================================================================
356 SMESH_PreMeshInfo::~SMESH_PreMeshInfo()
358 if ( _toRemoveFiles ) // it can be true only for SMESH_PreMeshInfo of the mesh
359 filesNoMoreNeeded( _mesh, _medFileName, _hdfFileName );
361 _toRemoveFiles = false;
364 //================================================================================
366 * \brief fills SMESH_PreMeshInfo field of all objects of mesh
368 //================================================================================
370 void SMESH_PreMeshInfo::LoadFromFile( SMESH_Mesh_i* mesh,
372 const std::string& medFile,
373 const std::string& hdfFile,
374 const bool toRemoveFiles)
378 SMESH_PreMeshInfo* meshPreInfo = new SMESH_PreMeshInfo( mesh,meshID,medFile,hdfFile );
379 mesh->changePreMeshInfo() = meshPreInfo;
381 meshPreInfo->_toRemoveFiles = toRemoveFiles;
383 meshInfoLoaded( mesh );
385 if ( meshPreInfo->readPreInfoFromHDF() )
386 // all SMESH_PreMeshInfo's are stored in HDF file (written after
387 // implementing SMESH_PreMeshInfo)
390 // try to read SMESH_PreMeshInfo from med file (as study is older than SMESH_PreMeshInfo)
391 if ( meshPreInfo->readMeshInfo() )
393 meshPreInfo->readGroupInfo();
394 meshPreInfo->readSubMeshInfo();
398 meshPreInfo->FullLoadFromFile();
400 SMESH_CATCH( SMESH::doNothing );
403 //================================================================================
405 * \brief Tries to read all SMESH_PreMeshInfo from a HDF file
406 * \retval bool - true if succeeded
408 * This method is symmetrical to SaveToFile()
410 //================================================================================
412 bool SMESH_PreMeshInfo::readPreInfoFromHDF()
414 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
415 aFile->OpenOnDisk( HDF_RDONLY );
417 SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << _meshID;
418 const bool infoAvailable = aFile->ExistInternalObject( hdfGroupName );
421 HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile );
422 infoHdfGroup->OpenOnDisk();
424 // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
425 // within aGroup->ExistInternalObject( name )
426 TColStd_MapOfAsciiString mapOfNames;
428 std::vector< std::string > subNames;
429 infoHdfGroup->GetAllObjects( subNames );
430 for ( size_t iN = 0; iN < subNames.size(); ++iN )
431 mapOfNames.Add( subNames[ iN ].c_str() );
434 _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup, mapOfNames );
436 // read SMESH_PreMeshInfo of groups
437 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
438 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
440 if ( SMESH_GroupBase_i* group_i =
441 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
443 group_i->changePreMeshInfo() = newInstance();
444 if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() )
446 const std::string name = group->GetStoreName();
447 group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup, mapOfNames );
452 // read SMESH_PreMeshInfo of sub-meshes
453 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
454 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
456 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
458 sm->changePreMeshInfo() = newInstance();
459 sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()),
466 aFile->CloseOnDisk();
469 return infoAvailable;
472 //================================================================================
474 * \brief Reads mesh info of mesh from the med file
476 //================================================================================
478 bool SMESH_PreMeshInfo::readMeshInfo()
482 MED::PWrapper aMed = MED::CrWrapper(_medFileName,true);
483 // if ( aMed->GetVersion() != MED::eV2_2 )
486 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
489 int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo ));
492 setNb( SMDSEntity_Node, nbNodes);
494 // read nb of elements
495 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
496 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
497 for ( ; me2sme != me2smeEnd; ++me2sme )
499 int nbElems = aMed->GetNbCells( medMeshInfo, entityByGeom(me2sme->first), me2sme->first );
501 setNb( me2sme->second, nbElems );
507 //================================================================================
509 * \brief Reads info of groups from the med file
511 //================================================================================
513 void SMESH_PreMeshInfo::readGroupInfo()
515 if ( _mesh->_mapGroups.empty() ) return;
517 // make SMESH_PreMeshInfo of groups
518 map< std::string, SMESH_PreMeshInfo* > name2GroupInfo;
519 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
520 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
522 if ( SMESH_GroupBase_i* group_i =
523 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
525 SMESH_PreMeshInfo* info = newInstance();
526 group_i->changePreMeshInfo() = info;
527 if ( SMESHDS_Group* group = dynamic_cast< SMESHDS_Group* >( group_i->GetGroupDS() ))
529 std::string name = group->GetStoreName();
530 name2GroupInfo.insert( std::make_pair( name, info ));
531 info->_isInfoOk = true;
536 map< int, vector< SMESH_PreMeshInfo* > > famId2grInfo;
538 MED::PWrapper aMed = MED::CrWrapper(_medFileName,false);
539 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
541 // read families to fill in famId2grInfo
542 int nbFams = aMed->GetNbFamilies( medMeshInfo );
543 if ( nbFams <= 1 ) return; // zero family is always present
544 for ( int iF = 0; iF <= nbFams; ++iF )
546 int nbGroups = aMed->GetNbFamGroup( iF, medMeshInfo );
547 if ( nbGroups < 1 ) continue;
548 MED::PFamilyInfo medFamInfo = aMed->CrFamilyInfo( medMeshInfo, nbGroups, nbGroups );
549 aMed->GetFamilyInfo( iF, medFamInfo ); // read groups of a family
550 vector< SMESH_PreMeshInfo* >& grInfoVec = famId2grInfo[ medFamInfo->GetId() ];
551 for ( int iG = 0; iG < nbGroups; ++iG )
553 const std::string grName = medFamInfo->GetGroupName( iG );
554 map< std::string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.find( grName );
555 if ( n2i != name2GroupInfo.end() )
556 grInfoVec.push_back( n2i->second );
560 // read family numbers of elements
561 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
562 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
563 MED::PElemInfo medElemInfo = aMed->CrElemInfo( medMeshInfo, 0 );
564 MED::TIntVector& famNums = medElemInfo->myFamNum;
565 for ( ; me2sme != me2smeEnd; ++me2sme ) // loop on elem types
567 famNums.resize( NbEntities( me2sme->second ));
568 if ( famNums.empty() ) continue;
569 aMed->GetFamilies( medElemInfo, famNums.size(), entityByGeom(me2sme->first), me2sme->first );
570 // distribute elements of a type among groups
571 map< int, vector< SMESH_PreMeshInfo* > >::iterator f2infos = famId2grInfo.begin();
572 for ( size_t i = 0; i < famNums.size(); ++i )
574 if ( famNums[i] != f2infos->first )
576 f2infos = famId2grInfo.find( famNums[i] );
577 if ( f2infos == famId2grInfo.end() )
578 f2infos = famId2grInfo.insert
579 ( std::make_pair( famNums[i], vector< SMESH_PreMeshInfo*>())).first;
581 vector< SMESH_PreMeshInfo* >& infoVec = f2infos->second ;
582 for ( size_t j = 0; j < infoVec.size(); ++j )
583 infoVec[j]->_elemCounter++;
585 // pass _elemCounter to a real elem type
586 map< std::string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.begin();
587 for ( ; n2i != name2GroupInfo.end(); ++n2i )
589 SMESH_PreMeshInfo* info = n2i->second;
590 info->setNb( me2sme->second, info->_elemCounter );
591 info->_elemCounter = 0;
596 //================================================================================
598 * \brief Reads info of sub-meshes from hdf file of old study
600 //================================================================================
602 void SMESH_PreMeshInfo::readSubMeshInfo()
604 if ( _mesh->_mapSubMeshIor.empty() ) return;
606 // create SMESH_PreMeshInfo of sub-meshes
607 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
608 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
610 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
612 sm->changePreMeshInfo() = newInstance();
613 sm->changePreMeshInfo()->_isInfoOk = true;
618 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
619 aFile->OpenOnDisk( HDF_RDONLY );
621 char meshGrpName[ 30 ];
622 sprintf( meshGrpName, "Mesh %d", _meshID );
623 if ( aFile->ExistInternalObject( meshGrpName ) )
625 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
626 aTopGroup->OpenOnDisk();
627 if ( aTopGroup->ExistInternalObject( "Submeshes" ))
629 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
630 aGroup->OpenOnDisk();
632 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
633 int maxSmId = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
635 for ( int isNode = 0; isNode < 2; ++isNode )
637 std::string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
638 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
640 // read sub-mesh id of all nodes or elems
641 HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
642 aDataset->OpenOnDisk();
643 int nbElems = aDataset->GetSize();
644 int* smIDs = new int [ nbElems ];
645 aDataset->ReadFromDisk( smIDs );
646 aDataset->CloseOnDisk();
647 // count nb elems in each sub-mesh
648 vector<int> nbBySubmeshId( maxSmId + 1, 0 );
649 for ( int i = 0; i < nbElems; ++i )
651 const int smID = smIDs[ i ];
652 if ( smID < (int) nbBySubmeshId.size() )
653 nbBySubmeshId[ smID ]++;
657 // store nb elems in SMESH_PreMeshInfo of sub-meshes
658 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
659 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
661 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
663 SMESH_PreMeshInfo* & info = sm->changePreMeshInfo();
665 vector<int> smIds = getSimpleSubMeshIds( meshDS, id2sm->first );
666 for ( size_t i = 0; i < smIds.size(); ++i )
667 info->_elemCounter += nbBySubmeshId[ smIds[i] ];
669 SMDSAbs_EntityType elemType;
672 elemType = SMDSEntity_Node;
676 bool koElemType = false;
677 const TopoDS_Shape& shape = meshDS->IndexToShape( smIds[0] );
678 elemType = getElemType( shape.ShapeType(), info->_elemCounter, koElemType );
679 info->_isInfoOk = !koElemType;
681 info->setNb( elemType, info->_elemCounter );
684 } // if ( aGroup->ExistInternalObject( aDSName ))
685 } // for ( int isNode = 0; isNode < 2; ++isNode )
687 aGroup->CloseOnDisk();
688 } // if ( aTopGroup->ExistInternalObject( "Submeshes" ))
690 aTopGroup->CloseOnDisk();
691 } // if ( aFile->ExistInternalObject( meshGrpName ) )
693 aFile->CloseOnDisk();
697 //================================================================================
699 * \brief Return type of element for sub-mesh on a shape of given type
701 //================================================================================
703 SMDSAbs_EntityType SMESH_PreMeshInfo::getElemType( const TopAbs_ShapeEnum shapeType,
704 const int nbElemsInSubMesh,
705 bool& isKoType) const
709 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
714 type = SMDSEntity_Tetra;
715 typeEnd = SMDSEntity_Last;
716 isKoType = ( meshInfo->NbVolumes() != nbElemsInSubMesh );
720 type = SMDSEntity_Triangle;
721 typeEnd = SMDSEntity_Tetra;
722 isKoType = ( meshInfo->NbFaces() != nbElemsInSubMesh );
725 case TopAbs_EDGE: return SMDSEntity_Edge;
726 case TopAbs_VERTEX: return SMDSEntity_0D;
727 default: return SMDSEntity_Last;
732 for ( int t = type; t < typeEnd; ++t )
733 if ( nbElemsInSubMesh == meshInfo->NbEntities( SMDSAbs_EntityType( t )))
734 return SMDSAbs_EntityType( t );
737 return SMDSAbs_EntityType( type );
740 //================================================================================
742 * \brief Saves SMESH_PreMeshInfo to the study file
744 //================================================================================
746 void SMESH_PreMeshInfo::SaveToFile( SMESH_Mesh_i* mesh,
750 // create a HDF group for SMESH_PreMeshInfo of this mesh
751 SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << meshID;
752 HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, hdfFile );
753 infoHdfGroup->CreateOnDisk();
758 meshInfo2hdf( mesh->GetMeshInfo(), "Mesh", infoHdfGroup );
761 SMESH_PreMeshInfo incompleteInfo( 0,0,"","");
762 incompleteInfo.setNb( SMDSEntity_Node, GroupOnFilter_OutOfDate );
763 SMESHDS_Mesh* meshDS = mesh->GetImpl().GetMeshDS();
765 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = mesh->_mapGroups.begin();
766 for ( ; i2group != mesh->_mapGroups.end(); ++i2group )
768 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
770 SMESHDS_GroupBase * group = group_i->GetGroupDS();
771 if ( SMESHDS_GroupOnFilter* gof = dynamic_cast<SMESHDS_GroupOnFilter*>(group))
773 // prevent too long storage time due to applying filter to many elements
774 if ( !gof->IsUpToDate() && meshDS->GetMeshInfo().NbElements( gof->GetType() ) > 1e5 )
776 meshInfo2hdf( incompleteInfo.GetMeshInfo(),
777 group->GetStoreName(),
782 meshInfo2hdf( group_i->GetMeshInfo(), group->GetStoreName(), infoHdfGroup);
786 // info of sub-meshes
787 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = mesh->_mapSubMeshIor.begin();
788 for ( ; id2sm != mesh->_mapSubMeshIor.end(); ++id2sm )
790 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
792 meshInfo2hdf( sm->GetMeshInfo(),
793 SMESH_Comment( sm->GetId() ),
798 SMESH_CATCH( SMESH::doNothing );
800 infoHdfGroup->CloseOnDisk();
803 //================================================================================
805 * \brief Reads all data and remove all SMESH_PreMeshInfo fields from objects
807 //================================================================================
809 void SMESH_PreMeshInfo::FullLoadFromFile() const
811 SignalToGUI signalOnLoading( _mesh );
813 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
814 _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info
816 ::SMESH_Mesh& mesh = _mesh->GetImpl();
817 SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
821 MYDEBUGOUT( "BEG FullLoadFromFile() " << _meshID );
824 DriverMED_R_SMESHDS_Mesh myReader;
825 myReader.SetFile( _medFileName.c_str() );
826 myReader.SetMesh( meshDS );
827 myReader.SetMeshId( _meshID );
831 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
832 set<SMESHDS_GroupBase*>::const_iterator groupIt = groups.begin();
833 for ( ; groupIt != groups.end(); ++groupIt )
834 if ( SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( *groupIt ))
835 myReader.GetGroup( aGrp );
838 readSubMeshes( &myReader );
840 SMESH_CATCH( SMESH::doNothing );
842 _mesh->changePreMeshInfo() = meshInfo;
846 signalOnLoading.sendStop();
850 // load dependent meshes referring/referred via hypotheses
851 mesh.GetSubMesh( mesh.GetShapeToMesh() )->
852 ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED);
854 MYDEBUGOUT( "END FullLoadFromFile()" );
857 //================================================================================
859 * \brief Reads full data of sub-meshes
861 //================================================================================
863 void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const
865 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
866 aFile->OpenOnDisk( HDF_RDONLY );
868 char meshGrpName[ 30 ];
869 sprintf( meshGrpName, "Mesh %d", _meshID );
870 if ( aFile->ExistInternalObject( meshGrpName ) )
872 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
873 aTopGroup->OpenOnDisk();
875 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
877 // issue 0020693. Restore _isModified flag
878 if ( aTopGroup->ExistInternalObject( "_isModified" ))
880 HDFdataset* aDataset = new HDFdataset( "_isModified", aTopGroup );
881 aDataset->OpenOnDisk();
882 hdf_size size = aDataset->GetSize();
883 int* isModified = new int[ size ];
884 aDataset->ReadFromDisk( isModified );
885 aDataset->CloseOnDisk();
886 _mesh->GetImpl().SetIsModified( bool(*isModified));
887 delete [] isModified;
890 bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
891 if ( submeshesInFamilies ) // from MED
893 // old way working before fix of PAL 12992
894 reader->CreateAllSubMeshes();
899 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
900 aGroup->OpenOnDisk();
902 int maxID = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
903 vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 );
904 vector< TopAbs_ShapeEnum > smType ( maxID + 1, TopAbs_SHAPE );
906 PositionCreator aPositionCreator;
908 SMDS_NodeIteratorPtr nIt = meshDS->nodesIterator();
909 SMDS_ElemIteratorPtr eIt = meshDS->elementsIterator();
910 for ( int isNode = 0; isNode < 2; ++isNode )
912 std::string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
913 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
915 HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
916 aDataset->OpenOnDisk();
917 // read submesh IDs for all elements sorted by ID
918 size_t nbElems = aDataset->GetSize();
919 int* smIDs = new int [ nbElems ];
920 aDataset->ReadFromDisk( smIDs );
921 aDataset->CloseOnDisk();
923 // get elements sorted by ID
924 TIDSortedElemSet elemSet;
926 while ( nIt->more() ) elemSet.insert( elemSet.end(), nIt->next() );
928 while ( eIt->more() ) elemSet.insert( elemSet.end(), eIt->next() );
929 //ASSERT( elemSet.size() == nbElems ); -- issue 20182
930 // -- Most probably a bad study was saved when there were
931 // not fixed bugs in SMDS_MeshInfo
932 if ( elemSet.size() < nbElems ) {
934 cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
936 nbElems = elemSet.size();
938 // add elements to sub-meshes
939 TIDSortedElemSet::iterator iE = elemSet.begin();
940 for ( size_t i = 0; i < nbElems; ++i, ++iE )
942 int smID = smIDs[ i ];
943 if ( smID == 0 ) continue;
944 const SMDS_MeshElement* elem = *iE;
945 if ( smID > maxID ) {
946 // corresponding subshape no longer exists: maybe geom group has been edited
947 if ( _mesh->GetImpl().HasShapeToMesh() )
948 meshDS->RemoveElement( elem );
951 // get or create submesh
952 SMESHDS_SubMesh* & sm = subMeshes[ smID ];
954 sm = meshDS->NewSubMesh( smID );
955 smType[ smID ] = meshDS->IndexToShape( smID ).ShapeType();
959 SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]);
960 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( static_cast<const SMDS_MeshNode*>( elem ));
961 node->SetPosition( pos );
964 sm->AddElement( elem );
970 } // end reading submeshes
972 // Read node positions on sub-shapes (SMDS_Position)
974 if ( aTopGroup->ExistInternalObject( "Node Positions" ))
976 // There are 5 datasets to read:
977 // "Nodes on Edges" - ID of node on edge
978 // "Edge positions" - U parameter on node on edge
979 // "Nodes on Faces" - ID of node on face
980 // "Face U positions" - U parameter of node on face
981 // "Face V positions" - V parameter of node on face
982 const char* aEid_DSName = "Nodes on Edges";
983 const char* aEu_DSName = "Edge positions";
984 const char* aFu_DSName = "Face U positions";
985 //char* aFid_DSName = "Nodes on Faces";
986 //char* aFv_DSName = "Face V positions";
989 int nbEids = 0, nbFids = 0;
990 int *aEids = 0, *aFids = 0;
991 double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
994 HDFgroup* aGroup = new HDFgroup( "Node Positions", aTopGroup );
995 aGroup->OpenOnDisk();
997 // loop on 5 data sets
998 int aNbObjects = aGroup->nInternalObjects();
999 for ( int i = 0; i < aNbObjects; i++ )
1002 char aDSName[ HDF_NAME_MAX_LEN+1 ];
1003 aGroup->InternalObjectIndentify( i, aDSName );
1005 HDFdataset* aDataset = new HDFdataset( aDSName, aGroup );
1006 aDataset->OpenOnDisk();
1007 if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
1009 double* pos = new double [ aDataset->GetSize() ];
1010 aDataset->ReadFromDisk( pos );
1012 if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
1014 else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
1021 int aSize = aDataset->GetSize();
1023 // for reading files, created from 18.07.2005 till 10.10.2005
1024 if (aDataset->GetType() == HDF_STRING)
1025 aSize /= sizeof(int);
1027 int* ids = new int [aSize];
1028 aDataset->ReadFromDisk( ids );
1029 // on face or nodes?
1030 if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
1039 aDataset->CloseOnDisk();
1040 } // loop on 5 datasets
1042 // Set node positions on edges or faces
1043 for ( int onFace = 0; onFace < 2; onFace++ )
1045 int nbNodes = ( onFace ? nbFids : nbEids );
1046 if ( nbNodes == 0 ) continue;
1047 int* aNodeIDs = ( onFace ? aFids : aEids );
1048 double* aUPos = ( onFace ? aFupos : aEpos );
1049 double* aVPos = ( onFace ? aFvpos : 0 );
1051 for ( int iNode = 0; iNode < nbNodes; iNode++ )
1053 const SMDS_MeshNode* node = meshDS->FindNode( aNodeIDs[ iNode ]);
1054 if ( !node ) continue; // maybe removed while Loading() if geometry changed
1055 SMDS_PositionPtr aPos = node->GetPosition();
1058 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182
1059 // -- Most probably a bad study was saved when there were
1060 // not fixed bugs in SMDS_MeshInfo
1061 if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
1062 SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
1063 ( static_cast<const SMDS_FacePosition*>( aPos ));
1064 fPos->SetUParameter( aUPos[ iNode ]);
1065 fPos->SetVParameter( aVPos[ iNode ]);
1069 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182
1070 if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) {
1071 SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
1072 ( static_cast<const SMDS_EdgePosition*>( aPos ));
1073 fPos->SetUParameter( aUPos[ iNode ]);
1078 if ( aEids ) delete [] aEids;
1079 if ( aFids ) delete [] aFids;
1080 if ( aEpos ) delete [] aEpos;
1081 if ( aFupos ) delete [] aFupos;
1082 if ( aFvpos ) delete [] aFvpos;
1084 aGroup->CloseOnDisk();
1086 } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
1088 aTopGroup->CloseOnDisk();
1089 } // if ( aFile->ExistInternalObject( meshGrpName ) )
1091 aFile->CloseOnDisk();
1095 //================================================================================
1097 * \brief Remove all SMESH_PreMeshInfo fields from objects w/o data loading
1099 //================================================================================
1101 void SMESH_PreMeshInfo::ForgetAllData() const
1105 if ( _mesh->changePreMeshInfo() != this )
1106 return _mesh->changePreMeshInfo()->ForgetAllData();
1108 // remove SMESH_PreMeshInfo from groups
1109 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
1110 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
1112 if ( SMESH_GroupBase_i* group_i =
1113 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
1115 SMESH_PreMeshInfo* & info = group_i->changePreMeshInfo();
1120 // remove SMESH_PreMeshInfo from sub-meshes
1121 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
1122 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
1124 if ( SMESH_subMesh_i* sm_i = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
1126 SMESH_PreMeshInfo* & info = sm_i->changePreMeshInfo();
1131 // remove SMESH_PreMeshInfo from the mesh
1132 _mesh->changePreMeshInfo() = NULL;
1135 SMESH_CATCH( SMESH::doNothing );
1142 // ::SMESH_Mesh& mesh = _mesh->GetImpl();
1144 // // update hyps needing full mesh data restored (issue 20918)
1145 // // map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id2hyp= _mesh->_mapHypo.begin();
1146 // // for ( ; id2hyp != _mesh->_mapHypo.end(); ++id2hyp )
1147 // // if ( SMESH_Hypothesis_i* hyp = SMESH::DownCast<SMESH_Hypothesis_i*>( id2hyp->second ))
1148 // // hyp->UpdateAsMeshesRestored();
1151 // SMESH_CATCH( SMESH::doNothing );
1154 //================================================================================
1156 * \brief remove all SMESH_PreMeshInfo fields from mesh and its child objects w/o data loading
1158 //================================================================================
1160 void SMESH_PreMeshInfo::ForgetAllData( SMESH_Mesh_i* mesh )
1162 if ( mesh && mesh->changePreMeshInfo() )
1163 mesh->changePreMeshInfo()->ForgetAllData();
1166 //================================================================================
1168 * \brief Calls either FullLoadFromFile() or ForgetAllData() depending on preferences
1170 //================================================================================
1172 void SMESH_PreMeshInfo::ForgetOrLoad() const
1174 if ( SMESH_Gen_i::GetSMESHGen()->ToForgetMeshDataOnHypModif() &&
1175 _mesh->HasShapeToMesh())
1181 //================================================================================
1183 * \brief Method of SMESH_IDSource interface
1185 //================================================================================
1187 SMESH::array_of_ElementType* SMESH_PreMeshInfo::GetTypes() const
1189 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
1193 if (NbEdges()) types[nbTypes++] = SMESH::EDGE;
1194 if (NbFaces()) types[nbTypes++] = SMESH::FACE;
1195 if (NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
1196 if (Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
1197 if (NbBalls()) types[nbTypes++] = SMESH::BALL;
1198 types->length( nbTypes );
1200 return types._retn();
1203 //================================================================================
1205 * \brief Method of SMESH_IDSource interface returning nb elements by element type
1207 //================================================================================
1209 SMESH::long_array* SMESH_PreMeshInfo::GetMeshInfo() const
1211 SMESH::long_array_var aRes = new SMESH::long_array();
1212 aRes->length(SMESH::Entity_Last);
1213 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1216 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1217 aRes[i] = NbEntities((SMDSAbs_EntityType)i);
1218 return aRes._retn();
1221 //================================================================================
1223 * Returns false if GetMeshInfo() returns incorrect information that may
1224 * happen if mesh data is not yet fully loaded from the file of study.
1226 //================================================================================
1228 bool SMESH_PreMeshInfo::IsMeshInfoCorrect() const
1233 //================================================================================
1235 * \brief TEMPORARY method to remove study files on closing study;
1236 * RIGHT WAY: study files are remove automatically when meshes are destroyed
1238 //================================================================================
1240 void SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp)
1242 SALOMEDS::Study_var study = smeshComp->GetStudy();
1243 if ( theStudyIDToMeshCounter[ (int) study->StudyId() ] > 0 )
1245 SALOMEDS::ChildIterator_wrap itBig = study->NewChildIterator( smeshComp );
1246 for ( ; itBig->More(); itBig->Next() ) {
1247 SALOMEDS::SObject_wrap gotBranch = itBig->Value();
1248 CORBA::Object_var anObject = SMESH_Gen_i::SObjectToObject( gotBranch );
1249 if ( SMESH_Mesh_i* mesh = SMESH::DownCast<SMESH_Mesh_i*>( anObject ))
1251 if ( mesh->changePreMeshInfo() )
1253 mesh->changePreMeshInfo()->ForgetAllData();