📄 mitab_mapfile.cpp
字号:
* Convert from coordinates system units as defined in the file's * coordsys clause to long integer (internal) coordinates. * * Note that the false easting/northing and the conversion factor from * datum to coordsys units are not included in the calculation. * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY, GBool bIgnoreOverflow/*=FALSE*/){ if (m_poHeader == NULL) return -1; return m_poHeader->Coordsys2Int(dX, dY, nX, nY, bIgnoreOverflow);}/********************************************************************** * TABMAPFile::Int2CoordsysDist() * * Convert a pair of X,Y size (or distance) values from long integer * (internal) to coordinates system units as defined in the file's coordsys * clause. * * The difference with Int2Coordsys() is that this function only applies * the scaling factor: it does not apply the displacement. * * Since the calculations on the X and Y values are independent, either * one can be omitted (i.e. passed as 0) * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY){ if (m_poHeader == NULL) return -1; return m_poHeader->Int2CoordsysDist(nX, nY, dX, dY);}/********************************************************************** * TABMAPFile::Coordsys2IntDist() * * Convert a pair of X,Y size (or distance) values from coordinates * system units as defined in the file's coordsys clause to long * integer (internal) coordinate units. * * The difference with Int2Coordsys() is that this function only applies * the scaling factor: it does not apply the displacement. * * Since the calculations on the X and Y values are independent, either * one can be omitted (i.e. passed as 0) * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY){ if (m_poHeader == NULL) return -1; return m_poHeader->Coordsys2IntDist(dX, dY, nX, nY);}/********************************************************************** * TABMAPFile::SetCoordsysBounds() * * Set projection coordinates bounds of the newly created dataset. * * This function must be called after creating a new dataset and before any * feature can be written to it. * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::SetCoordsysBounds(double dXMin, double dYMin, double dXMax, double dYMax){ int nStatus = 0; if (m_poHeader == NULL) return -1; nStatus = m_poHeader->SetCoordsysBounds(dXMin, dYMin, dXMax, dYMax); if (nStatus == 0) ResetCoordFilter(); return nStatus;}/********************************************************************** * TABMAPFile::GetMaxObjId() * * Return the value of the biggest valid object id. * * Note that object ids are positive and start at 1. * * Returns a value >= 0 on success, -1 on error. **********************************************************************/GInt32 TABMAPFile::GetMaxObjId(){ if (m_poIdIndex) return m_poIdIndex->GetMaxObjId(); return -1;}/********************************************************************** * TABMAPFile::MoveToObjId() * * Get ready to work with the object with the specified id. The object * data pointer (inside m_poCurObjBlock) will be moved to the first byte * of data for this map object. * * The object type and id (i.e. table row number) will be accessible * using GetCurObjType() and GetCurObjId(). * * Note that object ids are positive and start at 1. * * Returns 0 on success, -1 on error. **********************************************************************/int TABMAPFile::MoveToObjId(int nObjId){ int nFileOffset; /*----------------------------------------------------------------- * In read access mode, since the .MAP/.ID are optional, if the * file is not opened then we can still act as if one existed and * make any object id look like a TAB_GEOM_NONE *----------------------------------------------------------------*/ if (m_fp == NULL && m_eAccessMode == TABRead) { CPLAssert(m_poIdIndex == NULL && m_poCurObjBlock == NULL); m_nCurObjPtr = 0; m_nCurObjId = nObjId; m_nCurObjType = TAB_GEOM_NONE; return 0; } if (m_poIdIndex == NULL || m_poCurObjBlock == NULL) { CPLError(CE_Failure, CPLE_AssertionFailed, "MoveToObjId(): file not opened!"); m_nCurObjPtr = m_nCurObjId = m_nCurObjType = -1; return -1; } /*----------------------------------------------------------------- * Move map object pointer to the right location. Fetch location * from the index file, unless we are already pointing at it. *----------------------------------------------------------------*/ if( m_nCurObjId == nObjId ) nFileOffset = m_nCurObjPtr; else nFileOffset = m_poIdIndex->GetObjPtr(nObjId); if (nFileOffset == 0) { /*--------------------------------------------------------- * Object with no geometry... this is a valid case. *--------------------------------------------------------*/ m_nCurObjPtr = 0; m_nCurObjId = nObjId; m_nCurObjType = TAB_GEOM_NONE; } else if ( m_poCurObjBlock->GotoByteInFile(nFileOffset) == 0) { /*------------------------------------------------------------- * OK, it worked, read the object type and row id. *------------------------------------------------------------*/ m_nCurObjPtr = nFileOffset; m_nCurObjType = m_poCurObjBlock->ReadByte(); m_nCurObjId = m_poCurObjBlock->ReadInt32(); // Do a consistency check... if (m_nCurObjId != nObjId) { CPLError(CE_Failure, CPLE_FileIO, "Object ID from the .ID file (%d) differs from the value " "in the .MAP file (%d). File may be corrupt.", nObjId, m_nCurObjId); m_nCurObjPtr = m_nCurObjId = m_nCurObjType = -1; return -1; } } else { /*--------------------------------------------------------- * Failed positioning input file... CPLError has been called. *--------------------------------------------------------*/ m_nCurObjPtr = m_nCurObjId = m_nCurObjType = -1; return -1; } return 0;}/********************************************************************** * TABMAPFile::PrepareNewObj() * * Get ready to write a new object of the specified type and with the * specified id. * * 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 object type and * row ID will be written to the m_poCurObjBlock, so it will be ready to * receive the first byte of data for this map object. * * 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(int nObjId, GByte nObjType){ int nObjSize; 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 (nObjType == TAB_GEOM_NONE) { m_nCurObjType = nObjType; m_nCurObjId = nObjId; m_nCurObjPtr = 0; m_poIdIndex->SetObjPtr(m_nCurObjId, 0); return 0; } /*----------------------------------------------------------------- * 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_SYMBOL_C || nObjType == TAB_GEOM_FONTSYMBOL_C || nObjType == TAB_GEOM_CUSTOMSYMBOL_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_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_ARC_C) { m_poHeader->m_numLineObjects++; } else if (nObjType == TAB_GEOM_REGION || nObjType == TAB_GEOM_V450_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_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 for V450-specific object types and minimum TAB file version number *----------------------------------------------------------------*/ if (m_nMinTABVersion < 450 && (nObjType == TAB_GEOM_V450_REGION || nObjType == TAB_GEOM_V450_MULTIPLINE || nObjType == TAB_GEOM_V450_REGION_C || nObjType == TAB_GEOM_V450_MULTIPLINE_C) ) { m_nMinTABVersion = 450; } /*----------------------------------------------------------------- * Check for V460-specific object types (multipoint and collection) *----------------------------------------------------------------*/ if (m_nMinTABVersion < 650 && (nObjType == TAB_GEOM_MULTIPOINT || nObjType == TAB_GEOM_MULTIPOINT_C || nObjType == TAB_GEOM_COLLECTION || nObjType == TAB_GEOM_COLLECTION_C ) ) { m_nMinTABVersion = 650; } /*----------------------------------------------------------------- * OK, looks like we will need object block... check if it exists and * create it if it has not been created yet (first time for this file). * We do not create the object block in the open() call because * files that contained only "NONE" geometries ended up with empty * object and spatial index blocks. * Note: A coord block will be created only if needed later. *----------------------------------------------------------------*/ if (m_poCurObjBlock == NULL) { m_poCurObjBlock = new TABMAPObjectBlock(m_eAccessMode); int nBlockOffset = m_oBlockManager.AllocNewBlock(); m_poCurObjBlock->InitNewBlock(m_fp, 512, nBlockOffset); // The reference to the first object block should // actually go through the index blocks... this will be // updated when file is closed. m_poHeader->m_nFirstIndexBlock = nBlockOffset; } /*----------------------------------------------------------------- * Fetch new object size, make sure there is enough room in obj. * block for new object, and save/create a new one if necessary. *----------------------------------------------------------------*/ nObjSize = m_poHeader->GetMapObjectSize(nObjType); if (m_poCurObjBlock->GetNumUnusedBytes() < nObjSize ) { /*------------------------------------------------------------- * OK, the new object won't fit in the current block. Commit * the current block to disk, and init a new one. * * __TODO__ To create an optimum file, we should split the object * block at this point and update the index blocks... however the * file should still be usable even if we don't do it. *------------------------------------------------------------*/ CommitObjBlock(TRUE); } /*----------------------------------------------------------------- * Init member vars and write new object type/id *----------------------------------------------------------------*/ m_nCurObjType = nObjType; m_nCurObjId = nObjId; m_nCurObjPtr = m_poCurObjBlock->GetFirstUnusedByteOffset(); m_poCurObjBlock->GotoByteInFile(m_nCurObjPtr); m_poCurObjBlock->WriteByte(m_nCurObjType); m_poCurObjBlock->WriteInt32(m_nCurObjId); // Move write pointer to start location of next object (padding with zeros)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -