空間數據格式是空間數據的基礎,定義了如何在計算機中表達空間數據。各個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的完整數據結構如下所示

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 }