地圖通過切割後造成了瓦片,每個編號對於一個瓦片,瓦片能夠是柵格數據也能夠是矢量數據,柵格數據就是一張正方形圖片,渲染時只須要將這張圖片做爲紋理貼到指定位置就行能夠,柵格瓦片的缺點就是數據量大,縮放時失真,不能自由配置顯示樣式。這些缺點在矢量瓦片中都得以解決,矢量瓦片中使用矢量數據描述地圖元素,經過渲染這些矢量數據造成地圖,數據量很小,縮放的時候不會失真,能夠在不一樣視角展現,能夠展現更豐富的高度信息,例如能夠拔高建築物。git
瓦片數據在地圖渲染的流程中包含:下載,解析,生成渲染Mesh數據,在全部,通常對瓦片數據格式的要求是,體積小,解析快,能夠配合不一樣的樣式生成不一樣的效果。github
Feature是幾何圖形數據和屬性的合集。例如點Feature 包含 x ,y 座標,和name等屬性。下面是Feature類型對應描述的地圖元素。shell
Feature | 常見地圖元素 |
點 | POI |
線 | 路網,邊界,水系骨架 |
面 | 區域,海洋,綠地,建築物 |
多點 | 點雲,熱力圖 |
多線 | 多線相同屬性的線 |
多面 | 多個相同屬性的面 |
3D模型 | 地圖上的3D元素,例如建築物模型 |
圖形數據和特性的屬性構成了數據模型,例如建築物的數據模型包含一個多邊形表明俯視輪廓,屬性中包含名稱,高度,類型(商業仍是住宅等)。不一樣地圖使用的數據模型不一樣,包含的信息豐富程度也不相同,可是基本的信息都很雷同,下面是常見的一些數據模型:json
地圖元素 | 模型信息 |
POI | 點數據,文本,重要度(用於POI碰撞),商標,類型 |
公路 | 線數據,名稱,道路等級,方向性,類型 |
鐵路 | 線數據,名稱,類型 |
水面 | 名稱 |
綠地 | 名稱 |
建築物 | 名稱,高度 |
邊界線 | 類型 |
在渲染實現中,一般是先不區分實際地圖元素,而是實現對每種類型Feature的渲染,而後經過不一樣的配置實現不一樣的現實效果。例如,公路,鐵路和邊界線都是線元素,只要實現線的渲染,在線的渲染實現中,線的顏色,寬度,實虛線均可以配置,這樣咱們經過不一樣的配置就能夠實現各類公路,鐵路,和邊界線的渲染。這些配置就是樣式。數據模型中屬性須要能關聯的一個特性的樣式,這樣咱們就能經過一組樣式配置來配置整個地圖了。不一樣的樣式組合就渲染出不一樣的地圖風格,例如百度地圖中的普通地圖和旅遊地圖。數據結構
Mapbox MVT 數據格式規格app
本文檔中的「必須」、「必須不」、「必備」、"應該"、「不該該」、「建議」、「能夠」、「可選」的含義參照RFC 2119。google
本文檔規定了一種節省存儲空間的矢量瓦片數據編碼格式。這種格式應用於客戶端或服務端高效渲染或查詢要素信息。編碼
矢量瓦片文件採用Google Protocol Buffers進行編碼。Google Protocol Buffers是一種兼容多語言、多平臺、易擴展的數據序列化格式。spa
矢量瓦片文件的後綴應該爲mvt
。例如,vector.mvt
。設計
矢量瓦片的MIME類型應該設置爲application/vnd.mapbox-vector-tile
。
矢量瓦片表示的是投影在正方形區塊上的數據。矢量瓦片不該該包含範圍和投影信息。解碼方被假定知道矢量瓦片的範圍和投影信息。
Web Mercator是默認的投影方式,Google tile scheme是默認的瓦片編號方式。二者一塊兒完成了與任意範圍、任意精度的地理區域的一一對應,例如https://example.com/17/65535/43602.mvt
。
矢量瓦片能夠用來表示任意投影方式、任意瓦片編號方案的數據。
這部份內容描述矢量瓦片的數據結構。讀者須要先了解矢量瓦片protobuf編碼方案文件中的結構定義。
矢量瓦片由一組命名的圖層構成。每一個圖層包含幾何要素和元數據信息。設計的圖層格式可以保證圖層數據可以在內存中按順序排列,由此在圖層組末尾添加一個新的圖層就不用更改已有的數據。
每塊矢量瓦片應該至少包含一個圖層。每一個圖層應該至少包含一個要素。
圖層必須包含一個version
字段表示此圖層所遵照的《矢量瓦片標準》的主版本號。例如,某個圖層遵照2.1版本的標準,那麼它的version
字段的值則爲整數2
。version
字段應該設定爲圖層的第一個字段。解碼器應該首先解析version
字段,以肯定是否可以解析該版本的圖層。當遇到一個未知版本的矢量瓦片圖層時,解碼器能夠嘗試去解析它,或者能夠跳過該圖層。以上兩種狀況下,解碼器都應該繼續解析後續的圖層。
圖層必須包含一個name
字段。每塊矢量瓦片必須不包含兩個或兩個以上的圖層具備相同name
值。在向一塊矢量瓦片添加一個新的圖層以前,編碼器必須檢查已有的name
值以防止重複。
圖層中的每一個要素能夠包含一個或多個key-value做爲它的元數據(見下文)。全部要素的key和value被分別索引爲兩個列表——keys
和values
——爲圖層中的全部要素所共享。
圖層keys
字段的每一個元素都是字符串。keys
字段包含了圖層中全部要素的key,而且每一個key能夠經過它在keys
列表中的索引號引用,第一個key的索引號是0 。keys
列表必須不包含兩個或兩個以上key是同樣的。
圖層values
字段的每一個元素是多種類型的值的編碼(見下文)。values
字段包含了圖層中全部要素的value,而且每一個value能夠經過它在values
列表中的索引號引用,第一個value的索引號是0 。values
列表必須不包含兩個或兩個以上value是同樣的。
爲了支持字符串型、布爾型、整型、浮點型多種類型的值,對value
字段的編碼包含了一組optional
字段。每一個value必須包含其中的一個字段。
圖層必須包含一個extent
字段,表示瓦片的寬度和高度,以整數表示。矢量瓦片中的幾何座標能夠超出extent
定義的範圍。超出extent
範圍的幾何要素被常常用來做爲緩衝區,以渲染重疊在多塊相鄰瓦片上的要素。
例如,若是一塊瓦片的extent
範圍是4096,那麼座標的單位是瓦片長寬的1/4096。座標0在瓦片的頂部或左邊緣,座標4096在瓦片的底部或右邊緣。座標從1到4095都是在瓦片內部,座標小於0或者大於4096在瓦片外部。座標(1,10)
或(4095,10)
在瓦片內部。座標(0,10)
或(4096,10)
在瓦片邊緣。座標(-1,10)
或(4097,10)
在瓦片外部。
每一個要素必須包含一個geometry
字段。
每一個要素必須包含一個type
字段,該字段將在幾何類型章節描述(4.3.4)。
每一個要素能夠包含一個tags
字段。若是存在屬於要素級別的元數據,應該存儲到tags
字段中。
每一個要素能夠包含一個id
字段。若是一個要素包含一個id
字段,那麼id
字段的值應該相對於圖層中的其餘要素是惟一的。
矢量瓦片中的幾何數據被定義爲屏幕座標系。瓦片的左上角(顯示默認如此)是座標系的原點。X軸向右爲正,Y軸向下爲正。幾何圖形中的座標必須爲整數。
幾何圖形被編碼爲要素的geometry
字段的一個32位無符號型整數序列。每一個整數是CommandInteger
或者ParameterInteger
。解碼器解析這些整數序列做爲生成幾何圖形的一系列有序操做。
指令涉及到的位置是相對於「遊標」的,即一個可重定義的點。對於要素中的第一條指令,遊標在座標系中的位置是(0,0)
。有些指定可以移動遊標,於是會影響到接下來執行的指令。
CommandInteger
指代所要執行的操做和執行的次數,分別以command ID和command count表示。
command ID以CommandInteger
最末尾的3個比特位表示,即從0到7。command count以CommandInteger
剩下的29個比特位表示,即0
到pow(2, 29) - 1
。
command ID、command count、和CommandInteger
三者能夠經過如下位運算相互轉換。
CommandInteger = (id & 0x7) | (count << 3)
id = CommandInteger & 0x7
count = CommandInteger >> 3
每一個command ID表示如下指令中的一種:
指令 | Id | 參數 | 參數個數 |
---|---|---|---|
MoveTo | 1 |
dX , dY |
2 |
LineTo | 2 |
dX , dY |
2 |
ClosePath | 7 |
無參數 | 0 |
指令 | ID | Count | CommandInteger | 二進制表示[Count][Id] |
---|---|---|---|---|
MoveTo | 1 |
1 |
9 |
[00000000 00000000 0000000 00001][001] |
MoveTo | 1 |
120 |
961 |
[00000000 00000000 0000011 11000][001] |
LineTo | 2 |
1 |
10 |
[00000000 00000000 0000000 00001][010] |
LineTo | 2 |
3 |
26 |
[00000000 00000000 0000000 00011][010] |
ClosePath | 7 |
1 |
15 |
[00000000 00000000 0000000 00001][111] |
指令的全部參數緊跟在ParameterInteger
以後。跟在CommandInteger
以後的ParameterIntegers
個數等於指令所須要參數的個數乘以指令執行的次數。例如,一條指示MoveTo
指令執行3次的CommandInteger
以後會跟隨6個ParameterIntegers
。
ParameterInteger
由zigzag方式編碼獲得,以使小負數和正數都被編碼爲小整數。將參數值編碼爲ParameterInteger
按如下公式轉換:
ParameterInteger = (value << 1) ^ (value >> 31)
參數值不支持大於pow(2,31) - 1
或-1 * (pow(2,31) - 1)
的數值。
如下的公式用來將ParameterInteger
解碼爲實際值:
value = ((ParameterInteger >> 1) ^ (-(ParameterInteger & 1)))
如下關於指令的描述中,遊標的初始位置定義爲座標(cX, cY)
,其中cX
指代遊標在X軸上的位置,cY
指代遊標在Y軸上的位置。
表示MoveTo
指令執行n
的ParameterInteger
必須當即接上n
對ParameterInteger
。對於(dX, dY)
參數:
(pX, pY)
,其中pX = cX + dX
和pY = cY + dY
。
(pX, pY)
。表示LineTo
指令執行n
的ParameterInteger
必須當即接上n
對ParameterInteger
。對於(dX, dY)
參數:
(cX, cY)
爲起點,(pX, pY)
爲終點的線段,其中pX = cX + dX
和pY = cY + dY
。
(pX, pY)
。對於任意一對(dX, dY)
,dX
和dY
必須不能同時爲0
.
每條ClosePath
指令必須只能執行一次而且無附帶參數。這條指令經過構造一條以遊標(cX, cY)
爲起點、當前環的起點爲終點的線段,閉合面要素的當前環。
這條指定不改變遊標的位置。
要素geometry
字段的type
的取值必須是GeomType
枚舉值之一。支持的幾何類型以下:
不支持GeometryCollection
類型。
本標準有意設置一個Unknown幾何類型。這種幾何類型能夠用來編碼試驗性的幾何類型。解碼器能夠選擇忽略這種幾何類型的要素。
POINT
幾何類型用來表示單點或多點幾何。每一個點幾何的指令序列必須包含一個MoveTo
指令,而且該指令的command count大於0。
若是POINT
幾何的MoveTo
的command count爲1,那麼必須將其解析爲單點;不然必須解析爲多點,指令後面的每對ParameterInteger
表示一個單點。
LINESTRING
幾何類型用來表示單線或多線幾何。線幾何的指令序列必須包含一個或多個下列序列:
MoveTo
指令,其command count爲1LineTo
指令,其command count大於0若是LINESTRING
的指令序列只包含1個MoveTo
指令,那麼必須將其解析爲單線;不然,必須將其解析爲多線,其中的每一個MoveTo
指令開始構造一條新線幾何。
POLYGON
幾何類型表示面或多面幾何,每一個面有且只有一個外環和零個或多個內環。面幾何的指令序列包含一個或多個下列序列:
ExteriorRing
InteriorRing
Each ExteriorRing
and InteriorRing
MUST consist of the following sequence: 每一個ExteriorRing
和InteriorRing
必須包含如下序列:
MoveTo
指令,其command count爲1LineTo
指令,其command count大於1ClosePath
指令一個外環被定義爲一個線性的環,當應用surveyor's formula,以多邊形的節點在瓦片座標系下的座標計算面積時,其面積爲正。在瓦片座標系下(X向右爲正,Y向下爲正),外環節點以順時針旋轉。
一個內環被定義爲一個線性的環,當應用surveyor's formula,以多邊形的節點在瓦片座標系下的座標計算面積時,其面積爲負。在瓦片座標系下(X向右爲正,Y向下爲正),內環節點以逆時針旋轉。
若是POLYGON
的指令序列只包含一個外環,那麼必須將其解析爲單面;不然,必須解析爲多面幾何,其中每一個外環表示一個新面的開始。若是面幾何包換內環,那麼必須將其編碼到所屬的外環以後。
線性環必須不包含異常點,例如自相交或自相切。在ClosePath
以前的座標不該該與線性環的起始點座標相同,由於會產生零長度的線段。線性環通過surveyor's formula計算的面積不該該爲0,由於這意味着環包含有異常點。
面幾何必須不能有內環相交,而且內環必須被包圍在內環之中。
假設示例點的座標爲:
表示它只須要一條指令:
編碼 : [ 9 50 34 ]
| | `> 解碼: ((34 >> 1) ^ (-(34 & 1))) = +17
| `> 解碼: ((50 >> 1) ^ (-(50 & 1))) = +25
| ===== 相對地 MoveTo(+25, +17) == 建立點 (25,17)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設多點要素的座標爲:
編碼須要兩條指令:
編碼 : [ 17 10 14 3 9 ]
| | | | `> 解碼: ((9 >> 1) ^ (-(9 & 1))) = -5
| | | `> 解碼: ((3 >> 1) ^ (-(3 & 1))) = -2
| | | === 相對地 MoveTo(-2, -5) == 建立點 (3,2)
| | `> 解碼: ((34 >> 1) ^ (-(34 & 1))) = +7
| `> 解碼: ((50 >> 1) ^ (-(50 & 1))) = +5
| ===== relative MoveTo(+25, +17) == 建立點 (25,17)
`> [00010 001] = command id 1 (MoveTo), command count 2
假設示例線要素的座標爲:
編碼須要3條指令:
編碼 : [ 9 4 4 18 0 16 16 0 ]
| | ==== 相對地 LineTo(+8, +0) == 鏈接到點 (10, 10)
| | ==== 相對地 LineTo(+0, +8) == 鏈接到點 (2, 10)
| `> [00010 010] = command id 2 (LineTo), command count 2
| === 相對地 MoveTo(+2, +2)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設示例要素的座標爲:
編碼須要如下指令:
編碼 : [ 9 4 4 18 0 16 16 0 9 17 17 10 4 8 ]
| | | | === 相對地 LineTo(+2, +4) == 鏈接到點 (3,5)
| | | `> [00001 010] = command id 2 (LineTo), command count 1
| | | ===== 相對地 MoveTo(-9, -9) == 新建一條線從 (1,1)
| | `> [00001 001] = command id 1 (MoveTo), command count 1
| | ==== 相對地 LineTo(+8, +0) == 鏈接到點 (10, 10)
| | ==== 相對地 LineTo(+0, +8) == 鏈接到點 (2, 10)
| `> [00010 010] = command id 2 (LineTo), command count 2
| === 相對地 MoveTo(+2, +2)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設示例面要素的座標爲:
編碼須要如下指令:
編碼 : [ 9 6 12 18 10 12 24 44 15 ]
| | `> [00001 111] command id 7 (ClosePath), command count 1
| | ===== 相對地 LineTo(+12, +22) == 鏈接到點 (20, 34)
| | ===== 相對地 LineTo(+5, +6) == 鏈接到點 (8, 12)
| `> [00010 010] = command id 2 (LineTo), command count 2
| ==== 相對地 MoveTo(+3, +6)
`> [00001 001] = command id 1 (MoveTo), command count 1
示例要素包含兩個多邊形,其中一個多邊形有一個洞。多邊形中的點以下。注意,多邊形中的點環繞順序很是重要,應爲這個順序被用來區別外環和內環。
編碼須要如下一系列指令:
要素屬性被編碼爲tag
字段中的一對對整數。在每對tag
中,第一個整數表示key在其所屬的layer
的keys
列表的中索引號(以0開始)。第二個整數表示value在其所屬的layer
的values
列表的中索引號(以0開始)。一個要素的全部key索引必須惟一,以保證要素中沒有重複的屬性項。每一個要素的tag
字段必須爲偶數。要素中的tag
字段包含的key索引號或value索引號必須不能大於或等於相應圖層中keys
或values
列表中的元素數目。
例如,一個GeoJSON格式的要素以下:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-8247861.1000836585,
4970241.327215323
]
},
"type": "Feature",
"properties": {
"hello": "world",
"h": "world",
"count": 1.23
}
},
{
"geometry": {
"type": "Point",
"coordinates": [
-8247861.1000836585,
4970241.327215323
]
},
"type": "Feature",
"properties": {
"hello": "again",
"count": 2
}
}
]
}
會被結構化爲:
layers {
version: 2
name: "points"
features: {
id: 1
tags: 0
tags: 0
tags: 1
tags: 0
tags: 2
tags: 1
type: Point
geometry: 9
geometry: 2410
geometry: 3080
}
features {
id: 2
tags: 0
tags: 2
tags: 2
tags: 3
type: Point
geometry: 9
geometry: 2410
geometry: 3080
}
keys: "hello"
keys: "h"
keys: "count"
values: {
string_value: "world"
}
values: {
double_value: 1.23
}
values: {
string_value: "again"
}
values: {
int_value: 2
}
extent: 4096
}
注意幾何要素的實際座標取決於座標系和瓦片的範圍。
MapBox MVT數據格式:https://github.com/jingsam/vector-tile-spec/blob/master/2.1/README_zh.md
本文檔中的「必須」、「必須不」、「必備」、"應該"、「不該該」、「建議」、「能夠」、「可選」的含義參照RFC 2119。
本文檔規定了一種節省存儲空間的矢量瓦片數據編碼格式。這種格式應用於客戶端或服務端高效渲染或查詢要素信息。
矢量瓦片文件採用Google Protocol Buffers進行編碼。Google Protocol Buffers是一種兼容多語言、多平臺、易擴展的數據序列化格式。
矢量瓦片文件的後綴應該爲mvt
。例如,vector.mvt
。
矢量瓦片的MIME類型應該設置爲application/vnd.mapbox-vector-tile
。
矢量瓦片表示的是投影在正方形區塊上的數據。矢量瓦片不該該包含範圍和投影信息。解碼方被假定知道矢量瓦片的範圍和投影信息。
Web Mercator是默認的投影方式,Google tile scheme是默認的瓦片編號方式。二者一塊兒完成了與任意範圍、任意精度的地理區域的一一對應,例如https://example.com/17/65535/43602.mvt
。
矢量瓦片能夠用來表示任意投影方式、任意瓦片編號方案的數據。
這部份內容描述矢量瓦片的數據結構。讀者須要先了解矢量瓦片protobuf編碼方案文件中的結構定義。
矢量瓦片由一組命名的圖層構成。每一個圖層包含幾何要素和元數據信息。設計的圖層格式可以保證圖層數據可以在內存中按順序排列,由此在圖層組末尾添加一個新的圖層就不用更改已有的數據。
每塊矢量瓦片應該至少包含一個圖層。每一個圖層應該至少包含一個要素。
圖層必須包含一個version
字段表示此圖層所遵照的《矢量瓦片標準》的主版本號。例如,某個圖層遵照2.1版本的標準,那麼它的version
字段的值則爲整數2
。version
字段應該設定爲圖層的第一個字段。解碼器應該首先解析version
字段,以肯定是否可以解析該版本的圖層。當遇到一個未知版本的矢量瓦片圖層時,解碼器能夠嘗試去解析它,或者能夠跳過該圖層。以上兩種狀況下,解碼器都應該繼續解析後續的圖層。
圖層必須包含一個name
字段。每塊矢量瓦片必須不包含兩個或兩個以上的圖層具備相同name
值。在向一塊矢量瓦片添加一個新的圖層以前,編碼器必須檢查已有的name
值以防止重複。
圖層中的每一個要素能夠包含一個或多個key-value做爲它的元數據(見下文)。全部要素的key和value被分別索引爲兩個列表——keys
和values
——爲圖層中的全部要素所共享。
圖層keys
字段的每一個元素都是字符串。keys
字段包含了圖層中全部要素的key,而且每一個key能夠經過它在keys
列表中的索引號引用,第一個key的索引號是0 。keys
列表必須不包含兩個或兩個以上key是同樣的。
圖層values
字段的每一個元素是多種類型的值的編碼(見下文)。values
字段包含了圖層中全部要素的value,而且每一個value能夠經過它在values
列表中的索引號引用,第一個value的索引號是0 。values
列表必須不包含兩個或兩個以上value是同樣的。
爲了支持字符串型、布爾型、整型、浮點型多種類型的值,對value
字段的編碼包含了一組optional
字段。每一個value必須包含其中的一個字段。
圖層必須包含一個extent
字段,表示瓦片的寬度和高度,以整數表示。矢量瓦片中的幾何座標能夠超出extent
定義的範圍。超出extent
範圍的幾何要素被常常用來做爲緩衝區,以渲染重疊在多塊相鄰瓦片上的要素。
例如,若是一塊瓦片的extent
範圍是4096,那麼座標的單位是瓦片長寬的1/4096。座標0在瓦片的頂部或左邊緣,座標4096在瓦片的底部或右邊緣。座標從1到4095都是在瓦片內部,座標小於0或者大於4096在瓦片外部。座標(1,10)
或(4095,10)
在瓦片內部。座標(0,10)
或(4096,10)
在瓦片邊緣。座標(-1,10)
或(4097,10)
在瓦片外部。
每一個要素必須包含一個geometry
字段。
每一個要素必須包含一個type
字段,該字段將在幾何類型章節描述(4.3.4)。
每一個要素能夠包含一個tags
字段。若是存在屬於要素級別的元數據,應該存儲到tags
字段中。
每一個要素能夠包含一個id
字段。若是一個要素包含一個id
字段,那麼id
字段的值應該相對於圖層中的其餘要素是惟一的。
矢量瓦片中的幾何數據被定義爲屏幕座標系。瓦片的左上角(顯示默認如此)是座標系的原點。X軸向右爲正,Y軸向下爲正。幾何圖形中的座標必須爲整數。
幾何圖形被編碼爲要素的geometry
字段的一個32位無符號型整數序列。每一個整數是CommandInteger
或者ParameterInteger
。解碼器解析這些整數序列做爲生成幾何圖形的一系列有序操做。
指令涉及到的位置是相對於「遊標」的,即一個可重定義的點。對於要素中的第一條指令,遊標在座標系中的位置是(0,0)
。有些指定可以移動遊標,於是會影響到接下來執行的指令。
CommandInteger
指代所要執行的操做和執行的次數,分別以command ID和command count表示。
command ID以CommandInteger
最末尾的3個比特位表示,即從0到7。command count以CommandInteger
剩下的29個比特位表示,即0
到pow(2, 29) - 1
。
command ID、command count、和CommandInteger
三者能夠經過如下位運算相互轉換。
CommandInteger = (id & 0x7) | (count << 3)
id = CommandInteger & 0x7
count = CommandInteger >> 3
每一個command ID表示如下指令中的一種:
指令 | Id | 參數 | 參數個數 |
---|---|---|---|
MoveTo | 1 |
dX , dY |
2 |
LineTo | 2 |
dX , dY |
2 |
ClosePath | 7 |
無參數 | 0 |
指令 | ID | Count | CommandInteger | 二進制表示[Count][Id] |
---|---|---|---|---|
MoveTo | 1 |
1 |
9 |
[00000000 00000000 0000000 00001][001] |
MoveTo | 1 |
120 |
961 |
[00000000 00000000 0000011 11000][001] |
LineTo | 2 |
1 |
10 |
[00000000 00000000 0000000 00001][010] |
LineTo | 2 |
3 |
26 |
[00000000 00000000 0000000 00011][010] |
ClosePath | 7 |
1 |
15 |
[00000000 00000000 0000000 00001][111] |
指令的全部參數緊跟在ParameterInteger
以後。跟在CommandInteger
以後的ParameterIntegers
個數等於指令所須要參數的個數乘以指令執行的次數。例如,一條指示MoveTo
指令執行3次的CommandInteger
以後會跟隨6個ParameterIntegers
。
ParameterInteger
由zigzag方式編碼獲得,以使小負數和正數都被編碼爲小整數。將參數值編碼爲ParameterInteger
按如下公式轉換:
ParameterInteger = (value << 1) ^ (value >> 31)
參數值不支持大於pow(2,31) - 1
或-1 * (pow(2,31) - 1)
的數值。
如下的公式用來將ParameterInteger
解碼爲實際值:
value = ((ParameterInteger >> 1) ^ (-(ParameterInteger & 1)))
如下關於指令的描述中,遊標的初始位置定義爲座標(cX, cY)
,其中cX
指代遊標在X軸上的位置,cY
指代遊標在Y軸上的位置。
表示MoveTo
指令執行n
的ParameterInteger
必須當即接上n
對ParameterInteger
。對於(dX, dY)
參數:
(pX, pY)
,其中pX = cX + dX
和pY = cY + dY
。
(pX, pY)
。表示LineTo
指令執行n
的ParameterInteger
必須當即接上n
對ParameterInteger
。對於(dX, dY)
參數:
(cX, cY)
爲起點,(pX, pY)
爲終點的線段,其中pX = cX + dX
和pY = cY + dY
。
(pX, pY)
。對於任意一對(dX, dY)
,dX
和dY
必須不能同時爲0
.
每條ClosePath
指令必須只能執行一次而且無附帶參數。這條指令經過構造一條以遊標(cX, cY)
爲起點、當前環的起點爲終點的線段,閉合面要素的當前環。
這條指定不改變遊標的位置。
要素geometry
字段的type
的取值必須是GeomType
枚舉值之一。支持的幾何類型以下:
不支持GeometryCollection
類型。
本標準有意設置一個Unknown幾何類型。這種幾何類型能夠用來編碼試驗性的幾何類型。解碼器能夠選擇忽略這種幾何類型的要素。
POINT
幾何類型用來表示單點或多點幾何。每一個點幾何的指令序列必須包含一個MoveTo
指令,而且該指令的command count大於0。
若是POINT
幾何的MoveTo
的command count爲1,那麼必須將其解析爲單點;不然必須解析爲多點,指令後面的每對ParameterInteger
表示一個單點。
LINESTRING
幾何類型用來表示單線或多線幾何。線幾何的指令序列必須包含一個或多個下列序列:
MoveTo
指令,其command count爲1LineTo
指令,其command count大於0若是LINESTRING
的指令序列只包含1個MoveTo
指令,那麼必須將其解析爲單線;不然,必須將其解析爲多線,其中的每一個MoveTo
指令開始構造一條新線幾何。
POLYGON
幾何類型表示面或多面幾何,每一個面有且只有一個外環和零個或多個內環。面幾何的指令序列包含一個或多個下列序列:
ExteriorRing
InteriorRing
Each ExteriorRing
and InteriorRing
MUST consist of the following sequence: 每一個ExteriorRing
和InteriorRing
必須包含如下序列:
MoveTo
指令,其command count爲1LineTo
指令,其command count大於1ClosePath
指令一個外環被定義爲一個線性的環,當應用surveyor's formula,以多邊形的節點在瓦片座標系下的座標計算面積時,其面積爲正。在瓦片座標系下(X向右爲正,Y向下爲正),外環節點以順時針旋轉。
一個內環被定義爲一個線性的環,當應用surveyor's formula,以多邊形的節點在瓦片座標系下的座標計算面積時,其面積爲負。在瓦片座標系下(X向右爲正,Y向下爲正),內環節點以逆時針旋轉。
若是POLYGON
的指令序列只包含一個外環,那麼必須將其解析爲單面;不然,必須解析爲多面幾何,其中每一個外環表示一個新面的開始。若是面幾何包換內環,那麼必須將其編碼到所屬的外環以後。
線性環必須不包含異常點,例如自相交或自相切。在ClosePath
以前的座標不該該與線性環的起始點座標相同,由於會產生零長度的線段。線性環通過surveyor's formula計算的面積不該該爲0,由於這意味着環包含有異常點。
面幾何必須不能有內環相交,而且內環必須被包圍在內環之中。
假設示例點的座標爲:
表示它只須要一條指令:
編碼 : [ 9 50 34 ]
| | `> 解碼: ((34 >> 1) ^ (-(34 & 1))) = +17
| `> 解碼: ((50 >> 1) ^ (-(50 & 1))) = +25
| ===== 相對地 MoveTo(+25, +17) == 建立點 (25,17)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設多點要素的座標爲:
編碼須要兩條指令:
編碼 : [ 17 10 14 3 9 ]
| | | | `> 解碼: ((9 >> 1) ^ (-(9 & 1))) = -5
| | | `> 解碼: ((3 >> 1) ^ (-(3 & 1))) = -2
| | | === 相對地 MoveTo(-2, -5) == 建立點 (3,2)
| | `> 解碼: ((34 >> 1) ^ (-(34 & 1))) = +7
| `> 解碼: ((50 >> 1) ^ (-(50 & 1))) = +5
| ===== relative MoveTo(+25, +17) == 建立點 (25,17)
`> [00010 001] = command id 1 (MoveTo), command count 2
假設示例線要素的座標爲:
編碼須要3條指令:
編碼 : [ 9 4 4 18 0 16 16 0 ]
| | ==== 相對地 LineTo(+8, +0) == 鏈接到點 (10, 10)
| | ==== 相對地 LineTo(+0, +8) == 鏈接到點 (2, 10)
| `> [00010 010] = command id 2 (LineTo), command count 2
| === 相對地 MoveTo(+2, +2)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設示例要素的座標爲:
編碼須要如下指令:
編碼 : [ 9 4 4 18 0 16 16 0 9 17 17 10 4 8 ]
| | | | === 相對地 LineTo(+2, +4) == 鏈接到點 (3,5)
| | | `> [00001 010] = command id 2 (LineTo), command count 1
| | | ===== 相對地 MoveTo(-9, -9) == 新建一條線從 (1,1)
| | `> [00001 001] = command id 1 (MoveTo), command count 1
| | ==== 相對地 LineTo(+8, +0) == 鏈接到點 (10, 10)
| | ==== 相對地 LineTo(+0, +8) == 鏈接到點 (2, 10)
| `> [00010 010] = command id 2 (LineTo), command count 2
| === 相對地 MoveTo(+2, +2)
`> [00001 001] = command id 1 (MoveTo), command count 1
假設示例面要素的座標爲:
編碼須要如下指令:
編碼 : [ 9 6 12 18 10 12 24 44 15 ]
| | `> [00001 111] command id 7 (ClosePath), command count 1
| | ===== 相對地 LineTo(+12, +22) == 鏈接到點 (20, 34)
| | ===== 相對地 LineTo(+5, +6) == 鏈接到點 (8, 12)
| `> [00010 010] = command id 2 (LineTo), command count 2
| ==== 相對地 MoveTo(+3, +6)
`> [00001 001] = command id 1 (MoveTo), command count 1
示例要素包含兩個多邊形,其中一個多邊形有一個洞。多邊形中的點以下。注意,多邊形中的點環繞順序很是重要,應爲這個順序被用來區別外環和內環。
編碼須要如下一系列指令:
要素屬性被編碼爲tag
字段中的一對對整數。在每對tag
中,第一個整數表示key在其所屬的layer
的keys
列表的中索引號(以0開始)。第二個整數表示value在其所屬的layer
的values
列表的中索引號(以0開始)。一個要素的全部key索引必須惟一,以保證要素中沒有重複的屬性項。每一個要素的tag
字段必須爲偶數。要素中的tag
字段包含的key索引號或value索引號必須不能大於或等於相應圖層中keys
或values
列表中的元素數目。
例如,一個GeoJSON格式的要素以下:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-8247861.1000836585,
4970241.327215323
]
},
"type": "Feature",
"properties": {
"hello": "world",
"h": "world",
"count": 1.23
}
},
{
"geometry": {
"type": "Point",
"coordinates": [
-8247861.1000836585,
4970241.327215323
]
},
"type": "Feature",
"properties": {
"hello": "again",
"count": 2
}
}
]
}
會被結構化爲:
layers {
version: 2
name: "points"
features: {
id: 1
tags: 0
tags: 0
tags: 1
tags: 0
tags: 2
tags: 1
type: Point
geometry: 9
geometry: 2410
geometry: 3080
}
features {
id: 2
tags: 0
tags: 2
tags: 2
tags: 3
type: Point
geometry: 9
geometry: 2410
geometry: 3080
}
keys: "hello"
keys: "h"
keys: "count"
values: {
string_value: "world"
}
values: {
double_value: 1.23
}
values: {
string_value: "again"
}
values: {
int_value: 2
}
extent: 4096
}
注意幾何要素的實際座標取決於座標系和瓦片的範圍。