📄 mitab_mapcoordblock.cpp
字号:
int TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed, GBool bV450Hdr, int numSections, TABMAPCoordSecHdr *pasHdrs, GInt32 &numVerticesTotal){ int i, nTotalHdrSizeUncompressed; CPLErrorReset(); /*------------------------------------------------------------- * Note about header+vertices size vs compressed coordinates: * The uncompressed header sections are actually 16 bytes, but the * offset calculations are based on prior decompression of the * coordinates. Our coordinate offset calculations have * to take this fact into account. * Also, V450 header section uses int32 instead of int16 for numVertices * and we add another 2 bytes to align with a 4 bytes boundary. *------------------------------------------------------------*/ if (bV450Hdr) nTotalHdrSizeUncompressed = 28 * numSections; else nTotalHdrSizeUncompressed = 24 * numSections; numVerticesTotal = 0; for(i=0; i<numSections; i++) { /*------------------------------------------------------------- * Read the coord. section header blocks *------------------------------------------------------------*/ if (bV450Hdr) pasHdrs[i].numVertices = ReadInt32(); else pasHdrs[i].numVertices = ReadInt16(); pasHdrs[i].numHoles = ReadInt16(); ReadIntCoord(bCompressed, pasHdrs[i].nXMin, pasHdrs[i].nYMin); ReadIntCoord(bCompressed, pasHdrs[i].nXMax, pasHdrs[i].nYMax); pasHdrs[i].nDataOffset = ReadInt32(); if (CPLGetLastErrorType() != 0) return -1; numVerticesTotal += pasHdrs[i].numVertices; pasHdrs[i].nVertexOffset = (pasHdrs[i].nDataOffset - nTotalHdrSizeUncompressed ) / 8;#ifdef TABDUMP printf("pasHdrs[%d] = { numVertices = %d, numHoles = %d, \n" " nXMin=%d, nYMin=%d, nXMax=%d, nYMax=%d,\n" " nDataOffset=%d, nVertexOffset=%d }\n", i, pasHdrs[i].numVertices, pasHdrs[i].numHoles, pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax, pasHdrs[i].nYMax, pasHdrs[i].nDataOffset, pasHdrs[i].nVertexOffset); printf(" dX = %d, dY = %d (center = %d , %d)\n", pasHdrs[i].nXMax - pasHdrs[i].nXMin, pasHdrs[i].nYMax - pasHdrs[i].nYMin, m_nComprOrgX, m_nComprOrgY);#endif } for(i=0; i<numSections; i++) { /*------------------------------------------------------------- * Make sure all coordinates are grouped together * (Well... at least check that all the vertex indices are enclosed * inside the [0..numVerticesTotal] range.) *------------------------------------------------------------*/ if ( pasHdrs[i].nVertexOffset < 0 || (pasHdrs[i].nVertexOffset + pasHdrs[i].numVertices ) > numVerticesTotal) { CPLError(CE_Failure, CPLE_AssertionFailed, "Unsupported case or corrupt file: MULTIPLINE/REGION " "object vertices do not appear to be grouped together."); return -1; } } return 0;}/********************************************************************** * TABMAPObjectBlock::WriteCoordSecHdrs() * * Write a set of coordinate section headers for PLINE MULTIPLE or REGIONs. * pasHdrs should point to an array of numSections TABMAPCoordSecHdr * structures that have been properly initialized. * * In V450 the numVertices is stored on an int32 instead of an int16 * * At the end of the call, this TABMAPCoordBlock object will be ready to * receive the coordinate data. * * Returns 0 if succesful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/int TABMAPCoordBlock::WriteCoordSecHdrs(GBool bV450Hdr, int numSections, TABMAPCoordSecHdr *pasHdrs, GBool bCompressed /*=FALSE*/){ int i; CPLErrorReset(); for(i=0; i<numSections; i++) { /*------------------------------------------------------------- * Write the coord. section header blocks *------------------------------------------------------------*/ if (bV450Hdr) WriteInt32(pasHdrs[i].numVertices); else WriteInt16(pasHdrs[i].numVertices); WriteInt16(pasHdrs[i].numHoles); WriteIntCoord(pasHdrs[i].nXMin, pasHdrs[i].nYMin, bCompressed); WriteIntCoord(pasHdrs[i].nXMax, pasHdrs[i].nYMax, bCompressed); WriteInt32(pasHdrs[i].nDataOffset); if (CPLGetLastErrorType() == CE_Failure ) return -1; } return 0;}/********************************************************************** * TABMAPCoordBlock::WriteIntCoord() * * Write a pair of integer coordinates values to the current position in the * the block. * * Returns 0 if succesful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/int TABMAPCoordBlock::WriteIntCoord(GInt32 nX, GInt32 nY, GBool bCompressed /*=FALSE*/){ if ((!bCompressed && (WriteInt32(nX) != 0 || WriteInt32(nY) != 0 ) ) || (bCompressed && (WriteInt16(nX - m_nComprOrgX) != 0 || WriteInt16(nY - m_nComprOrgY) != 0) ) ) { return -1; } /*----------------------------------------------------------------- * Update block MBR *----------------------------------------------------------------*/ //__TODO__ Do we still need to track the block MBR??? if (nX < m_nMinX) m_nMinX = nX; if (nX > m_nMaxX) m_nMaxX = nX; if (nY < m_nMinY) m_nMinY = nY; if (nY > m_nMaxY) m_nMaxY = nY; /*------------------------------------------------------------- * Also keep track of current feature MBR. *------------------------------------------------------------*/ if (nX < m_nFeatureXMin) m_nFeatureXMin = nX; if (nX > m_nFeatureXMax) m_nFeatureXMax = nX; if (nY < m_nFeatureYMin) m_nFeatureYMin = nY; if (nY > m_nFeatureYMax) m_nFeatureYMax = nY; return 0;}/********************************************************************** * TABMAPCoordBlock::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 TABMAPCoordBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr){ m_poBlockManagerRef = poBlockMgr;};/********************************************************************** * TABMAPCoordBlock::ReadBytes() * * Cover function for TABRawBinBlock::ReadBytes() that will automagically * load the next coordinate block in the chain before reading the * requested bytes if we are at the end of the current block and if * m_nNextCoordBlock is a valid block. * * Then the control is passed to TABRawBinBlock::ReadBytes() to finish the * work: * Copy the number of bytes from the data block's internal buffer to * the user's buffer pointed by pabyDstBuf. * * Passing pabyDstBuf = NULL will only move the read pointer by the * specified number of bytes as if the copy had happened... but it * won't crash. * * Returns 0 if succesful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/int TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf){ int nStatus; if (m_pabyBuf && m_nCurPos >= (m_numDataBytes+MAP_COORD_HEADER_SIZE) && m_nNextCoordBlock > 0) { // We're at end of current block... advance to next block. if ( (nStatus=GotoByteInFile(m_nNextCoordBlock)) != 0) { // Failed.... an error has already been reported. return nStatus; } GotoByteInBlock(MAP_COORD_HEADER_SIZE); // Move pointer past header m_numBlocksInChain++; } if (m_pabyBuf && m_nCurPos < (m_numDataBytes+MAP_COORD_HEADER_SIZE) && m_nCurPos+numBytes > (m_numDataBytes+MAP_COORD_HEADER_SIZE) && m_nNextCoordBlock > 0) { // Data overlaps on more than one block // Read until end of this block and then recursively call ReadBytes() // for the rest. int numBytesInThisBlock = (m_numDataBytes+MAP_COORD_HEADER_SIZE)-m_nCurPos; nStatus = TABRawBinBlock::ReadBytes(numBytesInThisBlock, pabyDstBuf); if (nStatus == 0) nStatus = TABMAPCoordBlock::ReadBytes(numBytes-numBytesInThisBlock, pabyDstBuf+numBytesInThisBlock); return nStatus; } return TABRawBinBlock::ReadBytes(numBytes, pabyDstBuf);}/********************************************************************** * TABMAPCoordBlock::WriteBytes() * * Cover function for TABRawBinBlock::WriteBytes() that will automagically * CommitToFile() the current block and create a new one if we are at * the end of the current block. * * Then the control is passed to TABRawBinBlock::WriteBytes() to finish the * work. * * Passing pabySrcBuf = NULL will only move the write pointer by the * specified number of bytes as if the copy had happened... but it * won't crash. * * Returns 0 if succesful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/int TABMAPCoordBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf){ if (m_eAccess == TABWrite && m_poBlockManagerRef && (m_nBlockSize - m_nCurPos) < nBytesToWrite) { if (nBytesToWrite <= (m_nBlockSize-MAP_COORD_HEADER_SIZE)) { // Data won't fit in this block but can fit inside a single // block, so we'll allocate a new block for it. This will // prevent us from overlapping coordinate values on 2 blocks, but // still allows strings longer than one block (see 'else' below). // int nNewBlockOffset = m_poBlockManagerRef->AllocNewBlock(); SetNextCoordBlock(nNewBlockOffset); if (CommitToFile() != 0 || InitNewBlock(m_fp, 512, nNewBlockOffset) != 0) { // An error message should have already been reported. return -1; } m_numBlocksInChain++; } else { // Data to write is longer than one block... so we'll have to // split it over multiple block through multiple calls. // int nStatus = 0; while(nStatus == 0 && nBytesToWrite > 0) { int nBytes = m_nBlockSize-MAP_COORD_HEADER_SIZE; if ( (m_nBlockSize - m_nCurPos) > 0 ) { // Use free room in current block nBytes = (m_nBlockSize - m_nCurPos); } nBytes = MIN(nBytes, nBytesToWrite); // The following call will result in a new block being // allocated in the if() block above. nStatus = TABMAPCoordBlock::WriteBytes(nBytes, pabySrcBuf); nBytesToWrite -= nBytes; pabySrcBuf += nBytes; } return nStatus; } } if (m_nCurPos >= MAP_COORD_HEADER_SIZE) { // Keep track of Coordinate data... this means ignore header bytes // that could be written. m_nTotalDataSize += nBytesToWrite; m_nFeatureDataSize += nBytesToWrite; } return TABRawBinBlock::WriteBytes(nBytesToWrite, pabySrcBuf);}/********************************************************************** * TABMAPCoordBlock::StartNewFeature() * * Reset all member vars that are used to keep track of data size * and MBR for the current feature. This is info is not needed by * the coord blocks themselves, but it helps a lot the callers to * have this class take care of that for them. * * See Also: GetFeatureDataSize() and GetFeatureMBR() **********************************************************************/void TABMAPCoordBlock::StartNewFeature(){ m_nFeatureDataSize = 0; m_nFeatureXMin = 1000000000; m_nFeatureYMin = 1000000000; m_nFeatureXMax = -1000000000; m_nFeatureYMax = -1000000000;}/********************************************************************** * TABMAPCoordBlock::GetFeatureMBR() * * Return the MBR of all the coords written using WriteIntCoord() since * the last call to StartNewFeature(). **********************************************************************/void TABMAPCoordBlock::GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin, GInt32 &nXMax, GInt32 &nYMax){ nXMin = m_nFeatureXMin; nYMin = m_nFeatureYMin; nXMax = m_nFeatureXMax; nYMax = m_nFeatureYMax; }/********************************************************************** * TABMAPCoordBlock::Dump() * * Dump block contents... available only in DEBUG mode. **********************************************************************/#ifdef DEBUGvoid TABMAPCoordBlock::Dump(FILE *fpOut /*=NULL*/){ if (fpOut == NULL) fpOut = stdout; fprintf(fpOut, "----- TABMAPCoordBlock::Dump() -----\n"); if (m_pabyBuf == NULL) { fprintf(fpOut, "Block has not been initialized yet."); } else { fprintf(fpOut,"Coordinate Block (type %d) at offset %d.\n", m_nBlockType, m_nFileOffset); fprintf(fpOut," m_numDataBytes = %d\n", m_numDataBytes); fprintf(fpOut," m_nNextCoordBlock = %d\n", m_nNextCoordBlock); } fflush(fpOut);}#endif // DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -