📄 mitab_tabseamless.cpp
字号:
CPLError(CE_Failure, CPLE_NotSupported,
"Open Failed: The current implementation is limited "
"to 2047 base tables. The seamless file '%s' contains "
"%d tables and cannot be opened.",
m_pszFname, m_poIndexTable->GetFeatureCount(FALSE));
Close();
return -1;
}
/*-----------------------------------------------------------------
* We need to open the first table to get its FeatureDefn
*----------------------------------------------------------------*/
if (OpenBaseTable(-1, bTestOpenNoError) != 0 )
{
// Open Failed... an error has already been reported, just return.
if (bTestOpenNoError)
CPLErrorReset();
Close();
return -1;
}
CPLAssert(m_poCurBaseTable);
m_poFeatureDefnRef = m_poCurBaseTable->GetLayerDefn();
m_poFeatureDefnRef->Reference();
return 0;
}
/**********************************************************************
* TABSeamless::Close()
*
* Close current file, and release all memory used.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABSeamless::Close()
{
if (m_poIndexTable)
delete m_poIndexTable; // Automatically closes.
m_poIndexTable = NULL;
if (m_poFeatureDefnRef && m_poFeatureDefnRef->Dereference() == 0)
delete m_poFeatureDefnRef;
m_poFeatureDefnRef = NULL;
if (m_poCurFeature)
delete m_poCurFeature;
m_poCurFeature = NULL;
m_nCurFeatureId = -1;
CPLFree(m_pszFname);
m_pszFname = NULL;
CPLFree(m_pszPath);
m_pszPath = NULL;
m_nTableNameField = -1;
m_nCurBaseTableId = -1;
if (m_poCurBaseTable)
delete m_poCurBaseTable;
m_poCurBaseTable = NULL;
return 0;
}
/**********************************************************************
* TABSeamless::OpenBaseTable()
*
* Open the base table for specified IndexFeature.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABSeamless::OpenBaseTable(TABFeature *poIndexFeature,
GBool bTestOpenNoError /*=FALSE*/)
{
CPLAssert(poIndexFeature);
/*-----------------------------------------------------------------
* Fetch table id. We actually use the index feature's ids as the
* base table ids.
*----------------------------------------------------------------*/
int nTableId = poIndexFeature->GetFID();
if (m_nCurBaseTableId == nTableId && m_poCurBaseTable != NULL)
{
// The right table is already opened. Not much to do!
m_poCurBaseTable->ResetReading();
return 0;
}
// Close current base table
if (m_poCurBaseTable)
delete m_poCurBaseTable;
m_nCurBaseTableId = -1;
m_bEOF = FALSE;
/*-----------------------------------------------------------------
* Build full path to the table and open it.
* __TODO__ For now we assume that all table filename paths are relative
* but we may have to deal with absolute filenames as well.
*----------------------------------------------------------------*/
const char *pszName = poIndexFeature->GetFieldAsString(m_nTableNameField);
char *pszFname = CPLStrdup(CPLSPrintf("%s%s", m_pszPath, pszName));
#ifndef _WIN32
// On Unix, replace any '\\' in path with '/'
char *pszPtr = pszFname;
while((pszPtr = strchr(pszPtr, '\\')) != NULL)
{
*pszPtr = '/';
pszPtr++;
}
#endif
m_poCurBaseTable = new TABFile;
if (m_poCurBaseTable->Open(pszFname, "rb", bTestOpenNoError) != 0)
{
// Open Failed... an error has already been reported, just return.
if (bTestOpenNoError)
CPLErrorReset();
delete m_poCurBaseTable;
m_poCurBaseTable = NULL;
CPLFree(pszFname);
return -1;
}
// Set the spatial filter to the new table
if( m_poFilterGeom != NULL && m_poCurBaseTable )
{
m_poCurBaseTable->SetSpatialFilter( m_poFilterGeom );
}
m_nCurBaseTableId = nTableId;
CPLFree(pszFname);
return 0;
}
/**********************************************************************
* TABSeamless::OpenBaseTable()
*
* Open the base table for specified IndexFeature.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABSeamless::OpenBaseTable(int nTableId, GBool bTestOpenNoError /*=FALSE*/)
{
if (nTableId == -1)
{
// Open first table from dataset
m_poIndexTable->ResetReading();
if (OpenNextBaseTable(bTestOpenNoError) != 0)
{
// Open Failed... an error has already been reported.
if (bTestOpenNoError)
CPLErrorReset();
return -1;
}
}
else if (nTableId == m_nCurBaseTableId && m_poCurBaseTable != NULL)
{
// The right table is already opened. Not much to do!
m_poCurBaseTable->ResetReading();
return 0;
}
else
{
TABFeature *poIndexFeature = m_poIndexTable->GetFeatureRef(nTableId);
if (poIndexFeature)
{
if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0)
{
// Open Failed... an error has already been reported.
if (bTestOpenNoError)
CPLErrorReset();
return -1;
}
}
}
return 0;
}
/**********************************************************************
* TABSeamless::OpenNextBaseTable()
*
* Open the next base table in the dataset, using GetNextFeature() so that
* the spatial filter is respected.
*
* m_bEOF will be set if there are no more base tables to read.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABSeamless::OpenNextBaseTable(GBool bTestOpenNoError /*=FALSE*/)
{
CPLAssert(m_poIndexTable);
TABFeature *poIndexFeature = (TABFeature*)m_poIndexTable->GetNextFeature();
if (poIndexFeature)
{
if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0)
{
// Open Failed... an error has already been reported.
if (bTestOpenNoError)
CPLErrorReset();
delete poIndexFeature;
return -1;
}
delete poIndexFeature;
m_bEOF = FALSE;
}
else
{
// Reached EOF
m_bEOF = TRUE;
}
return 0;
}
/**********************************************************************
* TABSeamless::EncodeFeatureId()
*
* Combine the table id + feature id into a single feature id that should
* be unique amongst all base tables in this seamless dataset.
*
* We reserve some bits in the feature id for the table id based on the
* number of features in the index table. This reduces the available range
* of feature ids for each base table... for instance, if the index contains
* 65000 entries, then each base table will be limited to 65535 features.
*
* If the number of features in a base table exceeds the number of bits
* available (e.g. 65535 inthe above example) then the feature ids will
* wrap for this table and thus it will be impossible to access some of
* the features unless the caller uses only calls to GetNextFeature() and
* avoids calls to GetFeatureRef().
**********************************************************************/
int TABSeamless::EncodeFeatureId(int nTableId, int nBaseFeatureId)
{
if (nTableId == -1 || nBaseFeatureId == -1)
return -1;
/*-----------------------------------------------------------------
* __TODO__ For now we hardcode the bitmasks to be 12 bits for tableid
* and 20 bits for base feature id, but we should really
* base the numbers of bits on the number of features in
* the index table.
*----------------------------------------------------------------*/
return (nTableId*0x00100000 + nBaseFeatureId);
}
int TABSeamless::ExtractBaseTableId(int nEncodedFeatureId)
{
if (nEncodedFeatureId == -1)
return -1;
return (nEncodedFeatureId/0x00100000);
}
int TABSeamless::ExtractBaseFeatureId(int nEncodedFeatureId)
{
if (nEncodedFeatureId == -1)
return -1;
return (nEncodedFeatureId & 0x000fffff);
}
/**********************************************************************
* TABSeamless::GetNextFeatureId()
*
* Returns feature id that follows nPrevId, or -1 if it is the
* last feature id. Pass nPrevId=-1 to fetch the first valid feature id.
**********************************************************************/
int TABSeamless::GetNextFeatureId(int nPrevId)
{
if (m_poIndexTable == NULL)
return -1; // File is not opened yet
if (nPrevId == -1 || m_nCurBaseTableId != ExtractBaseTableId(nPrevId))
{
if (OpenBaseTable(ExtractBaseTableId(nPrevId)) != 0)
return -1;
}
int nId = ExtractBaseFeatureId(nPrevId);
do
{
nId = m_poCurBaseTable->GetNextFeatureId(nId);
if (nId != -1)
return EncodeFeatureId(m_nCurBaseTableId, nId); // Found one!
else
OpenNextBaseTable(); // Skip to next tile and loop again
} while (nId == -1 && !m_bEOF && m_poCurBaseTable);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -