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 <MED_Factory.hxx>
43 #include <HDFarray.hxx>
44 #include <HDFdataset.hxx>
45 #include <HDFfile.hxx>
46 #include <HDFgroup.hxx>
47 #include <SALOMEDS_Tool.hxx>
48 #include <SALOMEDS_wrap.hxx>
50 #include <Standard_ErrorHandler.hxx>
51 #include <Standard_Failure.hxx>
52 #include <TopoDS_Iterator.hxx>
53 #include <TopoDS_Shape.hxx>
55 #include CORBA_SERVER_HEADER(SALOME_Session)
57 #define MYDEBUGOUT(msg) //std::cout << msg << std::endl;
59 //================================================================================
60 #define PreMeshInfo_TRY \
61 try { OCC_CATCH_SIGNALS
62 //================================================================================
63 #define PreMeshInfo_CATCH } \
64 catch (Standard_Failure& ex) { \
65 onExceptionCaught(SMESH_Comment("OCC Exception caught: \t")<<ex.GetMessageString()); \
67 catch ( const std::exception& ex) { \
68 onExceptionCaught(SMESH_Comment("Exception caught: \t")<<ex.what()); \
71 onExceptionCaught("Unknown Exception caught"); \
73 //================================================================================
77 enum { GroupOnFilter_OutOfDate = -1 };
79 // a map to count not yet loaded meshes
80 static map< int, int > theStudyIDToMeshCounter;
82 //================================================================================
84 * \brief Counts not fully loaded meshes
86 //================================================================================
88 void meshInfoLoaded( SMESH_Mesh_i* mesh )
90 map< int, int >::iterator id2counter =
91 theStudyIDToMeshCounter.insert( make_pair( (int) mesh->GetStudyId(), 0 )).first;
94 //================================================================================
96 * \brief Removes temporary files if none of meshes needs them
98 //================================================================================
100 void filesNoMoreNeeded(SMESH_Mesh_i* mesh,
104 if ( --theStudyIDToMeshCounter[ (int) mesh->GetStudyId() ] == 0 )
106 string tmpDir = SALOMEDS_Tool::GetDirFromPath( hdfFile );
108 SALOMEDS::ListOfFileNames_var aFiles = new SALOMEDS::ListOfFileNames;
110 medFile = SALOMEDS_Tool::GetNameFromPath( medFile ) + ".med";
111 hdfFile = SALOMEDS_Tool::GetNameFromPath( hdfFile ) + ".hdf";
112 aFiles[0] = medFile.c_str();
113 aFiles[1] = hdfFile.c_str();
115 SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.c_str(), aFiles.in(), true );
119 //================================================================================
121 * \brief Method useful only to set a breakpoint to debug in case of exception
123 //================================================================================
125 void onExceptionCaught(const string& msg)
131 //=============================================================================
133 * \brief Class sending signals on start and finish of loading
135 //=============================================================================
139 string _messagePrefix;
140 SALOME::Session_var _session;
142 SignalToGUI( SMESH_Mesh_i* mesh )
144 SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
145 SALOMEDS::Study_var study = gen->GetCurrentStudy();
146 if ( !study->_is_nil() && study->StudyId() == mesh->GetStudyId() )
148 SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject(study, mesh->_this() );
149 CORBA::Object_var obj = gen->GetNS()->Resolve( "/Kernel/Session" );
150 _session = SALOME::Session::_narrow( obj );
151 if ( !meshSO->_is_nil() && !_session->_is_nil() )
153 CORBA::String_var meshEntry = meshSO->GetID();
154 _messagePrefix = "SMESH/mesh_loading/";
155 _messagePrefix += meshEntry.in();
157 string msgToGUI = _messagePrefix + "/";
158 msgToGUI += SMESH_Comment( mesh->NbNodes() );
160 msgToGUI += SMESH_Comment( mesh->NbElements() );
162 _session->emitMessageOneWay( msgToGUI.c_str());
168 if ( !_messagePrefix.empty() )
170 string msgToGUI = _messagePrefix + "/stop";
171 _session->emitMessageOneWay( msgToGUI.c_str());
172 _messagePrefix.clear();
175 ~SignalToGUI() { sendStop(); }
178 //=============================================================================
180 * \brief Creates SMDS_Position according to shape type
182 //=============================================================================
184 class PositionCreator {
186 SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
187 return (this->*myFuncTable[ type ])();
190 myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition );
191 myFuncTable[ TopAbs_SOLID ] = & PositionCreator::volumePosition;
192 myFuncTable[ TopAbs_FACE ] = & PositionCreator::facePosition;
193 myFuncTable[ TopAbs_EDGE ] = & PositionCreator::edgePosition;
194 myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition;
197 SMDS_PositionPtr edgePosition() const { return SMDS_PositionPtr( new SMDS_EdgePosition ); }
198 SMDS_PositionPtr facePosition() const { return SMDS_PositionPtr( new SMDS_FacePosition ); }
199 SMDS_PositionPtr volumePosition() const { return SMDS_PositionPtr( new SMDS_SpacePosition ); }
200 SMDS_PositionPtr vertexPosition() const { return SMDS_PositionPtr( new SMDS_VertexPosition); }
201 SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition(); }
202 typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const;
203 vector<FmakePos> myFuncTable;
206 //================================================================================
208 * \brief Returns ids of simple shapes composing a complex one
210 //================================================================================
212 vector<int> getSimpleSubMeshIds( SMESHDS_Mesh* meshDS, int shapeId )
216 list<TopoDS_Shape> shapeQueue( 1, meshDS->IndexToShape( shapeId ));
217 list<TopoDS_Shape>::iterator shape = shapeQueue.begin();
218 for ( ; shape != shapeQueue.end(); ++shape )
220 if ( shape->IsNull() ) continue;
221 if ( shape->ShapeType() == TopAbs_COMPOUND ||
222 shape->ShapeType() == TopAbs_COMPSOLID )
224 for ( TopoDS_Iterator it( *shape ); it.More(); it.Next() )
225 shapeQueue.push_back( it.Value() );
229 ids.push_back( meshDS->ShapeToIndex( *shape ));
235 //================================================================================
237 * \brief Return EEntiteMaillage by EGeometrieElement
239 //================================================================================
241 MED::EEntiteMaillage entityByGeom(const MED::EGeometrieElement geom )
243 return geom == MED::eBALL ? MED::eSTRUCT_ELEMENT : MED::eMAILLE;
246 //================================================================================
248 * \brief Return a map< EGeometrieElement, SMDSAbs_EntityType >
250 //================================================================================
252 typedef map< MED::EGeometrieElement, SMDSAbs_EntityType > Tmed2smeshElemTypeMap;
253 const Tmed2smeshElemTypeMap& med2smeshElemTypeMap()
255 static map< MED::EGeometrieElement, SMDSAbs_EntityType> med2smeshTypes;
256 if ( med2smeshTypes.empty() )
258 med2smeshTypes[ MED::ePOINT1 ] = SMDSEntity_0D ;
259 med2smeshTypes[ MED::eSEG2 ] = SMDSEntity_Edge ;
260 med2smeshTypes[ MED::eSEG3 ] = SMDSEntity_Quad_Edge ;
261 med2smeshTypes[ MED::eTRIA3 ] = SMDSEntity_Triangle ;
262 med2smeshTypes[ MED::eTRIA6 ] = SMDSEntity_Quad_Triangle ;
263 med2smeshTypes[ MED::eQUAD4 ] = SMDSEntity_Quadrangle ;
264 med2smeshTypes[ MED::eQUAD8 ] = SMDSEntity_Quad_Quadrangle ;
265 med2smeshTypes[ MED::eQUAD9 ] = SMDSEntity_BiQuad_Quadrangle ;
266 med2smeshTypes[ MED::eTETRA4 ] = SMDSEntity_Tetra ;
267 med2smeshTypes[ MED::ePYRA5 ] = SMDSEntity_Pyramid ;
268 med2smeshTypes[ MED::ePENTA6 ] = SMDSEntity_Penta ;
269 med2smeshTypes[ MED::eHEXA8 ] = SMDSEntity_Hexa ;
270 med2smeshTypes[ MED::eOCTA12 ] = SMDSEntity_Hexagonal_Prism ;
271 med2smeshTypes[ MED::eTETRA10 ] = SMDSEntity_Quad_Tetra ;
272 med2smeshTypes[ MED::ePYRA13 ] = SMDSEntity_Quad_Pyramid ;
273 med2smeshTypes[ MED::ePENTA15 ] = SMDSEntity_Quad_Penta ;
274 med2smeshTypes[ MED::eHEXA20 ] = SMDSEntity_Quad_Hexa ;
275 med2smeshTypes[ MED::eHEXA27 ] = SMDSEntity_TriQuad_Hexa ;
276 med2smeshTypes[ MED::ePOLYGONE ] = SMDSEntity_Polygon ;
277 med2smeshTypes[ MED::ePOLYEDRE ] = SMDSEntity_Polyhedra ;
278 med2smeshTypes[ MED::eNONE ] = SMDSEntity_Node ;
279 med2smeshTypes[ MED::eBALL ] = SMDSEntity_Ball ;
281 return med2smeshTypes;
284 //================================================================================
286 * \brief Return a vector<MED::EGeometrieElement> intended to retrieve
287 * MED::EGeometrieElement by SMDSAbs_EntityType
289 //================================================================================
291 const vector<MED::EGeometrieElement>& mesh2medElemType()
293 static vector<MED::EGeometrieElement> mesh2medElemTypes;
294 if ( mesh2medElemTypes.empty() )
296 mesh2medElemTypes.resize( SMDSEntity_Last + 1 );
297 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
298 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
299 for ( ; me2sme != me2smeEnd; ++me2sme )
300 mesh2medElemTypes[ me2sme->second ] = me2sme->first;
302 return mesh2medElemTypes;
305 //================================================================================
307 * \brief Writes meshInfo into a HDF file
309 //================================================================================
311 void meshInfo2hdf( SMESH::long_array_var meshInfo,
312 const std::string& name,
315 // we use med identification of element (MED::EGeometrieElement>) types
316 // but not enum SMDSAbs_EntityType because values of SMDSAbs_EntityType may
317 // change at insertion of new items in the middle.
318 const vector<MED::EGeometrieElement>& medTypes = mesh2medElemType();
322 for ( size_t i = 0; i < meshInfo->length(); ++i )
323 if ( meshInfo[i] > 0 )
325 data.push_back( medTypes[ i ] );
326 data.push_back( meshInfo[ i ] );
331 hdf_size datasetSize[] = { data.size() };
332 HDFarray* anArray = new HDFarray(0, HDF_INT32, 1, datasetSize);
333 anArray->CreateOnDisk();
335 HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup, HDF_ARRAY, datasetSize, 1 );
336 dataset->SetArrayId(anArray->GetId());
337 dataset->CreateOnDisk();
338 dataset->WriteOnDisk( & data[0] );
339 dataset->CloseOnDisk();
340 anArray->CloseOnDisk();
345 //================================================================================
347 * \brief Reads meshInfo from a HDF file
349 //================================================================================
351 void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name,
354 if ( hdfGroup->ExistInternalObject( name.c_str()) )
356 HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup );
357 dataset->OpenOnDisk();
359 // // hdf_size datasetSize[ 1 ];
360 // // HDFarray *array = new HDFarray(dataset);
361 // // array->GetDim( datasetSize );
362 // int size = dataset->GetSize();
364 vector<int> info( SMDSEntity_Last * 2, 0 );
365 dataset->ReadFromDisk( &info[0] );
366 dataset->CloseOnDisk();
368 const Tmed2smeshElemTypeMap& med2smesh = med2smeshElemTypeMap();
369 Tmed2smeshElemTypeMap::const_iterator me2sme, me2smeEnd = med2smesh.end();
370 for ( size_t i = 0; i < info.size(); )
372 int medType = info[i++];
373 int nbElems = info[i++];
374 if ( !nbElems ) break;
375 me2sme = med2smesh.find( (MED::EGeometrieElement) medType );
376 if ( me2sme != me2smeEnd )
377 setNb( me2sme->second, nbElems );
382 if ( NbNodes() == GroupOnFilter_OutOfDate ) // case of !SMESHDS_GroupOnFilter::IsUpToDate()
385 setNb( SMDSEntity_Node, 0 );
389 //================================================================================
391 * \brief Constructor callable by SMESH_PreMeshInfo only
393 //================================================================================
395 SMESH_PreMeshInfo::SMESH_PreMeshInfo(SMESH_Mesh_i* mesh,
397 const std::string& medFile,
398 const std::string& hdfFile)
399 : _medFileName( medFile ),
400 _hdfFileName( hdfFile ),
401 _toRemoveFiles( false ),
409 //================================================================================
411 * \brief Release temporary files
413 //================================================================================
415 SMESH_PreMeshInfo::~SMESH_PreMeshInfo()
417 if ( _toRemoveFiles ) // it can be true only for SMESH_PreMeshInfo of the mesh
418 filesNoMoreNeeded( _mesh, _medFileName, _hdfFileName );
420 _toRemoveFiles = false;
423 //================================================================================
425 * \brief fills SMESH_PreMeshInfo field of all objects of mesh
427 //================================================================================
429 void SMESH_PreMeshInfo::LoadFromFile( SMESH_Mesh_i* mesh,
431 const std::string& medFile,
432 const std::string& hdfFile,
433 const bool toRemoveFiles)
437 SMESH_PreMeshInfo* meshPreInfo = new SMESH_PreMeshInfo( mesh,meshID,medFile,hdfFile );
438 mesh->changePreMeshInfo() = meshPreInfo;
440 meshPreInfo->_toRemoveFiles = toRemoveFiles;
442 meshInfoLoaded( mesh );
444 if ( meshPreInfo->readPreInfoFromHDF() )
445 // all SMESH_PreMeshInfo's are stored in HDF file (written after
446 // implementing SMESH_PreMeshInfo)
449 // try to read SMESH_PreMeshInfo from med file (as study is older than SMESH_PreMeshInfo)
450 if ( meshPreInfo->readMeshInfo() )
452 meshPreInfo->readGroupInfo();
453 meshPreInfo->readSubMeshInfo();
457 meshPreInfo->FullLoadFromFile();
462 //================================================================================
464 * \brief Tries to read all SMESH_PreMeshInfo from a HDF file
465 * \retval bool - true if succeeded
467 * This method is symmetrical to SaveToFile()
469 //================================================================================
471 bool SMESH_PreMeshInfo::readPreInfoFromHDF()
473 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
474 aFile->OpenOnDisk( HDF_RDONLY );
476 SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << _meshID;
477 const bool infoAvailable = aFile->ExistInternalObject( hdfGroupName );
480 HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile );
481 infoHdfGroup->OpenOnDisk();
483 _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup );
485 // read SMESH_PreMeshInfo of groups
486 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
487 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
489 if ( SMESH_GroupBase_i* group_i =
490 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
492 group_i->changePreMeshInfo() = newInstance();
493 if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() )
495 const string name = group->GetStoreName();
496 group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup );
501 // read SMESH_PreMeshInfo of sub-meshes
502 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
503 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
505 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
507 sm->changePreMeshInfo() = newInstance();
508 sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()), infoHdfGroup );
513 aFile->CloseOnDisk();
516 return infoAvailable;
519 //================================================================================
521 * \brief Reads mesh info of mesh from the med file
523 //================================================================================
525 bool SMESH_PreMeshInfo::readMeshInfo()
529 MED::PWrapper aMed = MED::CrWrapper(_medFileName,true);
530 // if ( aMed->GetVersion() != MED::eV2_2 )
533 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
536 int nbNodes = std::max( 0, aMed->GetNbNodes( medMeshInfo ));
539 setNb( SMDSEntity_Node, nbNodes);
541 // read nb of elements
542 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
543 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
544 for ( ; me2sme != me2smeEnd; ++me2sme )
546 int nbElems = aMed->GetNbCells( medMeshInfo, entityByGeom(me2sme->first), me2sme->first );
548 setNb( me2sme->second, nbElems );
554 //================================================================================
556 * \brief Reads info of groups from the med file
558 //================================================================================
560 void SMESH_PreMeshInfo::readGroupInfo()
562 if ( _mesh->_mapGroups.empty() ) return;
564 // make SMESH_PreMeshInfo of groups
565 map< string, SMESH_PreMeshInfo* > name2GroupInfo;
566 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
567 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
569 if ( SMESH_GroupBase_i* group_i =
570 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
572 SMESH_PreMeshInfo* info = newInstance();
573 group_i->changePreMeshInfo() = info;
574 if ( SMESHDS_Group* group = dynamic_cast< SMESHDS_Group* >( group_i->GetGroupDS() ))
576 string name = group->GetStoreName();
577 name2GroupInfo.insert( make_pair( name, info ));
578 info->_isInfoOk = true;
583 map< int, vector< SMESH_PreMeshInfo* > > famId2grInfo;
585 MED::PWrapper aMed = MED::CrWrapper(_medFileName,false);
586 MED::PMeshInfo medMeshInfo = aMed->CrMeshInfo(3,3,SMESH_Comment( _meshID ));
588 // read families to fill in famId2grInfo
589 int nbFams = aMed->GetNbFamilies( medMeshInfo );
590 if ( nbFams <= 1 ) return; // zero family is always present
591 for ( int iF = 0; iF <= nbFams; ++iF )
593 int nbGroups = aMed->GetNbFamGroup( iF, medMeshInfo );
594 if ( nbGroups < 1 ) continue;
595 MED::PFamilyInfo medFamInfo = aMed->CrFamilyInfo( medMeshInfo, nbGroups, nbGroups );
596 aMed->GetFamilyInfo( iF, medFamInfo ); // read groups of a family
597 vector< SMESH_PreMeshInfo* >& grInfoVec = famId2grInfo[ medFamInfo->GetId() ];
598 for ( int iG = 0; iG < nbGroups; ++iG )
600 const string grName = medFamInfo->GetGroupName( iG );
601 map< string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.find( grName );
602 if ( n2i != name2GroupInfo.end() )
603 grInfoVec.push_back( n2i->second );
607 // read family numbers of elements
608 Tmed2smeshElemTypeMap::const_iterator me2sme = med2smeshElemTypeMap().begin();
609 Tmed2smeshElemTypeMap::const_iterator me2smeEnd = med2smeshElemTypeMap().end();
610 MED::PElemInfo medElemInfo = aMed->CrElemInfo( medMeshInfo, 0 );
611 MED::TIntVector& famNums = medElemInfo->myFamNum;
612 for ( ; me2sme != me2smeEnd; ++me2sme ) // loop on elem types
614 famNums.resize( NbEntities( me2sme->second ));
615 if ( famNums.empty() ) continue;
616 aMed->GetFamilies( medElemInfo, famNums.size(), entityByGeom(me2sme->first), me2sme->first );
617 // distribute elements of a type among groups
618 map< int, vector< SMESH_PreMeshInfo* > >::iterator f2infos = famId2grInfo.begin();
619 for ( size_t i = 0; i < famNums.size(); ++i )
621 if ( famNums[i] != f2infos->first )
623 f2infos = famId2grInfo.find( famNums[i] );
624 if ( f2infos == famId2grInfo.end() )
625 f2infos = famId2grInfo.insert
626 ( make_pair( famNums[i], vector< SMESH_PreMeshInfo*>())).first;
628 vector< SMESH_PreMeshInfo* >& infoVec = f2infos->second ;
629 for ( size_t j = 0; j < infoVec.size(); ++j )
630 infoVec[j]->_elemCounter++;
632 // pass _elemCounter to a real elem type
633 map< string, SMESH_PreMeshInfo* >::iterator n2i = name2GroupInfo.begin();
634 for ( ; n2i != name2GroupInfo.end(); ++n2i )
636 SMESH_PreMeshInfo* info = n2i->second;
637 info->setNb( me2sme->second, info->_elemCounter );
638 info->_elemCounter = 0;
643 //================================================================================
645 * \brief Reads info of sub-meshes from hdf file of old study
647 //================================================================================
649 void SMESH_PreMeshInfo::readSubMeshInfo()
651 if ( _mesh->_mapSubMeshIor.empty() ) return;
653 // create SMESH_PreMeshInfo of sub-meshes
654 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
655 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
657 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
659 sm->changePreMeshInfo() = newInstance();
660 sm->changePreMeshInfo()->_isInfoOk = true;
665 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
666 aFile->OpenOnDisk( HDF_RDONLY );
668 char meshGrpName[ 30 ];
669 sprintf( meshGrpName, "Mesh %d", _meshID );
670 if ( aFile->ExistInternalObject( meshGrpName ) )
672 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
673 aTopGroup->OpenOnDisk();
674 if ( aTopGroup->ExistInternalObject( "Submeshes" ))
676 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
677 aGroup->OpenOnDisk();
679 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
680 int maxSmId = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
682 for ( int isNode = 0; isNode < 2; ++isNode )
684 string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
685 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
687 // read sub-mesh id of all nodes or elems
688 HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
689 aDataset->OpenOnDisk();
690 int nbElems = aDataset->GetSize();
691 int* smIDs = new int [ nbElems ];
692 aDataset->ReadFromDisk( smIDs );
693 aDataset->CloseOnDisk();
694 // count nb elems in each sub-mesh
695 vector<int> nbBySubmeshId( maxSmId + 1, 0 );
696 for ( int i = 0; i < nbElems; ++i )
698 const int smID = smIDs[ i ];
699 if ( smID < (int) nbBySubmeshId.size() )
700 nbBySubmeshId[ smID ]++;
704 // store nb elems in SMESH_PreMeshInfo of sub-meshes
705 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
706 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
708 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
710 SMESH_PreMeshInfo* & info = sm->changePreMeshInfo();
712 vector<int> smIds = getSimpleSubMeshIds( meshDS, id2sm->first );
713 for ( size_t i = 0; i < smIds.size(); ++i )
714 info->_elemCounter += nbBySubmeshId[ smIds[i] ];
716 SMDSAbs_EntityType elemType;
719 elemType = SMDSEntity_Node;
723 bool koElemType = false;
724 const TopoDS_Shape& shape = meshDS->IndexToShape( smIds[0] );
725 elemType = getElemType( shape.ShapeType(), info->_elemCounter, koElemType );
726 info->_isInfoOk = !koElemType;
728 info->setNb( elemType, info->_elemCounter );
731 } // if ( aGroup->ExistInternalObject( aDSName ))
732 } // for ( int isNode = 0; isNode < 2; ++isNode )
734 aGroup->CloseOnDisk();
735 } // if ( aTopGroup->ExistInternalObject( "Submeshes" ))
737 aTopGroup->CloseOnDisk();
738 } // if ( aFile->ExistInternalObject( meshGrpName ) )
740 aFile->CloseOnDisk();
744 //================================================================================
746 * \brief Return type of element for sub-mesh on a shape of given type
748 //================================================================================
750 SMDSAbs_EntityType SMESH_PreMeshInfo::getElemType( const TopAbs_ShapeEnum shapeType,
751 const int nbElemsInSubMesh,
752 bool& isKoType) const
756 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
761 type = SMDSEntity_Tetra;
762 typeEnd = SMDSEntity_Last;
763 isKoType = ( meshInfo->NbVolumes() != nbElemsInSubMesh );
767 type = SMDSEntity_Triangle;
768 typeEnd = SMDSEntity_Tetra;
769 isKoType = ( meshInfo->NbFaces() != nbElemsInSubMesh );
772 case TopAbs_EDGE: return SMDSEntity_Edge;
773 case TopAbs_VERTEX: return SMDSEntity_0D;
774 default: return SMDSEntity_Last;
779 for ( int t = type; t < typeEnd; ++t )
780 if ( nbElemsInSubMesh == meshInfo->NbEntities( SMDSAbs_EntityType( t )))
781 return SMDSAbs_EntityType( t );
784 return SMDSAbs_EntityType( type );
787 //================================================================================
789 * \brief Saves SMESH_PreMeshInfo to the study file
791 //================================================================================
793 void SMESH_PreMeshInfo::SaveToFile( SMESH_Mesh_i* mesh,
797 // create a HDF group for SMESH_PreMeshInfo of this mesh
798 SMESH_Comment hdfGroupName("SMESH_PreMeshInfo"); hdfGroupName << meshID;
799 HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, hdfFile );
800 infoHdfGroup->CreateOnDisk();
805 meshInfo2hdf( mesh->GetMeshInfo(), "Mesh", infoHdfGroup );
808 SMESH_PreMeshInfo incompleteInfo( 0,0,"","");
809 incompleteInfo.setNb( SMDSEntity_Node, GroupOnFilter_OutOfDate );
810 SMESHDS_Mesh* meshDS = mesh->GetImpl().GetMeshDS();
812 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = mesh->_mapGroups.begin();
813 for ( ; i2group != mesh->_mapGroups.end(); ++i2group )
815 if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
817 SMESHDS_GroupBase * group = group_i->GetGroupDS();
818 if ( SMESHDS_GroupOnFilter* gof = dynamic_cast<SMESHDS_GroupOnFilter*>(group))
820 // prevent too long storage time due to applying filter to many elements
821 if ( !gof->IsUpToDate() && meshDS->GetMeshInfo().NbElements( gof->GetType() ) > 1e5 )
823 meshInfo2hdf( incompleteInfo.GetMeshInfo(),
824 group->GetStoreName(),
829 meshInfo2hdf( group_i->GetMeshInfo(), group->GetStoreName(), infoHdfGroup);
833 // info of sub-meshes
834 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = mesh->_mapSubMeshIor.begin();
835 for ( ; id2sm != mesh->_mapSubMeshIor.end(); ++id2sm )
837 if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
839 meshInfo2hdf( sm->GetMeshInfo(),
840 SMESH_Comment( sm->GetId() ),
847 infoHdfGroup->CloseOnDisk();
850 //================================================================================
852 * \brief Reads all data and remove all SMESH_PreMeshInfo fields from objects
854 //================================================================================
856 void SMESH_PreMeshInfo::FullLoadFromFile() const
858 SignalToGUI signalOnLoading( _mesh );
860 SMESH_PreMeshInfo* meshInfo = _mesh->changePreMeshInfo();
861 _mesh->changePreMeshInfo() = NULL; // to allow GUI accessing to real info
863 ::SMESH_Mesh& mesh = _mesh->GetImpl();
864 SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
868 MYDEBUGOUT( "BEG FullLoadFromFile() " << _meshID );
871 DriverMED_R_SMESHDS_Mesh myReader;
872 myReader.SetFile( _medFileName.c_str() );
873 myReader.SetMesh( meshDS );
874 myReader.SetMeshId( _meshID );
878 const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
879 set<SMESHDS_GroupBase*>::const_iterator groupIt = groups.begin();
880 for ( ; groupIt != groups.end(); ++groupIt )
881 if ( SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( *groupIt ))
882 myReader.GetGroup( aGrp );
885 readSubMeshes( &myReader );
889 _mesh->changePreMeshInfo() = meshInfo;
893 signalOnLoading.sendStop();
897 // load dependent meshes referring/referred via hypotheses
898 mesh.GetSubMesh( mesh.GetShapeToMesh() )->
899 ComputeStateEngine (SMESH_subMesh::SUBMESH_LOADED);
901 MYDEBUGOUT( "END FullLoadFromFile()" );
904 //================================================================================
906 * \brief Reads full data of sub-meshes
908 //================================================================================
910 void SMESH_PreMeshInfo::readSubMeshes(DriverMED_R_SMESHDS_Mesh* reader) const
912 HDFfile* aFile = new HDFfile( (char*) _hdfFileName.c_str() );
913 aFile->OpenOnDisk( HDF_RDONLY );
915 char meshGrpName[ 30 ];
916 sprintf( meshGrpName, "Mesh %d", _meshID );
917 if ( aFile->ExistInternalObject( meshGrpName ) )
919 HDFgroup* aTopGroup = new HDFgroup( meshGrpName, aFile );
920 aTopGroup->OpenOnDisk();
922 SMESHDS_Mesh* meshDS = _mesh->GetImpl().GetMeshDS();
924 // issue 0020693. Restore _isModified flag
925 if ( aTopGroup->ExistInternalObject( "_isModified" ))
927 HDFdataset* aDataset = new HDFdataset( "_isModified", aTopGroup );
928 aDataset->OpenOnDisk();
929 hdf_size size = aDataset->GetSize();
930 int* isModified = new int[ size ];
931 aDataset->ReadFromDisk( isModified );
932 aDataset->CloseOnDisk();
933 _mesh->GetImpl().SetIsModified( bool(*isModified));
934 delete [] isModified;
937 bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
938 if ( submeshesInFamilies ) // from MED
940 // old way working before fix of PAL 12992
941 reader->CreateAllSubMeshes();
946 HDFgroup* aGroup = new HDFgroup( "Submeshes", aTopGroup );
947 aGroup->OpenOnDisk();
949 int maxID = Max( meshDS->MaxSubMeshIndex(), meshDS->MaxShapeIndex() );
950 vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 );
951 vector< TopAbs_ShapeEnum > smType ( maxID + 1, TopAbs_SHAPE );
953 PositionCreator aPositionCreator;
955 SMDS_NodeIteratorPtr nIt = meshDS->nodesIterator();
956 SMDS_ElemIteratorPtr eIt = meshDS->elementsIterator();
957 for ( int isNode = 0; isNode < 2; ++isNode )
959 string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
960 if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
962 HDFdataset* aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
963 aDataset->OpenOnDisk();
964 // read submesh IDs for all elements sorted by ID
965 int nbElems = aDataset->GetSize();
966 int* smIDs = new int [ nbElems ];
967 aDataset->ReadFromDisk( smIDs );
968 aDataset->CloseOnDisk();
970 // get elements sorted by ID
971 TIDSortedElemSet elemSet;
973 while ( nIt->more() ) elemSet.insert( elemSet.end(), nIt->next() );
975 while ( eIt->more() ) elemSet.insert( elemSet.end(), eIt->next() );
976 //ASSERT( elemSet.size() == nbElems ); -- issue 20182
977 // -- Most probably a bad study was saved when there were
978 // not fixed bugs in SMDS_MeshInfo
979 if ( elemSet.size() < nbElems ) {
981 cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
983 nbElems = elemSet.size();
985 // add elements to submeshes
986 TIDSortedElemSet::iterator iE = elemSet.begin();
987 for ( int i = 0; i < nbElems; ++i, ++iE )
989 int smID = smIDs[ i ];
990 if ( smID == 0 ) continue;
991 const SMDS_MeshElement* elem = *iE;
992 if ( smID > maxID ) {
993 // corresponding subshape no longer exists: maybe geom group has been edited
994 if ( _mesh->GetImpl().HasShapeToMesh() )
995 meshDS->RemoveElement( elem );
998 // get or create submesh
999 SMESHDS_SubMesh* & sm = subMeshes[ smID ];
1001 sm = meshDS->NewSubMesh( smID );
1002 smType[ smID ] = meshDS->IndexToShape( smID ).ShapeType();
1006 SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]);
1007 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( static_cast<const SMDS_MeshNode*>( elem ));
1008 node->SetPosition( pos );
1009 sm->AddNode( node );
1011 sm->AddElement( elem );
1017 } // end reading submeshes
1019 // Read node positions on sub-shapes (SMDS_Position)
1021 if ( aTopGroup->ExistInternalObject( "Node Positions" ))
1023 // There are 5 datasets to read:
1024 // "Nodes on Edges" - ID of node on edge
1025 // "Edge positions" - U parameter on node on edge
1026 // "Nodes on Faces" - ID of node on face
1027 // "Face U positions" - U parameter of node on face
1028 // "Face V positions" - V parameter of node on face
1029 const char* aEid_DSName = "Nodes on Edges";
1030 const char* aEu_DSName = "Edge positions";
1031 const char* aFu_DSName = "Face U positions";
1032 //char* aFid_DSName = "Nodes on Faces";
1033 //char* aFv_DSName = "Face V positions";
1036 int nbEids = 0, nbFids = 0;
1037 int *aEids = 0, *aFids = 0;
1038 double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
1041 HDFgroup* aGroup = new HDFgroup( "Node Positions", aTopGroup );
1042 aGroup->OpenOnDisk();
1044 // loop on 5 data sets
1045 int aNbObjects = aGroup->nInternalObjects();
1046 for ( int i = 0; i < aNbObjects; i++ )
1049 char aDSName[ HDF_NAME_MAX_LEN+1 ];
1050 aGroup->InternalObjectIndentify( i, aDSName );
1052 HDFdataset* aDataset = new HDFdataset( aDSName, aGroup );
1053 aDataset->OpenOnDisk();
1054 if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
1056 double* pos = new double [ aDataset->GetSize() ];
1057 aDataset->ReadFromDisk( pos );
1059 if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
1061 else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
1068 int aSize = aDataset->GetSize();
1070 // for reading files, created from 18.07.2005 till 10.10.2005
1071 if (aDataset->GetType() == HDF_STRING)
1072 aSize /= sizeof(int);
1074 int* ids = new int [aSize];
1075 aDataset->ReadFromDisk( ids );
1076 // on face or nodes?
1077 if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
1086 aDataset->CloseOnDisk();
1087 } // loop on 5 datasets
1089 // Set node positions on edges or faces
1090 for ( int onFace = 0; onFace < 2; onFace++ )
1092 int nbNodes = ( onFace ? nbFids : nbEids );
1093 if ( nbNodes == 0 ) continue;
1094 int* aNodeIDs = ( onFace ? aFids : aEids );
1095 double* aUPos = ( onFace ? aFupos : aEpos );
1096 double* aVPos = ( onFace ? aFvpos : 0 );
1098 for ( int iNode = 0; iNode < nbNodes; iNode++ )
1100 const SMDS_MeshNode* node = meshDS->FindNode( aNodeIDs[ iNode ]);
1101 if ( !node ) continue; // maybe removed while Loading() if geometry changed
1102 SMDS_PositionPtr aPos = node->GetPosition();
1105 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182
1106 // -- Most probably a bad study was saved when there were
1107 // not fixed bugs in SMDS_MeshInfo
1108 if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
1109 SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
1110 ( static_cast<const SMDS_FacePosition*>( aPos ));
1111 fPos->SetUParameter( aUPos[ iNode ]);
1112 fPos->SetVParameter( aVPos[ iNode ]);
1116 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182
1117 if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) {
1118 SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
1119 ( static_cast<const SMDS_EdgePosition*>( aPos ));
1120 fPos->SetUParameter( aUPos[ iNode ]);
1125 if ( aEids ) delete [] aEids;
1126 if ( aFids ) delete [] aFids;
1127 if ( aEpos ) delete [] aEpos;
1128 if ( aFupos ) delete [] aFupos;
1129 if ( aFvpos ) delete [] aFvpos;
1131 aGroup->CloseOnDisk();
1133 } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
1135 aTopGroup->CloseOnDisk();
1136 } // if ( aFile->ExistInternalObject( meshGrpName ) )
1138 aFile->CloseOnDisk();
1142 //================================================================================
1144 * \brief Remove all SMESH_PreMeshInfo fields from objects w/o data loading
1146 //================================================================================
1148 void SMESH_PreMeshInfo::ForgetAllData() const
1152 if ( _mesh->changePreMeshInfo() != this )
1153 return _mesh->changePreMeshInfo()->ForgetAllData();
1155 // remove SMESH_PreMeshInfo from groups
1156 map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
1157 for ( ; i2group != _mesh->_mapGroups.end(); ++i2group )
1159 if ( SMESH_GroupBase_i* group_i =
1160 SMESH::DownCast<SMESH_GroupBase_i*>( i2group->second ))
1162 SMESH_PreMeshInfo* & info = group_i->changePreMeshInfo();
1167 // remove SMESH_PreMeshInfo from sub-meshes
1168 map<int, SMESH::SMESH_subMesh_ptr>::iterator id2sm = _mesh->_mapSubMeshIor.begin();
1169 for ( ; id2sm != _mesh->_mapSubMeshIor.end(); ++id2sm )
1171 if ( SMESH_subMesh_i* sm_i = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
1173 SMESH_PreMeshInfo* & info = sm_i->changePreMeshInfo();
1178 // remove SMESH_PreMeshInfo from the mesh
1179 _mesh->changePreMeshInfo() = NULL;
1189 // ::SMESH_Mesh& mesh = _mesh->GetImpl();
1191 // // update hyps needing full mesh data restored (issue 20918)
1192 // // map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id2hyp= _mesh->_mapHypo.begin();
1193 // // for ( ; id2hyp != _mesh->_mapHypo.end(); ++id2hyp )
1194 // // if ( SMESH_Hypothesis_i* hyp = SMESH::DownCast<SMESH_Hypothesis_i*>( id2hyp->second ))
1195 // // hyp->UpdateAsMeshesRestored();
1198 // PreMeshInfo_CATCH;
1201 //================================================================================
1203 * \brief remove all SMESH_PreMeshInfo fields from mesh and its child objects w/o data loading
1205 //================================================================================
1207 void SMESH_PreMeshInfo::ForgetAllData( SMESH_Mesh_i* mesh )
1209 if ( mesh && mesh->changePreMeshInfo() )
1210 mesh->changePreMeshInfo()->ForgetAllData();
1213 //================================================================================
1215 * \brief Calls either FullLoadFromFile() or ForgetAllData() depending on preferences
1217 //================================================================================
1219 void SMESH_PreMeshInfo::ForgetOrLoad() const
1221 if ( SMESH_Gen_i::GetSMESHGen()->ToForgetMeshDataOnHypModif() &&
1222 _mesh->HasShapeToMesh())
1228 //================================================================================
1230 * \brief Method of SMESH_IDSource interface
1232 //================================================================================
1234 SMESH::array_of_ElementType* SMESH_PreMeshInfo::GetTypes() const
1236 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
1240 if (NbEdges()) types[nbTypes++] = SMESH::EDGE;
1241 if (NbFaces()) types[nbTypes++] = SMESH::FACE;
1242 if (NbVolumes()) types[nbTypes++] = SMESH::VOLUME;
1243 if (Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
1244 if (NbBalls()) types[nbTypes++] = SMESH::BALL;
1245 types->length( nbTypes );
1247 return types._retn();
1250 //================================================================================
1252 * \brief Method of SMESH_IDSource interface returning nb elements by element type
1254 //================================================================================
1256 SMESH::long_array* SMESH_PreMeshInfo::GetMeshInfo() const
1258 SMESH::long_array_var aRes = new SMESH::long_array();
1259 aRes->length(SMESH::Entity_Last);
1260 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1263 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
1264 aRes[i] = NbEntities((SMDSAbs_EntityType)i);
1265 return aRes._retn();
1268 //================================================================================
1270 * Returns false if GetMeshInfo() returns incorrect information that may
1271 * happen if mesh data is not yet fully loaded from the file of study.
1273 //================================================================================
1275 bool SMESH_PreMeshInfo::IsMeshInfoCorrect() const
1280 //================================================================================
1282 * \brief TEMPORARY method to remove study files on closing study;
1283 * RIGHT WAY: study files are remove automatically when meshes are destroyed
1285 //================================================================================
1287 void SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD(SALOMEDS::SComponent_ptr smeshComp)
1289 SALOMEDS::Study_var study = smeshComp->GetStudy();
1290 if ( theStudyIDToMeshCounter[ (int) study->StudyId() ] > 0 )
1292 SALOMEDS::ChildIterator_wrap itBig = study->NewChildIterator( smeshComp );
1293 for ( ; itBig->More(); itBig->Next() ) {
1294 SALOMEDS::SObject_wrap gotBranch = itBig->Value();
1295 CORBA::Object_var anObject = SMESH_Gen_i::SObjectToObject( gotBranch );
1296 if ( SMESH_Mesh_i* mesh = SMESH::DownCast<SMESH_Mesh_i*>( anObject ))
1298 if ( mesh->changePreMeshInfo() )
1300 mesh->changePreMeshInfo()->ForgetAllData();