Shape--矢量数据

一.  Shape文件概述

        Shapefile是由ESRI公司开发的一种矢量存储格式。Shapefile用于描述几何体对象:点,折线与多边形,属于一种矢量图形格式,它能够保存几何图形的位置及相关属性。但这种格式没法存储地理数据的拓扑信息。Shapefile通常以X与Y的方式来处理地理坐标,一般X对应经度,Y对应纬度,用户必须注意X,Y的顺序。

        要组成一个Shapefile,有三个是必不可少的文件,它们分别是".shp", ".shx"与 ".dbf"文件

        .shp—图形格式,主文件用于保存元素的几何实体。shp格式的矢量数据图层一般只有一个,mdb和dxf等图层会有多个。

        .shx—图形索引格式。几何体位置索引,记录每一个几何体在shp文件之中的位置,能够加快向前或向后搜索一个几何体的效率。

        .dbf—属性数据格式,以dBase IV的数据表格式存储每个几何形状的属性数据。

        在每个.shp、.shx与.dbf文件之中,图形在每个文件的排序是一致的。也就是说,.shp的第一条记录与.shx及.dbf之中的第一条记录相对应,如此类推。此外,在.shp与.shx之中,有许多字段的字节序是不一样的。因此用户在编写读取这些文件格式的程序时,必须十分小心地处理不同文件的不同字节序。

        坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成,如下表所示:

 

       坐标文件的文件头是一个长度固定(100 bytes)的记录段,一共有9个int型和7个double型数据,主要记录内容见表:

           注:最后4个加星号特别标示的四个数据只有当这个Shapefile文件包含Z方向坐标或者具有Measure值时才有值,否则为0.0。所谓Measure值,是用于存储需要的附加数据,可以用来记录各种数据,例如权值、道路长度等信息。

二.位序

          上表中位序有Little和big的区别,通常,数据的位序都是Little,但在有些情况下可能会是big,二者的区别在于它们位序的顺序相反。一个位序为big的数据,如果我们想得到它的真实数值,需要将它的位序转换成Little即可,

      下面是转换代码(big->little)(目前只有C++代码后续用到补Java代码)

int OnChangeByteOrder(int indata){
    char ss[9];
    char ee[8];
    unsigned long val = unsigned long(indata);
    ultoa(val, ss, 16);// 将十六进制的数(val)转到一个字符串(ss)中,itoa(val,ss,16); 
    int i;
    int length = strlen(ss);
    if (length != 8){
        for (i = 0; i<8 - length; i++)
            ee[i] = '0';
        for (i = 0; i<length; i++)
            ee[i + 8 - length] = ss[i];
        for (i = 0; i<8; i++)
            ss[i] = ee[i];
    }
    //****** 进行倒序 
    int t;
    t = ss[0]; ss[0] = ss[6]; ss[6] = t;
    t = ss[1]; ss[1] = ss[7]; ss[7] = t;
    t = ss[2]; ss[2] = ss[4]; ss[4] = t;
    t = ss[3]; ss[3] = ss[5]; ss[5] = t;
 
    //****** 将存有十六进制数 (val) 的字符串 (ss) 中的十六进制数转成十进制数 
    int value = 0;
    for (i = 0; i<8; i++){
        int k;
        if (ss[i] == 'a' || ss[i] == 'b' || ss[i] == 'c' || ss[i] == 'd' || ss[i] == 'e' || ss[i] == 'f')
            k = 10 + ss[i] - 'a';
        else
            k = ss[i] - '0';
        value = value + int(k*(int)pow((DOUBLE)16, 7 - i));
    }
    return(value);
}

 下面是转换代码(little->big)

// 将十进制转换成十六进制,并转成big
int OnChangeByteOrderTenToSixteen(int indata){
    int yushu;
    int i = 7;
    char ss[8];
    if (indata == 0) return 0;
    while (indata > 0) {
        yushu = indata % 16;
        char k;
        if (yushu > 9)
            k = 'a' + yushu - 10;
        else
            k = '0' + yushu;
        ss[i] = k;
        indata = indata / 16;
        i--;
    }
 
    //****进行倒序 
    for (int j = 0; j<i + 1; j++) {
        ss[j] = '0';
    }
    int t, temp;
    t = ss[0]; ss[0] = ss[6]; ss[6] = t;
    t = ss[1]; ss[1] = ss[7]; ss[7] = t;
    t = ss[2]; ss[2] = ss[4]; ss[4] = t;
    t = ss[3]; ss[3] = ss[5]; ss[5] = t;
    for (i = 0; i < 8; i++) {
        if (ss[i] != '0') {
            temp = i;
            break;
        }
    }
    int k;
    int num = 0;
    for (i = temp; i < 8; i++) {
        if (ss[i] >= 'a'&&ss[i] <= 'f')
            k = 10 + ss[i] - 'a';
        else
            k = ss[i] - '0';
        num = num * 16 + k;
    }
    return num;
}

 

文章借鉴:

  https://www.cnblogs.com/ParanoiaApe/p/11611319.html

  https://www.cnblogs.com/fan-0802-WHU/p/10157773.html

 

posted @ 2020-11-30 09:25  小狗钱钱1  阅读(1200)  评论(0)    收藏  举报