📄 mitab_mapfile.cpp
字号:
/*----------------------------------------------------------------- * Make sure all previous calls succeded. *----------------------------------------------------------------*/ if (CPLGetLastErrorNo() != 0) { // Open Failed... an error has already been reported Close(); return -1; } return 0;}/********************************************************************** * TABMAPFile::Close() * * Close current file, and release all memory used. * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::Close(){ // Check if file is opened... it is possible to have a fake header // without an actual file attached to it. if (m_fp == NULL && m_poHeader == NULL) return 0; /*---------------------------------------------------------------- * Write access: commit latest changes to the file. *---------------------------------------------------------------*/ if (m_eAccessMode == TABWrite) { // Start by committing current object and coord blocks // Nothing happens if none has been created yet. CommitObjBlock(FALSE); // Write the drawing tools definitions now. CommitDrawingTools(); // Commit spatial index blocks CommitSpatialIndex(); // __TODO__ We probably need to update some header fields first. if (m_poHeader) { // OK, with V450 files, objects are not limited to 32k nodes // any more, and this means that m_nMaxCoordBufSize can become // huge, and actually more huge than can be held in memory. // MapInfo counts m_nMaxCoordBufSize=0 for V450 objects, but // until this is cleanly implented, we will just prevent // m_nMaxCoordBufSizefrom going beyond 512k in V450 files. if (m_nMinTABVersion >= 450) { m_poHeader->m_nMaxCoordBufSize = MIN(m_poHeader->m_nMaxCoordBufSize, 512*1024); } m_poHeader->CommitToFile(); } } // Check for overflow of internal coordinates and produce a warning // if that happened... if (m_poHeader && m_poHeader->m_bIntBoundsOverflow) { double dBoundsMinX, dBoundsMinY, dBoundsMaxX, dBoundsMaxY; Int2Coordsys(-1000000000, -1000000000, dBoundsMinX, dBoundsMinY); Int2Coordsys(1000000000, 1000000000, dBoundsMaxX, dBoundsMaxY); CPLError(CE_Warning, TAB_WarningBoundsOverflow, "Some objects were written outside of the file's " "predefined bounds.\n" "These objects may have invalid coordinates when the file " "is reopened.\n" "Predefined bounds: (%.15g,%.15g)-(%.15g,%.15g)\n", dBoundsMinX, dBoundsMinY, dBoundsMaxX, dBoundsMaxY ); } // Delete all structures if (m_poHeader) delete m_poHeader; m_poHeader = NULL; if (m_poIdIndex) { m_poIdIndex->Close(); delete m_poIdIndex; m_poIdIndex = NULL; } if (m_poCurObjBlock) { delete m_poCurObjBlock; m_poCurObjBlock = NULL; m_nCurObjPtr = -1; m_nCurObjType = -1; m_nCurObjId = -1; } if (m_poCurCoordBlock) { delete m_poCurCoordBlock; m_poCurCoordBlock = NULL; } if (m_poSpIndex) { delete m_poSpIndex; m_poSpIndex = NULL; m_poSpIndexLeaf = NULL; } if (m_poToolDefTable) { delete m_poToolDefTable; m_poToolDefTable = NULL; } // Close file if (m_fp) VSIFClose(m_fp); m_fp = NULL; CPLFree(m_pszFname); m_pszFname = NULL; return 0;}/************************************************************************//* PushBlock() *//* *//* Install a new block (object or spatial) as being current - *//* whatever that means. This method is only intended to ever *//* be called from LoadNextMatchingObjectBlock(). *//************************************************************************/TABRawBinBlock *TABMAPFile::PushBlock( int nFileOffset ){ TABRawBinBlock *poBlock; poBlock = GetIndexObjectBlock( nFileOffset ); if( poBlock == NULL ) return NULL; if( poBlock->GetBlockType() == TABMAP_INDEX_BLOCK ) { TABMAPIndexBlock *poIndex = (TABMAPIndexBlock *) poBlock; if( m_poSpIndexLeaf == NULL ) { m_poSpIndexLeaf = m_poSpIndex = poIndex; } else { CPLAssert( m_poSpIndexLeaf->GetEntry( m_poSpIndexLeaf->GetCurChildIndex())->nBlockPtr == nFileOffset ); m_poSpIndexLeaf->SetCurChildRef( poIndex, m_poSpIndexLeaf->GetCurChildIndex() ); poIndex->SetParentRef( m_poSpIndexLeaf ); m_poSpIndexLeaf = poIndex; } } else { CPLAssert( poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK ); if( m_poCurObjBlock != NULL ) delete m_poCurObjBlock; m_poCurObjBlock = (TABMAPObjectBlock *) poBlock; m_nCurObjPtr = nFileOffset; m_nCurObjType = 0; m_nCurObjId = -1; } return poBlock;}/************************************************************************//* LoadNextMatchingObjectBlock() *//* *//* Advance through the spatial indices till the next object *//* block is loaded that matching the spatial query extents. *//************************************************************************/int TABMAPFile::LoadNextMatchingObjectBlock( int bFirstObject ){ // If we are just starting, verify the stack is empty. if( bFirstObject ) { CPLAssert( m_poSpIndex == NULL && m_poSpIndexLeaf == NULL ); if( PushBlock( m_poHeader->m_nFirstIndexBlock ) == NULL ) return FALSE; if( m_poSpIndex == NULL ) { CPLAssert( m_poCurObjBlock != NULL ); return TRUE; } } while( m_poSpIndexLeaf != NULL ) { int iEntry = m_poSpIndexLeaf->GetCurChildIndex(); if( iEntry >= m_poSpIndexLeaf->GetNumEntries()-1 ) { TABMAPIndexBlock *poParent = m_poSpIndexLeaf->GetParentRef(); delete m_poSpIndexLeaf; m_poSpIndexLeaf = poParent; if( poParent != NULL ) { poParent->SetCurChildRef( NULL, poParent->GetCurChildIndex() ); } else { m_poSpIndex = NULL; } continue; } m_poSpIndexLeaf->SetCurChildRef( NULL, ++iEntry ); TABMAPIndexEntry *psEntry = m_poSpIndexLeaf->GetEntry( iEntry ); TABRawBinBlock *poBlock; if( psEntry->XMax < m_XMinFilter || psEntry->YMax < m_YMinFilter || psEntry->XMin > m_XMaxFilter || psEntry->YMin > m_YMaxFilter ) continue; poBlock = PushBlock( psEntry->nBlockPtr ); if( poBlock == NULL ) return FALSE; else if( poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK ) return TRUE; else /* continue processing new index block */; } return m_poSpIndexLeaf != NULL;}/************************************************************************//* ResetReading() *//* *//* Ensure that any resources related to a spatial traversal of *//* the file are recovered, and the state reinitialized to the *//* initial conditions. *//************************************************************************/void TABMAPFile::ResetReading(){ if (m_poSpIndex && m_eAccessMode == TABRead ) { delete m_poSpIndex; m_poSpIndex = NULL; m_poSpIndexLeaf = NULL; }}/************************************************************************//* GetNextFeatureId() *//* *//* Fetch the next feature id based on a traversal of the *//* spatial index. *//************************************************************************/int TABMAPFile::GetNextFeatureId( int nPrevId ){/* -------------------------------------------------------------------- *//* m_fp is NULL when all geometry are NONE and/or there's *//* no .map file and/or there's no spatial indexes *//* -------------------------------------------------------------------- */ if( m_fp == NULL ) return -1; if( nPrevId == 0 ) nPrevId = -1;/* -------------------------------------------------------------------- *//* This should always be true if we are being called properly. *//* -------------------------------------------------------------------- */ if( nPrevId != -1 && m_nCurObjId != nPrevId ) { CPLError( CE_Failure, CPLE_AppDefined, "TABMAPFile::GetNextFeatureId(%d) called out of sequence.", nPrevId ); return -1; } CPLAssert( nPrevId == -1 || m_poCurObjBlock != NULL );/* -------------------------------------------------------------------- *//* Ensure things are initialized properly if this is a request *//* for the first feature. *//* -------------------------------------------------------------------- */ if( nPrevId == -1 ) { m_nCurObjId = -1; }/* -------------------------------------------------------------------- *//* Try to advance to the next object in the current object *//* block. *//* -------------------------------------------------------------------- */ if( nPrevId == -1 || m_poCurObjBlock->AdvanceToNextObject(m_poHeader) == -1 ) { // If not, try to advance to the next object block, and get // first object from it. Note that some object blocks actually // have no objects, so we may have to advance to additional // object blocks till we find a non-empty one. GBool bFirstCall = (nPrevId == -1); do { if( !LoadNextMatchingObjectBlock( bFirstCall ) ) return -1; bFirstCall = FALSE; } while( m_poCurObjBlock->AdvanceToNextObject(m_poHeader) == -1 ); } m_nCurObjType = m_poCurObjBlock->GetCurObjectType(); m_nCurObjId = m_poCurObjBlock->GetCurObjectId(); m_nCurObjPtr = m_poCurObjBlock->GetStartAddress() + m_poCurObjBlock->GetCurObjectOffset(); CPLAssert( m_nCurObjId != -1 ); return m_nCurObjId;}/********************************************************************** * TABMAPFile::Int2Coordsys() * * Convert from long integer (internal) to coordinates system units * as defined in the file's coordsys clause. * * Note that the false easting/northing and the conversion factor from * datum to coordsys units are not included in the calculation. * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY){ if (m_poHeader == NULL) return -1; return m_poHeader->Int2Coordsys(nX, nY, dX, dY);}/********************************************************************** * TABMAPFile::Coordsys2Int() *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -