博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

矢量空间数据格式

Posted on 2013-02-08 23:07  marsprj  阅读(13134)  评论(0编辑  收藏  举报

空间数据格式是空间数据的基础,定义了如何在计算机中表达空间数据。各个GIS软件都定义了自己的空间数据格式。OGC定义了空间数据的交换格式,来实现各类GIS软件之间的空间数据交互。主要有WKT、WKB、GML几类,随着Google Earth的普及,KML也成为OGC的规范。

 

1. 常用的矢量数据格式主要包括以下六类:

  • 点(Point)
  • 多点(MultiPoint)
  • 线(LineString)
  • 多线(MultiLineString)
  • 面(Polygon)
  • 多面(MultiPolygon)

1) 点(Point)

    单独一个坐标点构成的空间实体。

 

2) 多点(MultiPoint)

    由多个坐标点构成的一个空间实体。

3) 线(LineString)

    由一条线构成的空间实体。

4) 多线(MultiLineString)

   有多条线构成的一个空间实体。

5) 面(Polygon)

    Polygon和MultiPolygon的结构较为复杂,概念相也容易混淆。Polygon和MultiPolygon都由多个环(Ring)构成的封闭的面状实体。

    Polygon具有1个外环和0个或n个内环构成。

    MultiPoylgon由多个Plygon构成,Plygon之间的空间关系是相离,因此MultiPolygon并没有外环。

6) 多面(MultiPolygon)

   由多个相离的Polygon构成,并没有一个外环。

    

 

 

2. WKT

WKT用文本的方式来表达Geometry,便于人的阅读。

WKT的格式为:Geometry类型(坐标数据)

1) 点(Point)

    格式:POINT(x y)

    下面是一个Point类型的Geometry的WKT

    § POINT(1 1)

  • Point:Geometry类型
  • (1 1):几何坐标(x y),x和y之间用空格隔开,不是用逗号。

2) 多点(MultiPoint)

    格式:MULTIPOINT(x1 y1,x2 y2,…,xn yn)

3) 线(LineString)

    格式:LINESTRING(x1 y1,x2 y2,…,xn yn)

4) 多线(MultiLineString)

   格式:MULTILINESTRING((x1 y1,x2 y2,…,xn yn),(x1 y1,x2 y2,…,xm ym),......)

5) 面(Polygon)

    格式:POLYGON((x1 y1,x2 y2,…,xn yn),(x1 y1,x2 y2,…,xm ym),......)

    其中每一个括号为一个环,其中(x1 y1,x2 y2,…,xn yn)为外环。

6) 多面(MultiPolygon)

    格式:MULTIPOLYGON(((x1 y1,x2 y2,…,xn yn),(x1 y1,x2 y2,…,xm ym),......)),(...));

    第一层括号为第一个Polygon,每个Polygon之间用逗号隔开。

  

3. WKB

WKB采用二进制的方式来表达Geometry数据。WKB是一种自描述的数据结构,本身带有Geometry的元数据信息。这里还是介绍常用的6种Geometry。

3.1 WKB的基本结构
下面以Point的来介绍WKB的基本结构,其他类型的Geometry的结构与Point的结构类似。

Point的WKB结构定义如下所示:

1 struct WKBPoint{
2     unsigned char    byteOrder;
3     int              wkbType;
4     Point            point;
5 };

 与之相对应的WKBPoint的内存结构如下图所示:

1) byteOrder(字节序)
    字节序描述了数据结构在计算机里面的内存排布。例如,32位系统上int类型数据由4个字节构成,这4个字节可以可以由高地址位向低地址位排列,也可以由低地址位向高地址位排列,由此引出Big Endian和Little Endian两种字节序。
    WKBPoint的第1个字节是字节序,描述了WKBPoint内存的排列是Big Endian还是Little Endian。当WKB的字节序与主机字节序不同时,需要将WKB的字节序进行逆序变换,转换为主机字节序,否则WKB无法被正确解析。
2) wkbType
    第2~5的四个字节为一个int型变量,描述了WKB的几何类型。
    系统根据wkbType描述的几何类型来调用不同的程序来解析WKB结构。
3) Point结构体
    对于WKBPoint,从第6个字节开始是一个struct Point类型数据结构,定义了点的坐标结构。
    struct Point的定义如下所示:

1 struct Point{
2     double x;
3     double y;
4 };

    可以看出,struct Point定义了一个x,y坐标对,描述了一个平台面上的点的坐标。

 WKB的前5个字节,即byteOrder和wkbType是所有WKB拥有的共同结构,用以判断WKB的基本信息。因此,可以定义为通用的结构体,由于WKB的预处理。

1 struct WKBGeometryInfo{
2     unsigned char    byteOrder;
3     int              wkbType; 
4 };

 

通过WKBGeometryInfo,可以判断wkb的类型,然后调用不同的处理函数进行处理。

 1 unsigned char* wkb;
 2 WKBGeometryInfo *info = (WKBGeometryInfo *)wkb;
 3 
 4 switch(info->wkbType)
 5 {
 6 case wkbPoint:
 7     ...
 8     break;
 9 case wkbLineString:
10     ...
11     break;
12 case wkbPolygon:
13     ...
14     break;
15 ....
16 }

 

 3.2 WKB数据结构的完整定义(C语言)

 1) 定义字节序对齐

     编译器优化结构体,采用4字节对齐方式。对于不满足4字节对齐的结构体,编译器会填充一些空字节,补足为4字节,来保持对齐方式。WKB的结构体不满足4字节对齐,为了让编译器不进行结构体对齐处理,需要显式地设置为1字节对齐。

1 #pragma pack(1)

 

2) 定义字节序枚举

1 enum WKBByteOrder {
2     wkbXDR,     // Big Endian
3     wkbNDR = 1  // Little Endian
4 };

 

定义默认字节序

1 #define coDefaultByteOrder wkbNDR

 

3) 定义几何数据类型枚举

 1 enum WKBGeometryType {
 2      wkbNull                ,
 3      wkbPoint                = 1,
 4      wkbLineString           = 2,
 5      wkbPolygon              = 3,
 6      wkbMultiPoint           = 4,
 7      wkbMultiLineString      = 5,
 8      wkbMultiPolygon         = 6,
 9      wkbGeometryCollection   = 7
10 };

 

4) 定义坐标点数据结构

1  struct Point{
2      double x;
3      double y;
4  };

 

5) 定义环(Ring)数据结构

1  struct LinearRing {
2      int     numPoints;
3      Point   points[1];
4  };

 

至此,完成WKB的基本数据结构及枚举的定义,下面定义6类几何数据结构

6) WKBPoint

1  struct WKBPoint{
2      unsigned char    byteOrder;
3      int              wkbType;    // = 1;
4      Point            point;
5  };

 

7) WKBLineString

1  struct WKBLineString {
2      unsigned char    byteOrder;
3      int              wkbType;    // = 2;
4      int              numPoints;
5      Point            points[1];
6  };

 

LineString实际上是一个Point序列。由于C语言里面不能定义变长数据,所以WKBLineString里面定义了只有一个元素的数组points。
实际上points指向了一个由numPoints个元素构成的points数组。
前面定义的LinearRing结构与此类似。

8) WKBPolygon
1  struct WKBPolygon {
2      unsigned char    byteOrder;
3      int              wkbType;    // = 3;
4      int              numRings;
5      LinearRing       rings[1];
6  };
7  

 

9) WKBMultiPoint
1  struct WKBMultiPoint {
2      unsigned char    byteOrder;
3      int              wkbType;    //=4;
4      int              numPoints;
5      WKBPoint         points[1];
6  };
10) WKBMultiLineString
1  struct WKBMultiLineString {
2      unsigned char    byteOrder;
3      int              wkbType;    // = 5;
4      int              numLineStrings;
5      WKBLineString    lineStrings[1];
6  };

 

11) WKBMultiPolygon
1  struct WKBMultiPolygon {
2      unsigned char    byteOrder;
3      int              wkbType;    // = 6;
4      int              numPolygons;
5      WKBPolygon       polygons[1];
6  };

 WKB的完整数据结构如下所示

View Code
  1 #pragma pack(1)
  2   
  3   /*
  4    * 定义字节序枚举
  5    */
  6   enum WKBByteOrder {
  7       wkbXDR,        // Big Endian    
  8       wkbNDR = 1     // Little Endian
  9   };
 10 
 11   /*
 12    * 定义默认字节序
 13    */
 14   #define coDefaultByteOrder wkbNDR  
 15 
 16   /*
 17    * 定义几何数据类型枚举
 18    */
 19   enum WKBGeometryType {
 20       wkbNull                ,
 21       wkbPoint                = 1,
 22       wkbLineString           = 2,
 23       wkbPolygon              = 3,
 24       wkbMultiPoint           = 4,
 25       wkbMultiLineString      = 5,
 26       wkbMultiPolygon         = 6,
 27       wkbGeometryCollection   = 7
 28   };
 29   
 30   /*
 31    * 定义点数据结构
 32    */
 33   struct Point{
 34       double x;
 35       double y;
 36   };
 37     
 38   /*
 39    * 定义环数据结构
 40    */
 41   struct LinearRing {
 42       int     numPoints;
 43       Point   points[1];
 44   };
 45   
 46   /*
 47    * 定义几何信息枚举,这个数据结构是所有WKB格式的头部
 48    */
 49   struct WKBGeometryInfo{
 50       unsigned char    byteOrder;
 51       int              wkbType; 
 52   };
 53   
 54   /*
 55    * 定义Point类型WKB数据结构
 56    */
 57   struct WKBPoint{
 58       unsigned char    byteOrder;
 59       int              wkbType;    // = 1;
 60       Point            point;
 61   };
 62     
 63   /*
 64    * 定义LineString类型WKB数据结构
 65    */
 66   struct WKBLineString {
 67       unsigned char    byteOrder;
 68       int              wkbType;    // = 2;
 69       int              numPoints;
 70       Point            points[1];
 71   };
 72   
 73   /*
 74    * 定义Polygon类型WKB数据结构
 75    */
 76   struct WKBPolygon {
 77       unsigned char    byteOrder;
 78       int              wkbType;    // = 3;
 79       int              numRings;
 80       LinearRing       rings[1];
 81   };
 82   
 83   /*
 84    * 定义MultiPoint类型WKB数据结构
 85    */
 86   struct WKBMultiPoint {
 87       unsigned char    byteOrder;
 88       int              wkbType;    //=4;
 89       int              numPoints;
 90       WKBPoint         points[1];
 91   };
 92   
 93   /*
 94    * 定义MultiLineString类型WKB数据结构
 95    */
 96   struct WKBMultiLineString {
 97       unsigned char    byteOrder;
 98       int              wkbType;    // = 5;
 99       int              numLineStrings;
100       WKBLineString    lineStrings[1];
101   };
102     
103   /*
104    * 定义BMultiPolygon 类型WKB数据结构
105    */
106   struct WKBMultiPolygon {
107       unsigned char    byteOrder;
108       int              wkbType;    // = 6;
109       int              numPolygons;
110       WKBPolygon       polygons[1];
111   };
112  
113   #pragma pack()

 3.3 WKB数据访问

1) WKBPoint

1 unsigned char* wkb;
2 WKBPoint* pWKBPoint = (WKBPoint*)wkb;
3 printf("%f,%f\n", pWKBPoint->point.x pWKBPoint->point.y);

 

2) WKBMultiPoint

 1 unsigned int numPoints = 0;
 2 WKBPoint* pWKBPoint = NULL;
 3 
 4 //Point个数
 5 numPoints = pWKBMultiPoint->numPoints;
 6 //获得points数组的指针
 7 pWKBPoint = (WKBPoint*)(&(pWKBMultiPoint->points[0]));
 8 //遍历points数组
 9 for(unsigned int i=0; i<numPoints; i++, pWKBPoint++)
10 {
11     printf("%f,%f\n", pWKBPoint->point.x pWKBPoint->point.y);
12 }
3) WKBLineString
 1 Point* pt=NULL;
 2 unsigned int numPoints = 0;
 3 
 4 //Point个数
 5 numPoints = pWKBLineString->numPoints;
 6 //获得points数组的指针
 7 pt = (Point*)(&(pWKBLineString->points[0]));
 8 //遍历points数组
 9 for(unsigned int i = 0; i<numPoints; i++,pt++, gdiPt++)
10 {
11     printf("%f,%f\n", pt->x pt->y);
12 }
4) WKBMultiLineString 
 1 Point *pt = NULL;
 2 WKBLineString* pWKBLineString = NULL;
 3 unsigned int numLineStrings = 0;
 4 
 5 //获得LineString个数
 6 numLineStrings = pWKBMultiLineString->numLineStrings;
 7 
 8 //获得LineString数组指针
 9 pWKBLineString = &(pWKBMultiLineString->lineStrings[0]);
10 for(unsigned int i=0; i<numLineStrings; i++)
11 {
12     //指向pWKBLineString的points数组首个元素的指针
13     pt = &(pWKBLineString->points[0]);
14     //访问pWKBLineString数据
15     //......
16 
17     //pt指向pWKBLineString的points数组的末尾
18     //即pWKBMultiLineString的下一个pWKBLineString的头部
19     pt += pWKBLineString->numPoints;
20     pWKBLineString = (auge::WKBLineString*)pt;
21 }
5) WKBPolygon
 1 unsigned int i=0,j=0;
 2 unsigned int numPoints = 0;
 3 unsigned int numRings = pWKBPolygon->numRings;
 4 Point *pt=NULL;
 5 LinearRing *pLinearRing = NULL;
 6 
 7 numRings = pWKBPolygon->numRings;
 8 pLinearRing = (auge::LinearRing*)(&(pWKBPolygon->rings[0]));    
 9 
10 for(i=0; i<numRings; i++)
11 {
12     numPoints = pLinearRing->numPoints;
13     //指向pLinearRing的points数组的首个元素
14     pt = (Point*)(&(pLinearRing->points[0]));
15     
16     //遍历points数组
17     for(j = 0; j<numPoints; j++,pt++)
18     {
19         printf("%f,%f\n", point->x point->y);
20     }
21     
22     //遍历完成后pt指向points数组的末尾,即pLinearRing的末尾,也就是下一个LinearRing的开始
23     pLinearRing = (LinearRing*)pt;
24 }

 

 6) MultiPolygon
 1 int numPoints = 0;
 2 int numLinearRing = 0;
 3 int numPolygons = 0;
 4 int i=0, j=0, k=0;
 5 
 6 Point         *pt=NULL;
 7 LinearRing    *pLinearRing = NULL;
 8 WKBPolygon    *pWKBPolygon = NULL;
 9 
10 
11 numPolygons = pWKBMultiPolygon->numPolygons;
12 pWKBPolygon = (WKBPolygon*)(&(pWKBMultiPolygon->polygons[0]));
13 
14 for(i=0; i<numPolygons; i++)
15 {    
16     numLinearRing = pWKBPolygon->numRings;
17     pLinearRing = (auge::LinearRing*)(&(pWKBPolygon->rings[0]));    
18     
19     for(j=0; j<numLinearRing; j++)
20     {
21         numPoints = pLinearRing->numPoints;
22         pt = (Point*)(&(pLinearRing->points[0]));
23         
24         for(k = 0; k<numPoints; k++,pt++)
25         {
26             printf("%f,%f\n", pt->x pt->y);
27         }
28         
29         pLinearRing = (auge::LinearRing*)pt;
30     }
31 
32     pWKBPolygon = (auge::WKBPolygon*)pLinearRing;
33 }