📄 tabmapindexblock.cpp
字号:
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 + -