1,地图数据分析-SHP数据读取

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;
View Code

实体数据由记录头和记录内容组成,其中记录头文件结构如下:

typedef struct tagShpRecordHeader {
    int RecordNumber;    // 1..n                [BIG_ENDIAN]
    int ContentLength;     // ShpObjectByteSize/2 [BIG_ENDIAN]
}SHP_RECORD_HEADER;
View Code

每一个记录内容记录了一个地理实体的坐标信息,包括地理实体的类型和坐标。

.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 );
};
View Code
原文地址:https://www.cnblogs.com/273809717/p/5144928.html