📄 mitab_mapfile.cpp
字号:
* can be used to return only NONE geometries.
*----------------------------------------------------------------*/
m_fp = NULL;
m_nCurObjType = TAB_GEOM_NONE;
/* Create a false header block that will return default
* values for projection and coordsys conversion stuff...
*/
m_poHeader = new TABMAPHeaderBlock(m_eAccessMode);
m_poHeader->InitNewBlock(NULL, 512, 0 );
return 1;
}
else
{
CPLError(CE_Failure, CPLE_FileIO,
"Open() failed for %s", pszFname);
return -1;
}
/*-----------------------------------------------------------------
* File appears to be valid... set the various class members
*----------------------------------------------------------------*/
m_fp = fp;
m_poHeader = (TABMAPHeaderBlock*)poBlock;
m_pszFname = CPLStrdup(pszFname);
/*-----------------------------------------------------------------
* Create a TABMAPObjectBlock, in READ mode only.
*
* In WRITE mode, the object block will be created only when needed.
* We do not create the object block in the open() call because
* files that contained only "NONE" geometries ended up with empty
* object and spatial index blocks.
*----------------------------------------------------------------*/
if (m_eAccessMode == TABRead)
{
m_poCurObjBlock = new TABMAPObjectBlock(m_eAccessMode);
m_poCurObjBlock->InitNewBlock(m_fp, 512);
}
else
{
m_poCurObjBlock = NULL;
}
/*-----------------------------------------------------------------
* Open associated .ID (object id index) file
*----------------------------------------------------------------*/
m_poIdIndex = new TABIDFile;
if (m_poIdIndex->Open(pszFname, pszAccess) != 0)
{
// Failed... an error has already been reported
Close();
return -1;
}
/*-----------------------------------------------------------------
* Default Coord filter is the MBR of the whole file
* This is currently unused but could eventually be used to handle
* spatial filters more efficiently.
*----------------------------------------------------------------*/
if (m_eAccessMode == TABRead)
{
ResetCoordFilter();
}
/*-----------------------------------------------------------------
* We could scan a file through its quad tree index... but we don't!
*
* In read mode, we just ignore the spatial index.
*
* In write mode the index is created and maintained as new object
* blocks are added inside CommitObjBlock().
*----------------------------------------------------------------*/
m_poSpIndex = NULL;
/*-----------------------------------------------------------------
* Initialization of the Drawing Tools table will be done automatically
* as Read/Write calls are done later.
*----------------------------------------------------------------*/
m_poToolDefTable = NULL;
/*-----------------------------------------------------------------
* 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.
CommitObjAndCoordBlocks(FALSE);
// Write the drawing tools definitions now.
CommitDrawingTools();
// Commit spatial index blocks
CommitSpatialIndex();
// Update header fields and commit
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);
}
// Write Ref to beginning of the chain of garbage blocks
m_poHeader->m_nFirstGarbageBlock =
m_oBlockManager.GetFirstGarbageBlock();
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;
}
/**********************************************************************
* TABMAPFile::SetQuickSpatialIndexMode()
*
* Select "quick spatial index mode".
*
* The default behavior of MITAB is to generate an optimized spatial index,
* but this results in slower write speed.
*
* Applications that want faster write speed and do not care
* about the performance of spatial queries on the resulting file can
* use SetQuickSpatialIndexMode() to require the creation of a non-optimal
* spatial index (actually emulating the type of spatial index produced
* by MITAB before version 1.6.0). In this mode writing files can be
* about 5 times faster, but spatial queries can be up to 30 times slower.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABMAPFile::SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode/*=TRUE*/)
{
if (m_eAccessMode != TABWrite)
{
CPLError(CE_Failure, CPLE_AssertionFailed,
"SetQuickSpatialIndexMode() failed: file not opened for write access.");
return -1;
}
if (m_poCurObjBlock != NULL || m_poSpIndex != NULL)
{
CPLError(CE_Failure, CPLE_AssertionFailed,
"SetQuickSpatialIndexMode() must be called before writing the first object.");
return -1;
}
m_bQuickSpatialIndexMode = bQuickSpatialIndexMode;
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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -