⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mitab_tabseamless.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            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 + -