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

📄 tabmapindexblock.cpp

📁 linux下一款GIS程序源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        return m_poCurChild->GetCurMaxDepth() + 1;    return 1;  /* No current child... this node counts for one. */}/********************************************************************** *                   TABMAPIndexBlock::GetMBR() * * Return the MBR for the current block. **********************************************************************/void TABMAPIndexBlock::GetMBR(UGKInt32 &nXMin, UGKInt32 &nYMin,                                      UGKInt32 &nXMax, UGKInt32 &nYMax){    nXMin = m_nMinX;    nYMin = m_nMinY;    nXMax = m_nMaxX;    nYMax = m_nMaxY; }/********************************************************************** *                   TABMAPIndexBlock::InsertEntry() * * Add a new entry to this index block.  It is assumed that there is at * least one free slot available, so if the block has to be split then it * should have been done prior to calling this function. * * Returns 0 on success, -1 on error. **********************************************************************/int     TABMAPIndexBlock::InsertEntry(UGKInt32 nXMin, UGKInt32 nYMin,                                      UGKInt32 nXMax, UGKInt32 nYMax,                                      UGKInt32 nBlockPtr){    if (m_eAccess != TABWrite && m_eAccess != TABReadWrite)    {        UGKError(ET_Failure, UGKErr_AssertionFailed,                "Failed adding index entry: File not opened for write access.");        return -1;    }    if (GetNumFreeEntries() < 1)    {        UGKError(ET_Failure, UGKErr_AssertionFailed,                  "Current Block Index is full, cannot add new entry.");        return -1;    }    /*-----------------------------------------------------------------     * Update count of entries and store new entry.     *----------------------------------------------------------------*/    m_numEntries++;    assert(m_numEntries <= TAB_MAX_ENTRIES_INDEX_BLOCK);    m_asEntries[m_numEntries-1].XMin = nXMin;    m_asEntries[m_numEntries-1].YMin = nYMin;    m_asEntries[m_numEntries-1].XMax = nXMax;    m_asEntries[m_numEntries-1].YMax = nYMax;    m_asEntries[m_numEntries-1].nBlockPtr = nBlockPtr;    return 0;}/********************************************************************** *                   TABMAPIndexBlock::AddEntry() * 递归 * Recursively search the tree until we encounter the best leaf to * contain the specified object MBR and add the new entry to it. * * In the even that the selected leaf node would be full, then it will be * split and this split can propagate up to its parent, etc. *                           * If bAddInThisNodeOnly=TRUE, then the entry is added only locally and * we do not try to update the child node.  This is used when the parent  * of a node that is being splitted has to be updated. * * Returns 0 on success, -1 on error. **********************************************************************/int     TABMAPIndexBlock::AddEntry(UGKInt32 nXMin, UGKInt32 nYMin,                                   UGKInt32 nXMax, UGKInt32 nYMax,                                   UGKInt32 nBlockPtr,                                   UGKBool bAddInThisNodeOnly /*=FALSE*/){    int i;    UGKBool bFound = FALSE;    if (m_eAccess != TABWrite && m_eAccess != TABReadWrite)    {        UGKError(ET_Failure, UGKErr_AssertionFailed,                "Failed adding index entry: File not opened for write access.");        return -1;    }    /*-----------------------------------------------------------------     * Update MBR now... even if we're going to split current node later.     *----------------------------------------------------------------*/    if (nXMin < m_nMinX)        m_nMinX = nXMin;    if (nXMax > m_nMaxX)        m_nMaxX = nXMax;        if (nYMin < m_nMinY)        m_nMinY = nYMin;    if (nYMax > m_nMaxY)        m_nMaxY = nYMax;    /*-----------------------------------------------------------------     * Look for the best candidate to contain the new entry     * __TODO__ For now we'll just look for the first entry that can      *          contain the MBR, but we could probably have a better     *          search criteria to optimize the resulting tree     *----------------------------------------------------------------*/    /*-----------------------------------------------------------------     * If bAddInThisNodeOnly=TRUE then we add the entry only locally     * and do not need to look for the proper leaf to insert it.     *----------------------------------------------------------------*/    if (bAddInThisNodeOnly)        bFound = TRUE;    /*-----------------------------------------------------------------     * First check if current child could be a valid candidate.     *----------------------------------------------------------------*/    if (!bFound &&        m_poCurChild && (m_asEntries[m_nCurChildIndex].XMin <= nXMin &&                         m_asEntries[m_nCurChildIndex].XMax >= nXMax &&                         m_asEntries[m_nCurChildIndex].YMin <= nYMin &&                         m_asEntries[m_nCurChildIndex].YMax >= nYMax ) )    {        bFound = TRUE;    }    /*-----------------------------------------------------------------     * Scan all entries to find a valid candidate     * We look for the entry whose center is the closest to the center     * of the object to add.     *----------------------------------------------------------------*/    if (!bFound)    {        int nObjCenterX = (nXMin + nXMax)/2;        int nObjCenterY = (nYMin + nYMax)/2;        // Make sure blocks currently in memory are written to disk.		//        if (m_poCurChild)        {            m_poCurChild->CommitToFile();            delete m_poCurChild;  //--ZGQ 这里有点问题,为什么要删除?            m_poCurChild = NULL; //为什么要置NULL			//因为每个TABMAPIndexBlock对象只有一个m_poCurChild --05/12/30 ADD			//下面会加载另外一个TABMAPIndexBlock块作为m_poCurChild                               m_nCurChildIndex = -1;        }        // Look for entry whose center is closest to center of new object        int nBestCandidate = -1;        int nMinDist = 2000000000;        for(i=0; i<m_numEntries; i++)        {            int nX = (m_asEntries[i].XMin + m_asEntries[i].XMax)/2;            int nY = (m_asEntries[i].YMin + m_asEntries[i].YMax)/2;            int nDist = (nX-nObjCenterX)*(nX-nObjCenterX) +                             (nY-nObjCenterY)*(nY-nObjCenterY);            if (nBestCandidate==-1 || nDist < nMinDist)            {                nBestCandidate = i;                nMinDist = nDist;            }        }                if (nBestCandidate != -1)        {            // Try to load corresponding child... if it fails then we are            // likely in a leaf node, so we'll add the new entry in the current            // node.            TABRawBinBlock *poBlock = NULL;            // Prevent error message if referred block not committed yet.            //CPLPushErrorHandler(CPLQuietErrorHandler);            if ((poBlock = TABCreateMAPBlockFromFile(m_fp,                                        m_asEntries[nBestCandidate].nBlockPtr,                                       512, TRUE, TABReadWrite)) &&                poBlock->GetBlockClass() == TABMAP_INDEX_BLOCK)            {                m_poCurChild = (TABMAPIndexBlock*)poBlock;                poBlock = NULL;                m_nCurChildIndex = nBestCandidate;                m_poCurChild->SetParentRef(this);                m_poCurChild->SetMAPBlockManagerRef(m_poBlockManagerRef);                bFound = TRUE;            }                            if (poBlock)                delete poBlock;                        //CPLPopErrorHandler();            UGKErrorReset();        }    }    if (bFound && !bAddInThisNodeOnly)    {        /*-------------------------------------------------------------         * Found a child leaf... pass the call to it.         *------------------------------------------------------------*/        if (m_poCurChild->AddEntry(nXMin, nYMin, nXMax, nYMax, nBlockPtr) != 0)            return -1;    }    else    {        /*-------------------------------------------------------------         * Found no child to store new object... we're likely at the leaf         * level so we'll store new object in current node         *------------------------------------------------------------*/        /*-------------------------------------------------------------         * First thing to do is make sure that there is room for a new         * entry in this node, and to split it if necessary.         *------------------------------------------------------------*/        if (GetNumFreeEntries() < 1)        {            if (m_poParentRef == NULL)            {                /*-----------------------------------------------------                 * Splitting the root node adds one level to the tree, so                 * after splitting we just redirect the call to the new                 * child that's just been created.                 *----------------------------------------------------*/                if (SplitRootNode((nXMin+nXMax)/2, (nYMin+nYMax)/2) != 0)                    return -1;  // Error happened and has already been reported                assert(m_poCurChild);                return m_poCurChild->AddEntry(nXMin, nYMin, nXMax, nYMax,                                              nBlockPtr, TRUE);            }            else            {                /*-----------------------------------------------------                 * Splitting a regular node                 *----------------------------------------------------*/                if (SplitNode((nXMin+nXMax)/2, (nYMin+nYMax)/2) != 0)                    return -1;             }        }        if (InsertEntry(nXMin, nYMin, nXMax, nYMax, nBlockPtr) != 0)            return -1;    }    /*-----------------------------------------------------------------     * Update current node MBR and the reference to it in our parent.     *----------------------------------------------------------------*/    RecomputeMBR();    return 0;}/********************************************************************** *                   TABMAPIndexBlock::SplitNode() * * Split current Node, update the references in the parent node, etc. * Note that Root Nodes cannot be split using this method... SplitRootNode() * should be used instead. * * nNewEntryX, nNewEntryY are the coord. of the center of the new entry that  * will be added after the split.  The split is done so that the current * node will be the one in which the new object should be stored. * * Returns 0 on success, -1 on error. **********************************************************************/int     TABMAPIndexBlock::SplitNode(int nNewEntryX, int nNewEntryY){    int nSrcEntries = m_numEntries;    int nWidth, nHeight, nCenterX1, nCenterY1, nCenterX2, nCenterY2;    assert(m_poBlockManagerRef);    /*-----------------------------------------------------------------     * Create a 2nd node, and assign both nodes a MBR that is half     * of the biggest dimension (width or height) of the current node's MBR     *     * We also want to keep this node's current child in here.     * Since splitting happens only during an addentry() operation and      * then both the current child and nNewEntryX/Y should fit in the same     * area.     *----------------------------------------------------------------*/    TABMAPIndexBlock *poNewNode = new TABMAPIndexBlock(m_eAccess);    if (poNewNode->InitNewBlock(m_fp, 512,                                 m_poBlockManagerRef->AllocNewBlock()) != 0)    {        return -1;    }    poNewNode->SetMAPBlockManagerRef(m_poBlockManagerRef);    nWidth = ABS(m_nMaxX - m_nMinX);    nHeight = ABS(m_nMaxY - m_nMinY);    if (nWidth > nHeight)    {        // Split node horizontally        nCenterY1 = nCenterY2 = m_nMinY + nHeight/2;        if (nNewEntryX < (m_nMinX + m_nMaxX)/2)        {            nCenterX1 = m_nMinX + nWidth/4;            nCenterX2 = m_nMaxX - nWidth/4;        }        else        {            nCenterX2 = m_nMinX + nWidth/4;            nCenterX1 = m_nMaxX - nWidth/4;        }    }    else    {        // Split node vertically        nCenterX1 = nCenterX2 = m_nMinX + nWidth/2;        if (nNewEntryY < (m_nMinY + m_nMaxY)/2)        {            nCenterY1 = m_nMinY + nHeight/4;            nCenterY2 = m_nMaxY - nHeight/4;        }        else        {            nCenterY2 = m_nMinY + nHeight/4;            nCenterY1 = m_nMaxY - nHeight/4;        }    }

⌨️ 快捷键说明

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