📄 mitab_mapindexblock.cpp
字号:
{ 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; } } /*----------------------------------------------------------------- * Go through all entries and assign them to one of the 2 nodes. * * Criteria is that entries are assigned to the node in which their * center falls. * * Hummm... this does not prevent the possibility that one of the * 2 nodes might end up empty at the end. *----------------------------------------------------------------*/ m_numEntries = 0; for(int iEntry=0; iEntry<nSrcEntries; iEntry++) { int nEntryCenterX = (m_asEntries[iEntry].XMax + m_asEntries[iEntry].XMin) / 2; int nEntryCenterY = (m_asEntries[iEntry].YMax + m_asEntries[iEntry].YMin) / 2; if (iEntry == m_nCurChildIndex || (nWidth > nHeight && ABS(nEntryCenterX-nCenterX1) < ABS(nEntryCenterX-nCenterX2)) || (nWidth <= nHeight && ABS(nEntryCenterY-nCenterY1) < ABS(nEntryCenterY-nCenterY2) ) ) { // This entry stays in current node. InsertEntry(m_asEntries[iEntry].XMin, m_asEntries[iEntry].YMin, m_asEntries[iEntry].XMax, m_asEntries[iEntry].YMax, m_asEntries[iEntry].nBlockPtr); // We have to keep track of new m_nCurChildIndex value if (iEntry == m_nCurChildIndex) { m_nCurChildIndex = m_numEntries-1; } } else { // This entry goes in the new node. poNewNode->InsertEntry(m_asEntries[iEntry].XMin, m_asEntries[iEntry].YMin, m_asEntries[iEntry].XMax, m_asEntries[iEntry].YMax, m_asEntries[iEntry].nBlockPtr); } } /*----------------------------------------------------------------- * If no entry was moved to second node, then move ALL entries except * the current child to the second node... this way current node will * have room for a new entry when this function exits. *----------------------------------------------------------------*/ if (poNewNode->GetNumEntries() == 0) { nSrcEntries = m_numEntries; m_numEntries = 0; for(int iEntry=0; iEntry<nSrcEntries; iEntry++) { if (iEntry == m_nCurChildIndex) { // Keep current child in current node InsertEntry(m_asEntries[iEntry].XMin, m_asEntries[iEntry].YMin, m_asEntries[iEntry].XMax, m_asEntries[iEntry].YMax, m_asEntries[iEntry].nBlockPtr); m_nCurChildIndex = m_numEntries-1; } else { // All other entries go to second node poNewNode->InsertEntry(m_asEntries[iEntry].XMin, m_asEntries[iEntry].YMin, m_asEntries[iEntry].XMax, m_asEntries[iEntry].YMax, m_asEntries[iEntry].nBlockPtr); } } } /*----------------------------------------------------------------- * Recompute MBR and update current node info in parent *----------------------------------------------------------------*/ RecomputeMBR(); poNewNode->RecomputeMBR(); /*----------------------------------------------------------------- * Add second node info to parent and then flush it to disk. * This may trigger splitting of parent *----------------------------------------------------------------*/ CPLAssert(m_poParentRef); int nMinX, nMinY, nMaxX, nMaxY; poNewNode->GetMBR(nMinX, nMinY, nMaxX, nMaxY); m_poParentRef->AddEntry(nMinX, nMinY, nMaxX, nMaxY, poNewNode->GetNodeBlockPtr(), TRUE); poNewNode->CommitToFile(); delete poNewNode; return 0;}/********************************************************************** * TABMAPIndexBlock::SplitRootNode() * * (private method) * * Split a Root Node. * First, a level of nodes must be added to the tree, then the contents * of what used to be the root node is moved 1 level down and then that * node is split like a regular node. * * Returns 0 on success, -1 on error **********************************************************************/int TABMAPIndexBlock::SplitRootNode(int nNewEntryX, int nNewEntryY){ CPLAssert(m_poBlockManagerRef); CPLAssert(m_poParentRef == NULL); /*----------------------------------------------------------------- * Since a root note cannot be split, we add a level of nodes * under it and we'll do the split at that level. *----------------------------------------------------------------*/ TABMAPIndexBlock *poNewNode = new TABMAPIndexBlock(m_eAccess); if (poNewNode->InitNewBlock(m_fp, 512, m_poBlockManagerRef->AllocNewBlock()) != 0) { return -1; } poNewNode->SetMAPBlockManagerRef(m_poBlockManagerRef); // Move all entries to the new child int nSrcEntries = m_numEntries; m_numEntries = 0; for(int iEntry=0; iEntry<nSrcEntries; iEntry++) { poNewNode->InsertEntry(m_asEntries[iEntry].XMin, m_asEntries[iEntry].YMin, m_asEntries[iEntry].XMax, m_asEntries[iEntry].YMax, m_asEntries[iEntry].nBlockPtr); } /*----------------------------------------------------------------- * Transfer current child object to new node. *----------------------------------------------------------------*/ if (m_poCurChild) { poNewNode->SetCurChildRef(m_poCurChild, m_nCurChildIndex); m_poCurChild->SetParentRef(poNewNode); m_poCurChild = NULL; m_nCurChildIndex = -1; } /*----------------------------------------------------------------- * Place info about new child in current node. *----------------------------------------------------------------*/ poNewNode->RecomputeMBR(); int nMinX, nMinY, nMaxX, nMaxY; poNewNode->GetMBR(nMinX, nMinY, nMaxX, nMaxY); InsertEntry(nMinX, nMinY, nMaxX, nMaxY, poNewNode->GetNodeBlockPtr()); /*----------------------------------------------------------------- * Keep a reference to the new child *----------------------------------------------------------------*/ poNewNode->SetParentRef(this); m_poCurChild = poNewNode; m_nCurChildIndex = m_numEntries -1; /*----------------------------------------------------------------- * And finally force the child to split itself *----------------------------------------------------------------*/ return m_poCurChild->SplitNode(nNewEntryX, nNewEntryY);}/********************************************************************** * TABMAPIndexBlock::RecomputeMBR() * * Recompute current block MBR, and update info in parent. **********************************************************************/void TABMAPIndexBlock::RecomputeMBR(){ m_nMinX = 1000000000; m_nMinY = 1000000000; m_nMaxX = -1000000000; m_nMaxY = -1000000000; for(int i=0; i<m_numEntries; i++) { if (m_asEntries[i].XMin < m_nMinX) m_nMinX = m_asEntries[i].XMin; if (m_asEntries[i].XMax > m_nMaxX) m_nMaxX = m_asEntries[i].XMax; if (m_asEntries[i].YMin < m_nMinY) m_nMinY = m_asEntries[i].YMin; if (m_asEntries[i].YMax > m_nMaxY) m_nMaxY = m_asEntries[i].YMax; } if (m_poParentRef) m_poParentRef->UpdateCurChildMBR(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, GetNodeBlockPtr());}/********************************************************************** * TABMAPIndexBlock::UpateCurChildMBR() * * Update current child MBR info, and propagate info in parent. * * nBlockPtr is passed only to validate the consistency of the tree. **********************************************************************/void TABMAPIndexBlock::UpdateCurChildMBR(GInt32 nXMin, GInt32 nYMin, GInt32 nXMax, GInt32 nYMax, GInt32 nBlockPtr){ CPLAssert(m_poCurChild); CPLAssert(m_asEntries[m_nCurChildIndex].nBlockPtr == nBlockPtr); m_asEntries[m_nCurChildIndex].XMin = nXMin; m_asEntries[m_nCurChildIndex].YMin = nYMin; m_asEntries[m_nCurChildIndex].XMax = nXMax; m_asEntries[m_nCurChildIndex].YMax = nYMax; m_nMinX = 1000000000; m_nMinY = 1000000000; m_nMaxX = -1000000000; m_nMaxY = -1000000000; for(int i=0; i<m_numEntries; i++) { if (m_asEntries[i].XMin < m_nMinX) m_nMinX = m_asEntries[i].XMin; if (m_asEntries[i].XMax > m_nMaxX) m_nMaxX = m_asEntries[i].XMax; if (m_asEntries[i].YMin < m_nMinY) m_nMinY = m_asEntries[i].YMin; if (m_asEntries[i].YMax > m_nMaxY) m_nMaxY = m_asEntries[i].YMax; } if (m_poParentRef) m_poParentRef->UpdateCurChildMBR(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, GetNodeBlockPtr());}/********************************************************************** * TABMAPIndexBlock::SetMAPBlockManagerRef() * * Pass a reference to the block manager object for the file this * block belongs to. The block manager will be used by this object * when it needs to automatically allocate a new block. **********************************************************************/void TABMAPIndexBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr){ m_poBlockManagerRef = poBlockMgr;};/********************************************************************** * TABMAPIndexBlock::SetParentRef() * * Used to pass a reference to this node's parent. **********************************************************************/void TABMAPIndexBlock::SetParentRef(TABMAPIndexBlock *poParent){ m_poParentRef = poParent;}/********************************************************************** * TABMAPIndexBlock::SetCurChildRef() * * Used to transfer a child object from one node to another **********************************************************************/void TABMAPIndexBlock::SetCurChildRef(TABMAPIndexBlock *poChild, int nChildIndex){ m_poCurChild = poChild; m_nCurChildIndex = nChildIndex;}/********************************************************************** * TABMAPIndexBlock::Dump() * * Dump block contents... available only in DEBUG mode. **********************************************************************/#ifdef DEBUGvoid TABMAPIndexBlock::Dump(FILE *fpOut /*=NULL*/){ if (fpOut == NULL) fpOut = stdout; fprintf(fpOut, "----- TABMAPIndexBlock::Dump() -----\n"); if (m_pabyBuf == NULL) { fprintf(fpOut, "Block has not been initialized yet."); } else { fprintf(fpOut,"Index Block (type %d) at offset %d.\n", m_nBlockType, m_nFileOffset); fprintf(fpOut," m_numEntries = %d\n", m_numEntries); /*------------------------------------------------------------- * Loop through all entries, dumping each of them *------------------------------------------------------------*/ if (m_numEntries > 0) ReadAllEntries(); for(int i=0; i<m_numEntries; i++) { fprintf(fpOut, " %6d -> (%d, %d) - (%d, %d)\n", m_asEntries[i].nBlockPtr, m_asEntries[i].XMin, m_asEntries[i].YMin, m_asEntries[i].XMax, m_asEntries[i].YMax ); } } fflush(fpOut);}#endif // DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -