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

📄 mitab_mapfile.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }
    }
    else
    {
        /*---------------------------------------------------------
         * Failed positioning input file... CPLError has been called.
         *--------------------------------------------------------*/
        m_nCurObjPtr = m_nCurObjId = m_nCurObjType = -1;
        return -1;
    }

    return 0;
}

/**********************************************************************
 *                   TABMAPFile::UpdateMapHeaderInfo()
 *
 * Update .map header information (counter of objects by type and minimum
 * required version) in light of a new object to be written to the file.
 *
 * Called only by PrepareNewObj() and by the TABCollection class.
 **********************************************************************/
void  TABMAPFile::UpdateMapHeaderInfo(GByte nObjType)
{
    /*-----------------------------------------------------------------
     * Update count of objects by type in the header block
     *----------------------------------------------------------------*/
    if (nObjType == TAB_GEOM_SYMBOL ||
        nObjType == TAB_GEOM_FONTSYMBOL ||
        nObjType == TAB_GEOM_CUSTOMSYMBOL ||
        nObjType == TAB_GEOM_MULTIPOINT ||
        nObjType == TAB_GEOM_V800_MULTIPOINT ||
        nObjType == TAB_GEOM_SYMBOL_C ||
        nObjType == TAB_GEOM_FONTSYMBOL_C ||
        nObjType == TAB_GEOM_CUSTOMSYMBOL_C ||
        nObjType == TAB_GEOM_MULTIPOINT_C ||
        nObjType == TAB_GEOM_V800_MULTIPOINT_C )
    {
        m_poHeader->m_numPointObjects++;
    }
    else if (nObjType == TAB_GEOM_LINE ||
             nObjType == TAB_GEOM_PLINE ||
             nObjType == TAB_GEOM_MULTIPLINE ||
             nObjType == TAB_GEOM_V450_MULTIPLINE ||
             nObjType == TAB_GEOM_V800_MULTIPLINE ||
             nObjType == TAB_GEOM_ARC ||
             nObjType == TAB_GEOM_LINE_C ||
             nObjType == TAB_GEOM_PLINE_C ||
             nObjType == TAB_GEOM_MULTIPLINE_C ||
             nObjType == TAB_GEOM_V450_MULTIPLINE_C ||
             nObjType == TAB_GEOM_V800_MULTIPLINE_C ||
             nObjType == TAB_GEOM_ARC_C)
    {
        m_poHeader->m_numLineObjects++;
    }
    else if (nObjType == TAB_GEOM_REGION ||
             nObjType == TAB_GEOM_V450_REGION ||
             nObjType == TAB_GEOM_V800_REGION ||
             nObjType == TAB_GEOM_RECT ||
             nObjType == TAB_GEOM_ROUNDRECT ||
             nObjType == TAB_GEOM_ELLIPSE ||
             nObjType == TAB_GEOM_REGION_C ||
             nObjType == TAB_GEOM_V450_REGION_C ||
             nObjType == TAB_GEOM_V800_REGION_C ||
             nObjType == TAB_GEOM_RECT_C ||
             nObjType == TAB_GEOM_ROUNDRECT_C ||
             nObjType == TAB_GEOM_ELLIPSE_C)
    {
        m_poHeader->m_numRegionObjects++;
    }
    else if (nObjType == TAB_GEOM_TEXT ||
             nObjType == TAB_GEOM_TEXT_C)
    {
        m_poHeader->m_numTextObjects++;
    }

    /*-----------------------------------------------------------------
     * Check forminimum TAB file version number
     *----------------------------------------------------------------*/
    int nVersion = TAB_GEOM_GET_VERSION(nObjType);

    if (nVersion > m_nMinTABVersion )
    {
        m_nMinTABVersion = nVersion;
    }

}

/**********************************************************************
 *                   TABMAPFile::PrepareNewObj()
 *
 * Get ready to write a new object described by poObjHdr (using the
 * poObjHdr's m_nId (featureId), m_nType and IntMBR members which must 
 * have been set by the caller).
 *
 * Depending on whether "quick spatial index mode" is selected, we either:
 *
 * 1- Walk through the spatial index to find the best place to insert the
 * new object, update the spatial index references, and prepare the object
 * data block to be ready to write the object to it.
 * ... or ...
 * 2- prepare the current object data block to be ready to write the 
 * object to it. If the object block is full then it is inserted in the 
 * spatial index and committed to disk, and a new obj block is created.
 *
 * m_poCurObjBlock will be set to be ready to receive the new object, and
 * a new block will be created if necessary (in which case the current 
 * block contents will be committed to disk, etc.)  The actual ObjHdr
 * data won't be written to m_poCurObjBlock until CommitNewObj() is called. 
 *
 * If this object type uses coordinate blocks, then the coordinate block
 * will be prepared to receive coordinates.
 *
 * This function will also take care of updating the .ID index entry for
 * the new object.
 *
 * Note that object ids are positive and start at 1.
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
{

    m_nCurObjPtr = m_nCurObjId = m_nCurObjType = -1;

    if (m_eAccessMode != TABWrite || 
        m_poIdIndex == NULL || m_poHeader == NULL)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
                 "PrepareNewObj() failed: file not opened for write access.");
        return -1;
    }

    /*-----------------------------------------------------------------
     * For objects with no geometry, we just update the .ID file and return
     *----------------------------------------------------------------*/
    if (poObjHdr->m_nType == TAB_GEOM_NONE)
    {
        m_nCurObjType = poObjHdr->m_nType;
        m_nCurObjId   = poObjHdr->m_nId;
        m_nCurObjPtr  = 0;
        m_poIdIndex->SetObjPtr(m_nCurObjId, 0);

        return 0;
    }

    /*-----------------------------------------------------------------
     * Update count of objects by type in the header block and minimum
     * required version.
     *----------------------------------------------------------------*/
    UpdateMapHeaderInfo(poObjHdr->m_nType);


    /*-----------------------------------------------------------------
     * Depending on the selected spatial index mode, we will either insert
     * new objects via the spatial index (slower write but results in optimal
     * spatial index) or directly in the current ObjBlock (faster write
     * but non-optimal spatial index)
     *----------------------------------------------------------------*/
    if ( !m_bQuickSpatialIndexMode )
    {
        if (PrepareNewObjViaSpatialIndex(poObjHdr) != 0)
            return -1;  /* Error already reported */
    }
    else
    {
        if (PrepareNewObjViaObjBlock(poObjHdr) != 0)
            return -1;  /* Error already reported */
    }

    /*-----------------------------------------------------------------
     * Prepare ObjBlock for this new object.
     * Real data won't be written to the object block until CommitNewObj()
     * is called.
     *----------------------------------------------------------------*/
    m_nCurObjPtr = m_poCurObjBlock->PrepareNewObject(poObjHdr);
    if (m_nCurObjPtr < 0 )
    {
        CPLError(CE_Failure, CPLE_FileIO,
                 "Failed writing object header for feature id %d",
                 poObjHdr->m_nId);
        return -1;
    }

    m_nCurObjType = poObjHdr->m_nType;
    m_nCurObjId   = poObjHdr->m_nId;

    /*-----------------------------------------------------------------
     * Update .ID Index
     *----------------------------------------------------------------*/
    m_poIdIndex->SetObjPtr(m_nCurObjId, m_nCurObjPtr);

    /*-----------------------------------------------------------------
     * Prepare Coords block... 
     * create a new TABMAPCoordBlock if it was not done yet.
     *----------------------------------------------------------------*/
    PrepareCoordBlock(m_nCurObjType, m_poCurObjBlock, &m_poCurCoordBlock);

    if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() == CE_Failure)
        return -1;

    return 0;
}

/**********************************************************************
 *                   TABMAPFile::PrepareNewObjViaSpatialIndex()
 *
 * Used by TABMAPFile::PrepareNewObj() to walk through the spatial index
 * to find the best place to insert the new object, update the spatial 
 * index references, and prepare the object data block to be ready to 
 * write the object to it.
 *
 * This method is used when "quick spatial index mode" is NOT selected,
 * i.e. when we want to produce a file with an optimal spatial index
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
{
    int nObjSize;
    GInt32 nObjBlockForInsert = -1;

    /*-----------------------------------------------------------------
     * Create spatial index if we don't have one yet.
     * We do not create the index and object data blocks in the open() 
     * call because files that contained only "NONE" geometries ended up 
     * with empty object and spatial index blocks.
     *----------------------------------------------------------------*/
    if (m_poSpIndex == NULL)
    {
        // Spatial Index not created yet...
        m_poSpIndex = new TABMAPIndexBlock(m_eAccessMode);

        m_poSpIndex->InitNewBlock(m_fp, 512, 
                                  m_oBlockManager.AllocNewBlock());
        m_poSpIndex->SetMAPBlockManagerRef(&m_oBlockManager);

        m_poHeader->m_nFirstIndexBlock = m_poSpIndex->GetNodeBlockPtr();

        /* We'll also need to create an object data block (later) */
        nObjBlockForInsert = -1;

        CPLAssert(m_poCurObjBlock == NULL);
    }
    else
    /*-----------------------------------------------------------------
     * Search the spatial index to find the best place to insert this 
     * new object. 
     *----------------------------------------------------------------*/
    {
        nObjBlockForInsert=m_poSpIndex->ChooseLeafForInsert(poObjHdr->m_nMinX, 
                                                            poObjHdr->m_nMinY,
                                                            poObjHdr->m_nMaxX,
                                                            poObjHdr->m_nMaxY);
        if (nObjBlockForInsert == -1)
        {
            /* ChooseLeafForInsert() should not fail unless file is corrupt*/
            CPLError(CE_Failure, CPLE_AssertionFailed,
                     "ChooseLeafForInsert() Failed?!?!");
            return -1;
        }
    }


    if (nObjBlockForInsert == -1)
    {
        /*-------------------------------------------------------------
         * Create a new object data block from scratch
         *------------------------------------------------------------*/
        m_poCurObjBlock = new TABMAPObjectBlock(TABReadWrite);

        int nBlockOffset = m_oBlockManager.AllocNewBlock();

        m_poCurObjBlock->InitNewBlock(m_fp, 512, nBlockOffset);

        /*-------------------------------------------------------------
         * Insert new object block in index, based on MBR of poObjHdr
         *------------------------------------------------------------*/
        if (m_poSpIndex->AddEntry(poObjHdr->m_nMinX, 
                                  poObjHdr->m_nMinY,
                                  poObjHdr->m_nMaxX,
                                  poObjHdr->m_nMaxY,
                                  m_poCurObjBlock->GetStartAddress()) != 0)
            return -1;

        m_poHeader->m_nMaxSpIndexDepth = MAX(m_poHeader->m_nMaxSpIndexDepth,
                                             m_poSpIndex->GetCurMaxDepth()+1);
    }
    else
    {
        /*-------------------------------------------------------------
         * Load existing object and Coord blocks, unless we've already 
         * got the right object block in memory
         *------------------------------------------------------------*/
        if (m_poCurObjBlock && 
            m_poCurObjBlock->GetStartAddress() != nObjBlockForInsert)
        {
            /* Got a block in memory but it's not the right one, flush it */
            if (CommitObjAndCoordBlocks(TRUE) != 0 )
                return -1;
        }

        if (m_poCurObjBlock == NULL)
        {
            if (LoadObjAndCoordBlocks(nObjBlockForInsert) != 0)
                return -1;

            // The ObjBlock doesn't know its MBR. Get the value from the 
            // index and set it
            GInt32 nMinX, nMinY, nMaxX, nMaxY;
            m_poSpIndex->GetCurLeafEntryMBR(m_poCurObjBlock->GetStartAddress(),
                                            nMinX, nMinY, nMaxX, nMaxY);
            m_poCurObjBlock->SetMBR(nMinX, nMinY, nMaxX, nMaxY);
        }
    }

    /*-----------------------------------------------------------------
     * Fetch new object size, make sure there is enough room in obj. 
     * block for new object, update spatial index and split if necessary.
     *----------------------------------------------------------------*/
    nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
    if (m_poCurObjBlock->GetNumUnusedBytes() >= nObjSize )
    {
        /*-------------------------------------------------------------
         * New object fits in current block, just update the spatial index
         *------------------------------------------------------------*/
        GInt32 nMinX, nMinY, nMaxX, nMaxY;
        m_poCurObjBlock->GetMBR(nMinX, nMinY, nMaxX, nMaxY);

        /* Need to calculate the enlarged MBR that includes new object */
        nMinX = MIN(nMinX, poObjHdr->m_nMinX);
        nMinY = MIN(nMinY, poObjHdr->m_nMinY);
        nMaxX = MAX(nMaxX, poObjHdr->m_nMaxX);
        nMaxY = MAX(nMaxY, poObjHdr->m_nMaxY);

        if (m_poSpIndex->UpdateLeafEntry(m_poCurObjBlock->GetStartAddress(),
                                         nMinX, nMinY, nMaxX, nMaxY) != 0)
            return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -