1 // Copyright (C) 2007-2012 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.
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_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"
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>
48 #include <Standard_ErrorHandler.hxx>
49 #include <Standard_Failure.hxx>
50 #include <TopoDS_Iterator.hxx>
51 #include <TopoDS_Shape.hxx>
53 #include CORBA_SERVER_HEADER(SALOME_Session)
55 #define MYDEBUGOUT(msg) //std::cout << msg << std::endl;
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()); \
65 catch ( const std::exception& ex) { \
66 onExceptionCaught(SMESH_Comment("Exception caught: \t")<<ex.what()); \
69 onExceptionCaught("Unknown Exception caught"); \
71 //================================================================================
75 enum { GroupOnFilter_OutOfDate = -1 };
77 // a map to count not yet loaded meshes
78 static map< int, int > theStudyIDToMeshCounter;
80 //================================================================================
82 * \brief Counts not fully loaded meshes
84 //================================================================================
86 void meshInfoLoaded( SMESH_Mesh_i* mesh )
88 map< int, int >::iterator id2counter =
89 theStudyIDToMeshCounter.insert( make_pair( (int) mesh->GetStudyId(), 0 )).first;
92 //================================================================================
94 * \brief Removes temporary files if none of meshes needs them
96 //================================================================================
98 void filesNoMoreNeeded(SMESH_Mesh_i* mesh,
102 if ( --theStudyIDToMeshCounter[ (int) mesh->GetStudyId() ] == 0 )
104 string tmpDir = SALOMEDS_Tool::GetDirFromPath( hdfFile );
106 SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames;
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();
113 SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true );
117 //================================================================================
119 * \brief Method useful only to set a breakpoint to debug in case of exception
121 //================================================================================
123 void onExceptionCaught(const string& msg)
129 //=============================================================================
131 * \brief Class sending signals on start and finish of loading
133 //=============================================================================
137 string _messagePrefix;
138 SALOME::Session_var _session;
140 SignalToGUI( SMESH_Mesh_i* mesh )
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() )
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() )
151 CORBA::String_var meshEntry = meshSO->GetID();
152 _messagePrefix = "SMESH/mesh_loading/";
153 _messagePrefix += meshEntry.in();
155 string msgToGUI = _messagePrefix + "/";
156 msgToGUI += SMESH_Comment( mesh->NbNodes() );
158 msgToGUI += SMESH_Comment( mesh->NbElements() );
160 _session->emitMessageOneWay( msgToGUI.c_str());
166 if ( !_messagePrefix.empty() )
168 string msgToGUI = _messagePrefix + "/stop";
169 _session->emitMessageOneWay( msgToGUI.c_str());
170 _messagePrefix.clear();
173 ~SignalToGUI() { sendStop(); }
176 //=============================================================================
178 * \brief Creates SMDS_Position according to shape type
180 //=============================================================================
182 class PositionCreator {
184 SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
185 return (this->*myFuncTable[ type ])();
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;
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;
204 //================================================================================
206 * \brief Returns ids of simple shapes composing a complex one
208 //================================================================================
210 vector<int> getSimpleSubMeshIds( SMESHDS_Mesh* meshDS, int shapeId )
214 list<TopoDS_Shape> shapeQueue( 1, meshDS->IndexToShape( shapeId ));
215 list<TopoDS_Shape>::iterator shape = shapeQueue.begin();
216 for ( ; shape != shapeQueue.end(); ++shape )
218 if ( shape->IsNull() ) continue;
219 if ( shape->ShapeType() == TopAbs_COMPOUND ||
220 shape->ShapeType() == TopAbs_COMPSOLID )
222 for ( TopoDS_Iterator it( *shape ); it.More(); it.Next() )
223 shapeQueue.push_back( it.Value() );
227 ids.push_back( meshDS->ShapeToIndex( *shape ));
233 //================================================================================
235 * \brief Return EEntiteMaillage by EGeometrieElement
237 //================================================================================
239 MED::EEntiteMaillage entityByGeom(const MED::EGeometrieElement geom )
241 return geom == MED::eBALL ? MED::eSTRUCT_ELEMENT : MED::eMAILLE;
244 //================================================================================
246 * \brief Return a map< EGeometrieElement, SMDSAbs_EntityType >
248 //================================================================================
250 typedef map< MED::EGeometrieElement, SMDSAbs_EntityType > Tmed2smeshElemTypeMap;
251 const Tmed2smeshElemTypeMap& med2smeshElemTypeMap()
253 static map< MED::EGeometrieElement, SMDSAbs_EntityType> med2smeshTypes;
254 if ( med2smeshTypes.empty() )
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 ;
279 return med2smeshTypes;
282 //================================================================================
284 * \brief Return a vector<MED::EGeometrieElement> intended to retrieve
285 * MED::EGeometrieElement by SMDSAbs_EntityType
287 //================================================================================
289 const vector<MED::EGeometrieElement>& mesh2medElemType()
291 static vector<MED::EGeometrieElement> mesh2medElemTypes;
292 if ( mesh2medElemTypes.empty() )
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;
300 return mesh2medElemTypes;
303 //================================================================================
305 * \brief Writes meshInfo into a HDF file
307 //================================================================================
309 void meshInfo2hdf( SMESH::long_array_var meshInfo,
310 const std::string& name,
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();
320 for ( size_t i = 0; i < meshInfo->length(); ++i )
321 if ( meshInfo[i] > 0 )
323 data.push_back( medTypes[ i ] );
324 data.push_back( meshInfo[ i ] );
329 hdf_size datasetSize[] = { data.size() };
330 HDFarray* anArray = new HDFarray(0, HDF_INT32, 1, datasetSize);
331 anArray->CreateOnDisk();
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();
343 //================================================================================
345 * \brief Reads meshInfo from a HDF file
347 //================================================================================
349 void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name,
352 if ( hdfGroup->ExistInternalObject( name.c_str()) )
354 HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup );
355 dataset->OpenOnDisk();
357 // // hdf_size datasetSize[ 1 ];
358 // // HDFarray *array = new HDFarray(dataset);
359 // // array->GetDim( datasetSize );
360 // int size = dataset->GetSize();
362 vector<int> info( SMDSEntity_Last * 2, 0 );
363 dataset->ReadFromDisk( &info[0] );
364 dataset->CloseOnDisk();
366 const Tmed2smeshElemTypeMap& med2smesh = med2smeshElemTypeMap();
367 Tmed2smeshElemTypeMap::const_iterator me2sme, me2smeEnd = med2smesh.end();
368 for ( size_t i = 0; i < info.size(); )
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 );
380 if ( NbNodes() == GroupOnFilter_OutOfDate ) // case of !SMESHDS_GroupOnFilter::IsUpToDate()
383 setNb( SMDSEntity_Node, 0 );
387 //================================================================================
389 * \brief Constructor callable by SMESH_PreMeshInfo only
391 //================================================================================
393 SMESH_PreMeshInfo::SMESH_PreMeshInfo(SMESH_Mesh_i* mesh,
395 const std::string& medFile,
396 const std::string& hdfFile)
397 : _medFileName( medFile ),
398 _hdfFileName( hdfFile ),
399 _toRemoveFiles( false ),
407 //================================================================================
409 * \brief Release temporary files
411 //================================================================================
413 SMESH_PreMeshInfo::~SMESH_PreMeshInfo()
415 if ( _toRemoveFiles ) // it can be true only for SMESH_PreMeshInfo of the mesh
416 filesNoMoreNeeded( _mesh, _medFileName, _hdfFileName );
418 _toRemoveFiles = false;
421 //================================================================================
423 * \brief fills SMESH_PreMeshInfo field of all objects of mesh
425 //================================================================================
427 void SMESH_PreMeshInfo::LoadFromFile( SMESH_Mesh_i* mesh,
429 const std::string& medFile,
430 const std::string& hdfFile,
431 const bool toRemoveFiles)
435 SMESH_PreMeshInfo* meshPreInfo = new SMESH_PreMeshInfo( mesh,meshID,medFile,hdfFile );
436 mesh->changePreMeshInfo() = meshPreInfo;
438 meshPreInfo->_toRemoveFiles = toRemoveFiles;
440 meshInfoLoaded( mesh );
442 if ( meshPreInfo->readPreInfoFromHDF() )
443 // all SMESH_PreMeshInfo's are stored in HDF file (written after
444 // implementing SMESH_PreMeshInfo)
447 // try to read SMESH_PreMeshInfo from med file (as study is older than SMESH_PreMeshInfo)
448 if ( meshPreInfo->readMeshInfo() )
450 meshPreInfo->readGroupInfo();
451 meshPreInfo->readSubMeshInfo();
455 meshPreInfo->FullLoadFromFile();
460 //================================================================================
462 * \brief Tries to read all SMESH_PreMeshInfo from a HDF file
463 * \retval bool - true if succeeded
465 * This method is symmetrical to SaveToFile()
467 //================================================================================
469 bool SMESH_PreMeshInfo::readPreInfoFromHDF()
471 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
472 aFile->OpenOnDisk( HDF_RDONLY );
474 SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << _meshID;
475 const bool infoAvailable = aFile->ExistInternalObject( hdfGroupName );
478 HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile );
479 infoHdfGroup->OpenOnDisk();
481 _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup );
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 )
487 if ( SMESH_GroupBase_i* group_i =
488 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
490 group_i->changePreMeshInfo() = newInstance();
491 if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() )
493 const string name = group->GetStoreName();
494 group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup );
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 )
503 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
505 sm->changePreMeshInfo() = newInstance();
506 sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()), infoHdfGroup );
511 aFile->CloseOnDisk();
514 return infoAvailable;
517 //================================================================================
519 * \brief Reads mesh info of mesh from the med file
521 //================================================================================
523 bool SMESH_PreMeshInfo::readMeshInfo()
527 MED::PWrapper aMed = MED::CrWrapper(_medFileName,true);
528 // if ( aMed->GetVersion() != MED::eV2_2 )
531 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
534 int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo ));
537 setNb( SMDSEntity_Node, nbNodes);
539 // read nb of elements
540 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
541 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
542 for ( ; me2sme != me2smeEnd; ++me2sme )
544 int nbElems = aMed->GetNbCells( medMeshInfo, entityByGeom(me2sme->first), me2sme->first );
546 setNb( me2sme->second, nbElems );
552 //================================================================================
554 * \brief Reads info of groups from the med file
556 //================================================================================
558 void SMESH_PreMeshInfo::readGroupInfo()
560 if ( _mesh->_mapGroups.empty() ) return;
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 )
567 if ( SMESH_GroupBase_i* group_i =
568 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
570 SMESH_PreMeshInfo* info = newInstance();
571 group_i->changePreMeshInfo() = info;
572 if ( SMESHDS_Group* group = dynamic_cast< SMESHDS_Group* >( group_i->GetGroupDS() ))
574 string name = group->GetStoreName();
575 name2GroupInfo.insert( make_pair( name, info ));
576 info->_isInfoOk = true;
581 map< int, vector< SMESH_PreMeshInfo* > > famId2grInfo;
583 MED::PWrapper aMed = MED::CrWrapper(_medFileName,false);
584 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
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 )
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 )
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 );
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
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 )
619 if ( famNums[i] != f2infos->first )
621 f2infos = famId2grInfo.find( famNums[i] );
622 if ( f2infos == famId2grInfo.end() )
623 f2infos = famId2grInfo.insert
624 ( make_pair( famNums[i], vector< SMESH_PreMeshInfo*>())).first;
626 vector< SMESH_PreMeshInfo* >& infoVec = f2infos->second ;
627 for ( size_t j = 0; j < infoVec.size(); ++j )
628 infoVec[j]->_elemCounter++;
630 // pass _elemCounter to a real elem type
631 map< string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.begin();
632 for ( ; n2i != name2GroupInfo.end(); ++n2i )
634 SMESH_PreMeshInfo* info = n2i->second;
635 info->setNb( me2sme->second, info->_elemCounter );
636 info->_elemCounter = 0;
641 //================================================================================
643 * \brief Reads info of sub-meshes from hdf file of old study
645 //================================================================================
647 void SMESH_PreMeshInfo::readSubMeshInfo()
649 if ( _mesh->_mapSubMeshIor.empty() ) return;
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 )
655 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
657 sm->changePreMeshInfo() = newInstance();
658 sm->changePreMeshInfo()->_isInfoOk = true;
663 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
664 aFile->OpenOnDisk( HDF_RDONLY );
666 char meshGrpName[ 30 ];
667 sprintf( meshGrpName, "Mesh %d", _meshID );
668 if ( aFile->ExistInternalObject( meshGrpName ) )
670 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
671 aTopGroup->OpenOnDisk();
672 if ( aTopGroup->ExistInternalObject( "Submeshes" ))
674 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
675 aGroup->OpenOnDisk();
677 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
678 int maxSmId = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
680 for ( int isNode = 0; isNode < 2; ++isNode )
682 string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
683 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
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 )
696 const int smID = smIDs[ i ];
697 if ( smID < (int) nbBySubmeshId.size() )
698 nbBySubmeshId[ smID ]++;
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 )
706 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
708 SMESH_PreMeshInfo* & info = sm->changePreMeshInfo();
710 vector<int> smIds = getSimpleSubMeshIds( meshDS, id2sm->first );
711 for ( size_t i = 0; i < smIds.size(); ++i )
712 info->_elemCounter += nbBySubmeshId[ smIds[i] ];
714 SMDSAbs_EntityType elemType;
717 elemType = SMDSEntity_Node;
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;
726 info->setNb( elemType, info->_elemCounter );
729 } // if ( aGroup->ExistInternalObject( aDSName ))
730 } // for ( int isNode = 0; isNode < 2; ++isNode )
732 aGroup->CloseOnDisk();
733 } // if ( aTopGroup->ExistInternalObject( "Submeshes" ))
735 aTopGroup->CloseOnDisk();
736 } // if ( aFile->ExistInternalObject( meshGrpName ) )
738 aFile->CloseOnDisk();
742 //================================================================================
744 * \brief Return type of element for sub-mesh on a shape of given type
746 //================================================================================
748 SMDSAbs_EntityType SMESH_PreMeshInfo::getElemType( const TopAbs_ShapeEnum shapeType,
749 const int nbElemsInSubMesh,
750 bool& isKoType) const
754 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
759 type = SMDSEntity_Tetra;
760 typeEnd = SMDSEntity_Last;
761 isKoType = ( meshInfo->NbVolumes() != nbElemsInSubMesh );
765 type = SMDSEntity_Triangle;
766 typeEnd = SMDSEntity_Tetra;
767 isKoType = ( meshInfo->NbFaces() != nbElemsInSubMesh );
770 case TopAbs_EDGE: return SMDSEntity_Edge;
771 case TopAbs_VERTEX: return SMDSEntity_0D;
772 default: return SMDSEntity_Last;
777 for ( int t = type; t < typeEnd; ++t )
778 if ( nbElemsInSubMesh == meshInfo->NbEntities( SMDSAbs_EntityType( t )))
779 return SMDSAbs_EntityType( t );
782 return SMDSAbs_EntityType( type );
785 //================================================================================
787 * \brief Saves SMESH_PreMeshInfo to the study file
789 //================================================================================
791 void SMESH_PreMeshInfo::SaveToFile( SMESH_Mesh_i* mesh,
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();
803 meshInfo2hdf( mesh->GetMeshInfo(), "Mesh", infoHdfGroup );
806 SMESH_PreMeshInfo incompleteInfo( 0,0,"","");
807 incompleteInfo.setNb( SMDSEntity_Node, GroupOnFilter_OutOfDate );
808 SMESHDS_Mesh* meshDS = mesh->GetImpl().GetMeshDS();
810 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = mesh->_mapGroups.begin();
811 for ( ; i2group != mesh->_mapGroups.end(); ++i2group )
813 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
815 SMESHDS_GroupBase * group = group_i->GetGroupDS();
816 if ( SMESHDS_GroupOnFilter* gof = dynamic_cast<SMESHDS_GroupOnFilter*>(group))
818 // prevent too long storage time due to applying filter to many elements
819 if ( !gof->IsUpToDate() && meshDS->GetMeshInfo().NbElements( gof->GetType() ) > 1e5 )
821 meshInfo2hdf( incompleteInfo.GetMeshInfo(),
822 group->GetStoreName(),
827 meshInfo2hdf( group_i->GetMeshInfo(), group->GetStoreName(), infoHdfGroup);
831 // info of sub-meshes
832 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = mesh->_mapSubMeshIor.begin();
833 for ( ; id2sm != mesh->_mapSubMeshIor.end(); ++id2sm )
835 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
837 meshInfo2hdf( sm->GetMeshInfo(),
838 SMESH_Comment( sm->GetId() ),
845 infoHdfGroup->CloseOnDisk();
848 //================================================================================
850 * \brief Reads all data and remove all SMESH_PreMeshInfo fields from objects
852 //================================================================================
854 void SMESH_PreMeshInfo::FullLoadFromFile() const
856 SignalToGUI signalOnLoading( _mesh );
858 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
859 _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info
861 ::SMESH_Mesh& mesh = _mesh->GetImpl();
862 SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
866 MYDEBUGOUT( "BEG FullLoadFromFile() " << _meshID );
869 DriverMED_R_SMESHDS_Mesh myReader;
870 myReader.SetFile( _medFileName.c_str() );
871 myReader.SetMesh( meshDS );
872 myReader.SetMeshId( _meshID );
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 );
883 readSubMeshes( &myReader );
887 _mesh->changePreMeshInfo() = meshInfo;
891 signalOnLoading.sendStop();
895 // load dependent meshes referring/referred via hypotheses
896 mesh.GetSubMesh( mesh.GetShapeToMesh() )->
897 ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED);
899 MYDEBUGOUT( "END FullLoadFromFile()" );
902 //================================================================================
904 * \brief Reads full data of sub-meshes
906 //================================================================================
908 void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const
910 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
911 aFile->OpenOnDisk( HDF_RDONLY );
913 char meshGrpName[ 30 ];
914 sprintf( meshGrpName, "Mesh %d", _meshID );
915 if ( aFile->ExistInternalObject( meshGrpName ) )
917 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
918 aTopGroup->OpenOnDisk();
920 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
922 // issue 0020693. Restore _isModified flag
923 if ( aTopGroup->ExistInternalObject( "_isModified" ))
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));
934 bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
935 if ( submeshesInFamilies ) // from MED
937 // old way working before fix of PAL 12992
938 reader->CreateAllSubMeshes();
943 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
944 aGroup->OpenOnDisk();
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 );
950 PositionCreator aPositionCreator;
952 SMDS_NodeIteratorPtr nIt = meshDS->nodesIterator();
953 SMDS_ElemIteratorPtr eIt = meshDS->elementsIterator();
954 for ( int isNode = 0; isNode < 2; ++isNode )
956 string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
957 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
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();
967 // get elements sorted by ID
968 TIDSortedElemSet elemSet;
970 while ( nIt->more() ) elemSet.insert( elemSet.end(), nIt->next() );
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 ) {
978 cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
980 nbElems = elemSet.size();
982 // add elements to submeshes
983 TIDSortedElemSet::iterator iE = elemSet.begin();
984 for ( int i = 0; i < nbElems; ++i, ++iE )
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 );
995 // get or create submesh
996 SMESHDS_SubMesh* & sm = subMeshes[ smID ];
998 sm = meshDS->NewSubMesh( smID );
999 smType[ smID ] = meshDS->IndexToShape( smID ).ShapeType();
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 );
1008 sm->AddElement( elem );
1014 } // end reading submeshes
1016 // Read node positions on sub-shapes (SMDS_Position)
1018 if ( aTopGroup->ExistInternalObject( "Node Positions" ))
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";
1033 int nbEids = 0, nbFids = 0;
1034 int *aEids = 0, *aFids = 0;
1035 double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
1038 HDFgroup* aGroup = new HDFgroup( "Node Positions", aTopGroup );
1039 aGroup->OpenOnDisk();
1041 // loop on 5 data sets
1042 int aNbObjects = aGroup->nInternalObjects();
1043 for ( int i = 0; i < aNbObjects; i++ )
1046 char aDSName[ HDF_NAME_MAX_LEN+1 ];
1047 aGroup->InternalObjectIndentify( i, aDSName );
1049 HDFdataset* aDataset = new HDFdataset( aDSName, aGroup );
1050 aDataset->OpenOnDisk();
1051 if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
1053 double* pos = new double [ aDataset->GetSize() ];
1054 aDataset->ReadFromDisk( pos );
1056 if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
1058 else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
1065 int aSize = aDataset->GetSize();
1067 // for reading files, created from 18.07.2005 till 10.10.2005
1068 if (aDataset->GetType() == HDF_STRING)
1069 aSize /= sizeof(int);
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 ) {
1083 aDataset->CloseOnDisk();
1084 } // loop on 5 datasets
1086 // Set node positions on edges or faces
1087 for ( int onFace = 0; onFace < 2; onFace++ )
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 );
1095 for ( int iNode = 0; iNode < nbNodes; iNode++ )
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();
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 ]);
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 ]);
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;
1128 aGroup->CloseOnDisk();
1130 } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
1132 aTopGroup->CloseOnDisk();
1133 } // if ( aFile->ExistInternalObject( meshGrpName ) )
1135 aFile->CloseOnDisk();
1139 //================================================================================
1141 * \brief Remove all SMESH_PreMeshInfo fields from objects w/o data loading
1143 //================================================================================
1145 void SMESH_PreMeshInfo::ForgetAllData() const
1149 if ( _mesh->changePreMeshInfo() != this )
1150 return _mesh->changePreMeshInfo()->ForgetAllData();
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 )
1156 if ( SMESH_GroupBase_i* group_i =
1157 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
1159 SMESH_PreMeshInfo* & info = group_i->changePreMeshInfo();
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 )
1168 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
1170 SMESH_PreMeshInfo* & info = sm->changePreMeshInfo();
1175 // remove SMESH_PreMeshInfo from the mesh
1176 _mesh->changePreMeshInfo() = NULL;
1186 // ::SMESH_Mesh& mesh = _mesh->GetImpl();
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();
1195 // PreMeshInfo_CATCH;
1198 //================================================================================
1200 * \brief Calls either FullLoadFromFile() or ForgetAllData() depending on preferences
1202 //================================================================================
1204 void SMESH_PreMeshInfo::ForgetOrLoad() const
1206 if ( SMESH_Gen_i::GetSMESHGen()->ToForgetMeshDataOnHypModif() &&
1207 _mesh->HasShapeToMesh())
1213 //================================================================================
1215 * \brief Method of SMESH_IDSource interface
1217 //================================================================================
1219 SMESH::array_of_ElementType* SMESH_PreMeshInfo::GetTypes() const
1221 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
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 );
1232 return types._retn();
1235 //================================================================================
1237 * \brief Method of SMESH_IDSource interface returning nb elements by element type
1239 //================================================================================
1241 SMESH::long_array* SMESH_PreMeshInfo::GetMeshInfo() const
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++)
1248 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1249 aRes[i] = NbEntities((SMDSAbs_EntityType)i);
1250 return aRes._retn();
1253 //================================================================================
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.
1258 //================================================================================
1260 bool SMESH_PreMeshInfo::IsMeshInfoCorrect() const
1265 //================================================================================
1267 * \brief TEMPORARY method to remove study files on closing study;
1268 * RIGHT WAY: study files are remove automatically when meshes are destroyed
1270 //================================================================================
1272 void SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp)
1274 SALOMEDS::Study_var study = smeshComp->GetStudy();
1275 if ( theStudyIDToMeshCounter[ (int) study->StudyId() ] > 0 )
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 ))
1283 if ( mesh->changePreMeshInfo() )
1285 mesh->changePreMeshInfo()->ForgetAllData();