1,地图制作软件
作为稳定的生产工具,地图公司一般使用MapInfo和Arcgis作为制作地图数据的软件。一般使用SHP格式。
2,SHP 格式读取
一个shapefile至少包括主文件*.shp,数据文件*.dbf,索引文件*.shx。一般来说在导航的开发中使用这三个文件。
.shp 是存储地理的几何属性(点,线,面等)的文件。由文件头和地理实体数据组成。
详细的数据结构如下:
typedef struct tagShpFileHeader { int FileCode; // 9994 [BIG_ENDIAN] int Unused0; // 0 [BIG_ENDIAN] int Unused1; // 0 [BIG_ENDIAN] int Unused2; // 0 [BIG_ENDIAN] int Unused3; // 0 [BIG_ENDIAN] int Unused4; // 0 [BIG_ENDIAN] int FileLength; // [BIG_ENDIAN] int Version; // 1000 [LITTLE_ENDIAN] int ShapeType; // SHP_OBJ_TYPE [LITTLE_ENDIAN] double Xmin; // [LITTLE_ENDIAN] double Ymin; double Xmax; double Ymax; int Unused5; int Unused6; int Unused7; int Unused8; int Unused9; int Unused10; int Unused11; int Unused12; }SHP_FILE_HEADER;
实体数据由记录头和记录内容组成,其中记录头文件结构如下:
typedef struct tagShpRecordHeader { int RecordNumber; // 1..n [BIG_ENDIAN] int ContentLength; // ShpObjectByteSize/2 [BIG_ENDIAN] }SHP_RECORD_HEADER;
每一个记录内容记录了一个地理实体的坐标信息,包括地理实体的类型和坐标。
.dbf是一种常用的数据库格式文件,这里略去不讲。
*.shx是索引文件,由文件头和内容组成。文件头是由固定的100个字节的记录段,每一条内容包含了一个偏移量和记录段的长度。主要目的是为了快速方便的在坐标文件中定位到指定的目标的坐标信息。
下面是关于.shp 和.dbf 读写类的设计
class XSHPReader { FILE *m_fpSHP; FILE *m_fpDBF; FILE *m_fpSHX; int m_nPreFetchIdx; bool m_bPreFetchDBF; bool m_bPreFetchSHP; SHPGeometry *m_ShpObj; XExtBuffer m_ShpBuffer; char *m_DbfRecBuffer; XExtBuffer m_DbfBuffer; TDBF_INFO m_DbfHeader; int m_DbfFieldCnt; TDBF_FIELDINFO *m_DbfFields; ARC_FILE_HEADER m_ShpHeader; void FreeMem( void ); bool ReadRecordDBF( void ); SHPGeometry *ReadRecordSHP( void ); long m_lRecordNum; public: char m_szFileName[ 256 ]; XSHPReader(); ~XSHPReader(); bool Open( const char *fname ); void Close(); SHP_OBJ_TYPE GetShpObjectType( void ); void GetEnvelope( SBox *box ); int GetFieldCount( void ); bool GetFieldInfo( int col, DBF_FIELD_INFO &FieldInfo ); bool RenameField( int col, const char *szFieldName ); int GetFieldIdx( const char *szFieldName ); int GetRecordCount( void ); bool Fetch( long off ); bool GetDataAsString( int col, char *str, int max_len ); SHPGeometry *GetGeometry( void ) { return m_ShpObj; }; }; class XSHPWriter { FILE *m_fpSHP; FILE *m_fpDBF; FILE *m_fpSHX; int m_nRecordCount; char *m_DbfRecBuffer; TDBF_INFO m_DbfHeader; int m_DbfFieldCnt; TDBF_FIELDINFO *m_DbfFields; SHPGeometry *m_ShpObj; ARC_FILE_HEADER m_ShpHeader; int m_nShpWrittenOffset; int m_nShpTotalSize; void FreeMem( void ); public: XSHPWriter(); ~XSHPWriter(); bool Create( const char *fname ); bool WriteSHPHeader( SHP_OBJ_TYPE shp_obj_type, const SBox *box ); bool WriteDBFHeader( int nFieldCnt, DBF_FIELD_INFO *pFieldsInfo ); void Close(); int GetFieldIdx( const char *szFieldName ); bool SetGeometry( SHPGeometry *pObj ); bool SetDataAsString( int col, char *str, int max_len ); bool WriteRecord( void ); }; class XDBFReader { FILE *m_fpDBF; int m_nPreFetchIdx; char *m_DbfRecBuffer; XExtBuffer m_DbfBuffer; TDBF_INFO m_DbfHeader; int m_DbfFieldCnt; TDBF_FIELDINFO *m_DbfFields; void FreeMem( void ); bool ReadRecordDBF( void ); public: char m_szFileName[ 256 ]; XDBFReader(); ~XDBFReader(); bool Open( const char *fname ); void Close(); int GetFieldCount( void ); bool GetFieldInfo( int col, DBF_FIELD_INFO &FieldInfo ); int GetFieldIdx( const char *szFieldName ); bool RenameField( int col, const char *szFieldName ); int GetRecordCount( void ); bool Fetch( long off ); bool GetDataAsString( int col, char *str, int max_len ); }; class XDBFWriter { FILE *m_fpDBF; int m_nRecordCount; char *m_DbfRecBuffer; TDBF_INFO m_DbfHeader; int m_DbfFieldCnt; TDBF_FIELDINFO *m_DbfFields; void FreeMem( void ); public: XDBFWriter(); ~XDBFWriter(); bool Create( const char *fname ); bool WriteDBFHeader( int nFieldCnt, DBF_FIELD_INFO *pFieldsInfo ); void Close(); bool SetDataAsString( int col, char *str, int max_len ); bool WriteRecord( void ); };