地图通过切割后造成了瓦片,每个编号对于一个瓦片,瓦片能够是栅格数据也能够是矢量数据,栅格数据就是一张正方形图片,渲染时只须要将这张图片做为纹理贴到指定位置就行能够,栅格瓦片的缺点就是数据量大,缩放时失真,不能自由配置显示样式。这些缺点在矢量瓦片中都得以解决,矢量瓦片中使用矢量数据描述地图元素,经过渲染这些矢量数据造成地图,数据量很小,缩放的时候不会失真,能够在不一样视角展现,能够展现更丰富的高度信息,例如能够拔高建筑物。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
}
注意几何要素的实际坐标取决于坐标系和瓦片的范围。