17. OpenStreetMap可更新矢量瓦片
学士学位论文 计算机科学系 应用科学大学 Rapperswil 2016年春季
Authors: 卢卡斯·马蒂内利,曼努埃尔·罗斯
Advisor: 斯特凡·凯勒教授
OSM2Vector瓦片的项目提供了免费的、全球的、定期更新的矢量瓦片,任何离线或在他们自己的服务器上的人都可以使用它们来创建最先进的地图。矢量瓦片已经过渲染,可以完全脱机使用,为网络和移动开发者提供了新的可能性。
这篇学士论文对OSM2Vector瓦片进行了改进,增加了对全球预渲染的支持,使矢量瓦片保持最新,并显著提高了质量,成为OpenStreetMap最好的矢量瓦片源代码。
已经创建了一个开放的工作流程,使矢量瓦片与OpenStreetMap贡献者每天添加的数以百万计的更改保持同步,并且可以跨多个主机进行缩放,以生成覆盖全球的矢量瓦片。由于与MapboxStreets的兼容性,开发人员可以将他们的矢量瓦片源代码切换到他们自己的瓦片服务器,从而避免供应商锁定并降低成本。
由于矢量瓦片可以通过下载获得,因此可以为桌面和移动设备创建一个离线版本的OpenStreetMap。这将为想要创建需要本地地图的应用程序的移动开发人员提供新的可能性。
有关更多信息,请访问项目网站http://osm2vectortiles.org.
情况
数字制图正在向矢量瓦片发展,以创建更具交互性和分辨率的独立制图。数据的矢量表示被发送到地图客户端,而不是将地图的图像传送到客户端。
几个矢量瓦片提供程序(如MapBox)打开创建矢量瓦片的过程,但仍然拥有矢量瓦片数据。希望独立于第三方服务或在其应用程序中具有有限互联网接入的开发人员和制图员需要免费的全球矢量瓦片来创建下一代地图应用程序。
方法
OSM2Vector瓦片项目致力于通过提供免费的、高质量的、不附带任何条件的矢量瓦片来推动映射向前发展。为了使开发人员独立于提供者,可以使用他们选择的瓦片服务器下载和托管矢量瓦片。此方法不同于所有其他矢量瓦片提供程序,并将为桌面和移动开发人员创建离线地图应用程序提供新的可能性。
改进OSM2Vector瓦片的过程是完全开放的,社区的反馈和需求一直是改进项目的基石,大多数功能请求和错误报告都来自实际用户。
结果
这篇论文的结果是在项目网站e http://osm2vectortiles.org上提供了全球范围内可下载的矢量瓦片,并提供了针对200多个国家和600个城市的摘录。矢量瓦片与最新的MapboxStreetsv7矢量瓦片兼容,允许人们将他们使用MapboxStudio创建的视觉样式与OSM2矢量瓦片一起使用。
创建矢量瓦片%s的工作流程可供每个人使用,并可用于其他项目。该工作流可以通过添加更多的工作者机器来线性扩展,并且是实现具有全局覆盖的离线矢量瓦片的独特方法。
矢量瓦片可以通过连续应用最新的OpenStreetMap更改并仅重新渲染地球上受这些更改影响的部分来保持与数据同步。这使得能够提供可下载的矢量瓦片,同时仍然使数据保持最新。
OSM2Vector瓦片的项目已经在几个实际项目中使用,通过进一步推动该项目,本文的结果是一个活生生的开源项目,有望在这篇学士论文中幸存下来。
我们要感谢以下人士对本论文的支持和贡献。
感谢IFS软件研究所的StefanKeller教授对定期会议的支持,与OSM社区的联系,以及在检查这篇论文方面的时间和努力。
ImreSamu,OpenStreetMap,为维护该项目提供帮助,提供有关技术挑战和代码贡献的建议。
KlokanTechnologiesgmbh的PetrPridal博士,负责启动该项目,并捐赠必要的云和cdn基础设施来生产和托管矢量瓦片
1. INTRODUCTION
1.1 愿景
矢量地图(Vector瓦片)是网络和移动地图的未来。下一代地图只有免费和开放的矢量瓦片源才有可能。OSM2矢量瓦片的目标是通过提供使用开放过程产生的、完全免费并且可以脱机使用的矢量瓦片来推进映射。在该项目现有实际用户的鼓励下,需要进一步改进,以满足使用该项目的开发人员和制图员在不建立自己的渲染Ing管道的情况下创建自定义OSM地图的要求。
1.2 问题
这篇学士论文的重点在于需要解决的三个主要问题。
定义MapBox矢量瓦片(第3章)
矢量瓦片需要满足某些制图标准,以使制图员能够创建高质量的地图。从头开始创建全球底图是一项巨大的任务,其中有几个有趣的问题,如标签放置、重要性排序和将正确的数据放在较小的空间中。专注于质量和与MapboxStreetsv7的兼容性使该项目真正适用于期望高质量地图的终端用户,并让现有用户更容易切换到OSM2Vector瓦片。
可扩展的渲染流程(第四章)
全局矢量瓦片s应该在合理的时间框架内进行渲染,以满足项目截止日期,并使开发人员能够快速迭代矢量瓦片s。瓦片s的绝对数量使得单个进程不可能对整个行星进行渲染。通过将进程分布在多台机器上,可以显着减少渲染在地球上运行的时间,只受可用基础设施数量的限制。该问题的解决方案将作为如何分发瓦片渲染流水线和启用具有全局覆盖的矢量瓦片的示例。
可更新矢量瓦片s(第5章)
OpenStreetMap贡献者每天添加多达300万个节点[7]。使地图保持最新对于矢量瓦片的用户和贡献者具有重要意义。矢量瓦片s应该以规则的间隔释放。然而,由于基础设施成本的原因,使用可扩展的渲染过程重新渲染整个星球是不可行的。通过预先计算将要更改的瓦片,并且仅渲染那些瓦片,一台机器可以使矢量瓦片保持最新,从而使项目长期可持续。
1.3 前期研究论文
OSM2Vector瓦片的项目起源于2015年秋季学期的上一篇研究论文,与本科论文具有相同的愿景,即允许任何人创建自定义开放街道地图,无需管理复杂的基础设施。
论文研究成果
- 生成矢量瓦片的工作流程(不是针对整个星球的渲染进行缩放)
- Mapbox Streets v5兼容矢量瓦片,瑞士
本论文的研究范围是创建一个基于OpenStreetMap数据生成矢量瓦片的可重复工作流。论文的研究重点在于解决小比例尺MapBoxStreetsv5的创建和实施问题(第3章),并为瑞士提供了预渲染格式的矢量瓦片数据。
此工作流旨在单台计算机上运行,并不是为了扩展整个星球的渲染(第4章)或保持矢量瓦片的最新(第4章)。
1.4 真实使用案例
OSM2Vector瓦片已经在实际工程中使用,证实了这种工程的需求。这些示例显示了Pre渲染edVector瓦片的潜在用例和客户。
-
MapHub.net允许您创建交互式可自定义地图来组织您自己的地图地理数据。它正在使用基于OSM2Vector瓦片的底图来为其用户提供各种底图可供选择。
-
梅克伦堡县地理信息系统的地理门户结合使用osm2矢量瓦片以自定义数据为底图,将重要信息呈现给市民。
-
赫尔辛基地区交通局(赫尔辛基地区交通局)正在使用osm2矢量瓦片作为来源具有自定义样式,可作为Digitransit平台的一部分向其他开发人员提供地图服务。
本章描述了贯穿全文的基本概念。
2. THEORY
本章描述了贯穿全文的基本概念。
2.1 OpenStreetMap数据模型
OpenStreetMap的数据模型由节点、方式和关系类型的对象组成。节点定义空间中的点,方式定义线性特征,关系定义对象如何相互关联[6]。
每个对象都可以有一个或多个与其关联的标签。标签定义了某个对象的含义。标记由键/值对组成,例如,标记Natural=wood用于定义树木覆盖的区域。OpenStreetMap标签没有严格的定义,用户可以添加自己的标签,但应该遵循许多约定。
半结构化的OpenStreetMap数据模型被转换为结构化的数据库模式,如第3节所述。2.1.节点、方式和关系被转换为真实的几何图形。例如,一条路之所以变成多边形,是因为它是共享第一个和最后一个节点的封闭路[4]。
2.2 矢量瓦片
不是像浏览器或手机那样将地图图像发送到客户端,而是只将数据的矢量表示发送到客户端,客户端使用的数据更少,并且允许更具交互性、动态性和分辨率独立的制图。这只有在客户端拥有更强大的硬件并且能够自己渲染地图的情况下才有可能。
Google早在2005年就引入了XYZ平铺方案[8],因为它不能按客户的视点提供地图图像的可伸缩性。其思想是将地图图像划分为一个网格,如图3所示,其中客户端通过使用瓦片INDIZES而不是坐标来请求幂等光栅图像。这允许在浏览器和服务器端进行缓存,并带来更流畅的地图体验。同样的方法也可以应用于矢量数据。矢量数据被切片为瓦片,而不是传递整个视口的矢量数据。
向量瓦片包含了特定瓦片所需要的所有几何和元数据。这使得它们比提供栅格瓦片更灵活,因为可以在飞行中应用不同的样式。例如基于浏览器语言偏好的特定城市标签就可以显示出来。
2.3 MapBox矢量瓦片规范
MapBox矢量瓦片规范定义了如何使用协议缓冲区对瓦片d矢量数据进行编码[14]。关于矢量瓦片的编码和内部结构的更多细节可以在规范[18]中找到。
矢量瓦片中的数据结构化为图层和要素。矢量瓦片可以有多个图层,例如道路、土地使用或水(在第8节中详细说明)。2)。每个图层由一个或多个要素组成,并且必须具有唯一的名称。要素包含几何图形字段(点、线串或多边形类型)和元数据(标记),例如标签转换。元数据键值对以键和值数组的形式存储在层中。要素上的标记仅通过其索引引用键和值。这有助于保持较小的文件大小,因为只需要存储唯一的值和键,并且可以由多个功能引用。键只能是字符串,而值可以有不同的类型,如字符串、双精度或整数。
范围字段定义瓦片坐标(矢量瓦片分辨率)的宽度和高度,这与编码要素的几何图形相关,如图5所示。为OSM2矢量瓦片的分辨率选择为4096个坐标单位。
几何图形的地理坐标将转换为矢量瓦片内的相对坐标。矢量瓦片被编码为用于虚拟笔(渲染ING客户端)的命令。从图5绘制多边形将产生清单1中的命令。
-
移动到起点(3,1)相对到左上角
-
从当前钢笔位置到(3、3)。由于目标位置是相对于当前位置进行编码的,所以编码的几何图形占用较少的空间。
-
从当前位置绘制直线(6,4)至(4,2)
-
当前位置的闭合路径(2,6)具有上次使用的起点(3,1)
2.4 XYZ坐标模式
对于向量瓦片的拼接,已经使用了XYZ编号模式。瓦片是在三维坐标系( x / y / z )中组织的,其中x和y代表轴,z代表缩放级。当用户缩放到地图中时,每个瓦片被瓦片内的四个孩子替换。
mercator投影中的地图分为x轴和y轴。x轴从0到达2z ( 从地图左至右边 ),y轴从0到达2z ( 地图从上到下边缘 )。
3. DEFINING MAPBOX VECTOR TILES
关于矢量瓦片的内容的主要要求是与MapBox的矢量瓦片兼容。这使得人们可以无缝地切换到OSM2Vector瓦片,并使用与MapboxStudio创建的相同视觉样式。
3.1 方法
MapBox的瓦片集被称为MapboxStreets。MapBox提供了有关MapBoxStreets矢量瓦片中包含哪些数据的详细文档。该文档包含定义图层可以具有的属性的图层引用。但是,数据显示的缩放级别以及描述数据的penStreetMap标记和约束都没有公开记录。为了能够对MapboxStreets进行逆向工程,必须通过分析官方MapBoxStreets矢量瓦片在不同的缩放级别来检索这些信息。在一个迭代且耗时的过程中,映射和查询不断改进,直到矢量瓦片输出与Mapbox街道的数据非常匹配。
3.2 实施
本节介绍生成MapBox街道兼容矢量瓦片所需实现的主要组件
3.2.1 导入地图
Imposm3[16]用于将OpenStreetMap数据导入PostgreSQL数据库。Imposm3满足过滤和映射OpenStreetMap数据的两个目的。
过滤数据
该映射允许通过标签显式过滤,并定义哪些数据进口的。这一点很重要,因为矢量瓦片中只包含所有OpenStreetMap数据的子集,因此不需要导入所有OpenStreetMap数据。
映射数据
该映射允许将OpenStreetMap键/值对映射到某个从半结构化数据创建结构化和有组织架构的数据库表。它负责从OpenStreetMap数据模型构建实际的几何图形(第2节。1)。
清单2中的示例定义将带有键Building的OpenStreetMap标记和与该键相关联的任何值映射到表building_polygon中。BUILDING_POLYGON表具有id、geometrym、Underlow、Timestamp和TYPE列。数据库中的地下列源自与OpenStreetMap关键字建筑:标高:地下相关联的规格化值。
在导入过程中,Imposm3会将OpenStreetMap节点、方式和关系转换为点、线串或多边形等几何体类型之一。映射是该项目最重要的方面之一,它映射了400多个单独的标签。
3.2.2 缩放级别视图
在导入过程之后,矢量瓦片所需的所有OpenStreetMap数据都存储在数据库中。由于在给定的缩放级别上只显示表中数据的子集,因此为每个缩放级别和层创建了SQL视图。缩放级别视图将表过滤到在给定缩放级别上显示的行。
图8在左侧显示了缩放级别为13的建筑层,在右侧显示了缩放级别为14的同一层。在缩放级别13上,仅在缩放级别14上示出的数据的子集是可见的。这是使用缩放级别视图提供有关更高缩放级别的更多详细信息的经典示例。
清单3显示了两个缩放级别上的SQL视图的定义。视图building_z13的查询中的WHERE子句将行过滤到面积大于1700的建筑物。这就是图8右侧显示的建筑较少的原因。
此外,缩放级别视图有助于分离保存实际数据和层定义的数据库表。例如,如果将新数据添加到图层中,这将非常有用,因为只需要修改导入映射和缩放级别视图。
3.2.3 层定义
源项目包含向量瓦片%s内的层的定义。该定义包含用于访问数据库的元数据和返回该层的必要数据的查询。清单4显示了层构建的定义。该查询不直接访问数据库表BUILDING_POLYGON。相反,它查询缩放级别视图Building_z13和Building_z14。
层定义用作向量瓦片渲染er(Mapnik)的输入。瓦片渲染er将执行每个分母的每个层查询,并替换诸如!瓦片_denominator!这样的表达式!(缩放级别)和!bbox!(瓦片的范围)与当前瓦片的值。如果对缩放级别为12的瓦片执行清单4中的查询,则不会返回任何数据,因为WHERE子句在两种情况下都不匹配。而如果其在缩放级别13上的瓦片上执行,则缩放级别视图Building_z13的所有数据将被包括在层构建中。
3.2.4 数据库表、缩放级别视图和图层之间的关系
图10显示了数据库表、缩放级别视图和层是如何相互关联的。此体系结构有助于组织数据库内的OpenStreetMap数据,并提供了单独优化单个缩放级别的可能性。图10中的箭头描述了数据流。
3.3 问题与优化
在地图的开发过程中,发现了一些问题,并进行了优化。本节详细解释了最有趣的问题。
3.3.1 避免在缩放级别视图中进行代价高昂的转换
缩放级别视图的目的是对数据进行过滤操作,使其仅包含显示在特定缩放级别上的行。在这些视图中应该避免昂贵的计算或转换,或者在预处理步骤中进行。
例如,有多个将多边形几何体转换为点几何体的标签层,由于从多边形计算质心的成本很高,这样的变换会导致较差的渲染性能。
这是因为每次执行层查询时,视图的所有行都会被转换,即使渲染ed瓦片只需要一部分数据(图12)。因此,选择正确的行并只在最小的可能子集上执行转换会产生更好的性能(图11)。
3.3.2 分类功能
OpenStreetMap包含映射到真实对象的标签的复杂分类。标签被组织成层,但是制图员需要另一个抽象级别来设置要素组的样式。例如,设计师希望将所有公园的颜色设置为绿色,而不是单独设置狗公园、花园和游乐场等标签的样式。因此,紧密相关的标签被分组在一起并存储在class字段中。此过程称为分类,本质上是将多个标记值映射到单个值。
这些分类涵盖400多个单独的标记,分为100多个组,并由SQL函数实现,如清单5所示。这些类定义是用基于YAML的格式,从中生成SQL分类函数。
清单5显示了LayerLanduse的简化类函数。它将类型值作为输入,并返回正确的类值。
3.3.3 OpenStreetMapID转换
OpenStreetMap的数据模型由节点、方式和关系组成。每个对象都分配有自己的OSMID。此ID在对象类型中不是唯一的。因此,可以找到三个具有相同id但具有不同对象类型的对象。
虽然这对于OpenStreetMap非常有效,但这会带来问题,因为在导入过程中,这些OpenStreetMap对象会转换为PostGIS几何图形。不同类型的对象可以转换为相同的PostGIS几何体,因此它们的ID会发生冲突。
为了避免这种情况,需要根据表1转换ID,以使OSMID在矢量瓦片[17]内唯一。
3.3.4 放置标签等级计算
等级对于确定应以哪个缩放级别显示哪些地点非常重要。NaturalEarth数据库包含有人类分配的标尺的地点,是更高质量标签的最重要来源(尽管人口很少,但历史名胜可能要重要得多)。此数据集与导入的OpenStreetMap数据合并。它们还可用于在较低的缩放级别限制密度,以降低数据密度。使用标尺和其他信息(如地点类型和人口),计算称为localranch的实际排名。图13中可以看到一个本地排名计算的示例(本地排名表示为圆圈内的数字)。
算法
将行星文件从缩放级别0渲染到缩放级别14需要P14瓦片%s要进行渲染编辑。由于两个原因,渲染不再可能连续生产如此数量的瓦片。
-
渲染Ing过程可能会失败,并且进度会丢失
-
单个工作进程需要大约276天的时间才能使用渲染命令每小时54000瓦片的吞吐量
为了解决这些问题,第4节中描述了两种测量方法。1和第4节。已经有2个人被带走了。
4. SCALABLE RENDERING PROCESS
4.1 将渲染进程拆分为作业
渲染ING进程(MAPNIK)将给定边界框内的渲染%s瓦片%s放入SQLite数据库(MB瓦片%s)。为了适应该过程,需要将全局边界框划分为许多较小的边界框,并且在该过程结束时,需要将许多小型SQLite数据库合并到一个大型行星SQLite数据库中。因此,作业的单位是从XYZ瓦片索引(金字塔作业第4节)派生的边界框。1.1)或作业列表(列出瓦片第4节1.2)。
4.1.1 金字塔作业
为了在世界范围内将渲染的工作划分为相等的部分,XYZ坐标模式在第2节中描述。4是用来把行星分成几个子金字塔的。金字塔作业意味着工作人员不仅需要渲染给定的瓦片索引,而且需要将所有后代瓦片降低到最大缩放级别(整个瓦片子金字塔)。
示例
给定作业缩放级别z=8和最大缩放级别Z=14,行星被划分为48个作业。这意味着每个子金字塔任务包括以缩放级别8对来自渲染的所有后代瓦片进行缩放(瓦片)。因此,每个作业由P6组成i=04i=5461瓦片需要被渲染ed。
4.1.2 列出作业
重要的是,能够更新不同的瓦片以在以后修复错误或重新渲染所有更改的几何体。列表作业是按其邻近度分组在一起的瓦片的批处理作业,它是从大量瓦片列表中创建的。
每周由更改的瓦片检测生成更改的瓦片的列表(2,000,000,000到3,000,000,000瓦片)。此列表必须拆分为批处理作业,其中每个作业包含数千个需要进行瓦片编辑的渲染。由于postgresql已经被配置为通过几何列的瓦片索引将行聚集在一起,因此可以通过将彼此接近的瓦片分组到一个批处理作业中来获得额外的性能。
算法
为了对一个批处理作业中非常接近的瓦片进行分组,这些瓦片按其四键[19]进行词法排序。由于四键编号方案的属性,这会导致瓦片按其父级INDIZE进行排序。
-
给出了一个很大的瓦片列表
-
计算XYZ瓦片索引的四元键
-
按四键按词法排序
-
将列表拆分为批量大小的子列表
Quadkey
Quadkey有几个独特的属性,这使得它非常适
合将瓦片分组在一起。
-
长度表示详细程度
-
Quadkey以父项瓦片的Quadkey开头
通过这些属性,可以简单地按瓦片的四元键进行词法排序,从而将瓦片分组在一起进行批处理。
4.2 分布式体系结构
为了跨多个主机分布,已经实现了使用作业队列的分布式体系结构(图18)。
-
金字塔或列表作业由GENERATE-JOBS创建并放入作业队列
-
不同主机上的不同工作进程轮询作业队列以查找新作业试着在给定的时间范围内渲染他们。
-
如果渲染ING未在给定时间范围内完成,则会将其放入失败的作业中排队。
-
生成的SQLite数据库将上载到与S3兼容的对象存储区,并链接到存储在结果队列中的结果消息。
处理错误
消息队列与持久队列一起使用确认机制。这意味着,如果任何流程在工作流中的任何阶段(渲染或Merge)失败,消息将重新排队并重新传递给下一个工作进程。由于总有一些作业从未完成或有非常明显的问题,超时可防止工人一次又一次地被相同失败的作业阻塞。失败的作业可以在稍后的时间点进行检查和重新安排。
4.3 合并结果
工作流的一个非常重要的部分是合并所有65536个SQLite数据库。合并作业进程在结果消息中下载链接的SQLite数据库,然后将其合并到指定的合并目标(例如PlanetMB瓦片文件)。
-
从结果队列消费消息。
-
链接的SQLite数据库从S3下载。
-
下载的SQLite数据库将附加到合并目标。
-
包含瓦片的数据表映射和包含实际PBF的图像复制数据以替换数据库中已有的条目。
将数据库“Sourcee.mb瓦片%s”附加为源;
替换为映射SELECT*FROMSOURCE。地图;
替换为图像SELECT*FROMSOURCE.IMAGES;
4.4 通过移除相同的子金字塔来节省空间
由于地球的大部分区域都被水覆盖,因此水瓦片是生成的行星文件的很大一部分。如果瓦片仅包含水,则不希望在从z8向下到z14的所有缩放级别上存储相同的水几何(结果为P6i=04i=5461s所有的瓦片都包含相同的几何体)。为防止此问题,将删除所有后代瓦片上包含相同数据的所有z8子金字塔。
算法
-
计算给定父瓦片在缩放级别MaskLevel的所有后代瓦片
-
计算每个瓦片的SHA1校验和
-
计数每个唯一校验和的出现次数
-
确保所有子体中只使用一个校验和
-
如果校验和与父瓦片校验和匹配,则删除所有子体
瓦片服务器实施
要支持瓦片服务器中删除的子金字塔,实现需要能够用来自较低缩放级别的数据回填较高缩放级别中缺失的数据。
-
如果存在请求的瓦片的矢量数据,则提供该数据
-
如果瓦片不存在,则计算缩放级别掩码级别的父瓦片
-
提供来自父瓦片的矢量数据
OpenStreetMap贡献者每天增加300多万个节点和方式。为了使Pre渲染ed瓦片保持最新,这带来了一个挑战,即查看更改,找出哪些瓦片受到这些更改的影响,并安排它们重新运行(Re渲染)。
找出哪些瓦片受更新影响需要多个步骤。
-
查找受更改影响的相关OpenStreetMap对象
-
计算对象几何图形覆盖的瓦片
时间限制
为了能够跟上渲染的更新, 处理时间不能超过数据库延迟的天数。
5. UPDATABLE VECTOR TILES
5.1 OpenStreetMap比较文件
OpenStreetMap提供单个XML文件,其中包含每个映射的对象。由于导入过程耗费时间和资源,因此重做此过程以跟上所有更改是不可行的。
因此,OSM额外提供OsmChange格式的每小时或每日差异文件,其中包含一段时间内创建、修改和删除的对象。在初始导入后仅导入后续的DIFF文件可使数据库与最新更改保持同步。
示例
清单6显示了一个示例diff文件,其中包含不同对象的创建、修改和删除条目。
不同的更改方案
创建对象
创建新对象(例如,添加新的兴趣点)。所有瓦片创建的对象所覆盖的内容必须收回(Re渲染)。
删除对象
对象被删除(例如,已不存在的老房子)。必须收回已删除对象覆盖的所有瓦片。
修改对象
对象被修改(例如,向地点添加额外的翻译)。全必须收回修改对象覆盖的瓦片。
移动对象
对象被移动(例如,必须修复映射不正确的公共汽车站或者在真实世界中被移动)。必须重新编辑原始对象覆盖的所有瓦片和移动对象覆盖的所有瓦片。
5.2 比较导入
除了导入常规的OSMPlanet文件外,Imposm3还支持导入OSMdiff文件。Imposm3将读取diff文件,并使用先前导入的本地缓存计算哪些节点、路径和关系受到更改的影响。
清单6中的CREATE条目导致SQLINSERT、DELETE和SQLDELETE在SQLDELETE中修改,后跟SQLINSERT语句。这是非常不幸的,人们会认为修改会导致SQLUPDATE语句。
imposm3的diff导入功能只是为了使数据库与OSM更改保持同步。无法跟踪表中的哪些行已被插入、更新或删除。
但是,此信息对于检测更改的瓦片并支持第5节中描述的所有更改场景IO至关重要。1.跟踪更改的功能的唯一方法是要么修改Imposm3,要么在数据库级别采取操作。
5.3 跟踪更改
要在数据库级别跟踪条目,需要将导入的时间戳添加到每个对象。这使得可以通过过滤最新的导入日期来查询修改和创建的对象。为了跟踪数据库中不再存在的条目(如已删除和已移动的对象),实现了对删除操作的审计。
5.3.1 跟踪插入的行
时间戳列用于保存插入要素的历史记录。时间戳列包含定义或更改功能的原始PBF或OSC文件的日期。这对于在第5节后面的时间范围内计算更改的瓦片非常重要。
-
imposm3diff进程为更新和添加的要素插入新行
-
现在,所有新行的时间戳列都设置为NULL
-
更新表并将ROWSTIMESTAMP列设置为导入的时间戳
5.3.2 跟踪删除的行
如果OpenStreetMap要素被更改或删除,Imposm3将首先从表中删除该行,然后再次插入该行(如果是更新)。这是由于性能原因,因为先删除后插入比更新快。为了支持删除、修改和移动对象的更改场景,为每个表启用TRACK_OSM_DELETE触发器以跟踪已删除的行,如清单7所示。
清单8中的触发器在丢弃该行之前将在单独的审核表中跟踪删除的行。
因此,每个表都有一个附加的删除表,其中包含所有已删除和已修改的行。这允许在第二步中计算受影响的瓦片并重新渲染它们。
5.4 计算更改的瓦片
确定哪些瓦片受数据库中的改变影响的一种方式是通过递归地向下XYZ四叉树并检查瓦片和几何的交集来根据改变的几何计算覆盖的瓦片。
算法
-
计算给定(x,y,z)瓦片索引的范围e
-
检查几何g是否与瓦片范围e相交
-
如果%2中没有交叉点,则停止
-
选择瓦片索引(x,y,z)
-
计算四个子(x,y,z)指数
-
如果缩放级别z尚未达到最大缩放级别Z,则为每个子行调用1
瓦片缓冲区
矢量瓦片中的几何图形可以延伸到瓦片(瓦片缓冲区的边界之外)。为了在算法中支持缓冲区的概念,定制缓冲区b扩展了(x,y,z)瓦片索引的范围e。瓦片的分辨率通常为256px。通过将缓冲器添加到瓦片256+2
PostgreSQL实施
PostGIS实现大量使用&&运算符和几何图形列上的主旨来检查瓦片范围和几何图形是否彼此相交。虽然使用几何体的边界框不准确,并且可能会产生误报更改的瓦片,但它比使用正确的ST_Intersects更快。
导出更改的瓦片
第5节中定义的算法。4应用于自给定时间戳以来已更改的所有几何图形,以找出受更改影响并需要再次进行瓦片的所有唯一渲染。
图25显示了10天内缩放级别为10的更改的瓦片。有了许多有趣的发现。
边界
令人吃惊的是,沿着行政边界,许多瓦片都发生了变化。这又回到了这样一个事实:在OpenStreetMap中,单个边界表示为多个节点,这些节点是单个关系的一部分。但是,在数据库中,边界表示为LINESTRING类型的单个几何图形。
如果有人更改了行政边界上的单个节点,则diff导入过程将删除此几何图形并再次插入它,如第5节中所述。2.在第二步中,改变的瓦片进程检测到该行已经改变,并计算所有受影响的瓦片,这就是为什么即使实际上只改变了一小部分边界,边界上的所有瓦片也被检测为改变的原因。
此问题的一个可能解决方案可能是排除更改后的瓦片流程的管理边界,并且仅不定期更新它们。
非洲的变化
看到有大量的测绘活动,这是令人鼓舞的。非洲。世界的这一部分可能是OpenStreetMap中映射最少的部分。
大型通用块
可以看到几个大的通用块。没有任何解释,可能会出现这种症状。
大片的农村地区没有什么变化
有很多地区,比如加拿大,阿拉斯加,俄罗斯、南美和澳大利亚几乎没有什么变化。
假设
原来,20天唯一变化的瓦片为~2000万瓦片,而10天唯一变化的瓦片约有1800万个瓦片,这导致假设经常变化的瓦片较少。
6. RESULTS AND FUTURE
第1节中定义的所有问题的解决方案。2个已被发现并实施。
6.1 结果
-
载体瓦片的质量已显著提高,并与MapboxStreetsv7已经到达。
-
一个开放源码工作流,用于扩展具有全球覆盖范围的矢量渲染瓦片已创建。
-
实现了基于OpenStreetMapDiff文件更新矢量瓦片的流程-根据用户反馈,项目网站得到显著改进。
-
针对整个地球的矢量瓦片,219个国家和692个城市的摘录以向下形式提供-在项目网站上加载。
-
详细的教程和自定义瓦片服务器,使入门尽可能简单都是被创造出来的。
6.2 未来
许多人的兴趣和参与表明,这个项目为自由和开放源码软件社区提供了巨大的价值。为了让它在未来变得有价值,需要克服几个挑战:
-
需要找到基础架构提供商才能运行更新流程在定期的基础上。
-
需要更多的人了解这个项目。
-
在项目期间,MapBox发布了矢量瓦片规范(版本)的更新2.0)。新标准需要得到支持,这样才能在将来正确使用他们的工具。对于一些挑战,未来几个月已经计划了可能的解决方案:
-
高铁软件研究所拥有一台服务器,可能用于更新过程中,但这一点尚未得到确认。
-
卢卡斯·马蒂内利(LukasMartinelli)和曼努埃尔·罗斯(ManuelRoth)将在FOSSGIS上发表关于OSM2矢量萨尔茨堡会议和波恩FOSS4G会议。这将有助于接触到更广泛的自由/开源软件社区,并进一步提高人们对该项目的兴趣。。
-
为了支持地图框矢量瓦片2。0规格整个星球需要Re渲染ed.如果时间和资源允许,项目维护人员打算在将来这样做。
7. REQUIREMENTSSPECIFICATION
本章介绍此项目的要求、用例和用户特征。
7.1 用例
本节介绍此项目的两个主要用例。
渲染矢量瓦片
用户渲染是一组自定义的矢量瓦片。由于并非所有数据的OpenStreetMap在OSM2Vector瓦片中,一些用户可能想要添加或删除数据。假设对创建自己的矢量瓦片感兴趣的用户克隆OSM2Vector瓦片的存储库,那么每个月可能有70个用户。
使用矢量瓦片
用户使用预编辑的矢量瓦片s并想要创建自定义底图。假设对使用自己的矢量瓦片感兴趣的用户阅读文档,那么每个月可能有600名用户。
7.2 用户特征
对互联网的访问有限或无法访问
受限制或限制的用户没有访问互联网的人可以下载整个星球的矢量瓦片,并在本地提供他们的自定义底图。
不能依赖第三方服务
许多组织不能依靠使用第三方服务,并希望在本地运行他们的地图。
自定义底图的外观
在许多使用情况下,最好调整底图以更好地匹配产品设计。
7.3 要求
学士学位论文由第7节描述的用例中的三个主要需求组成。1.这些需求的技术问题在第一部分中进行了描述。。
-
来自OpenStreetMap的整个星球的Pre渲染ed矢量瓦片(第4章)
-
更新功能以跟上未来OpenStreetMap的更改(第5章)
-
矢量瓦片与MapBoxStreetsv7兼容(第3章)
7.4 非功能需求
非功能性需求是该项目成功的关键。如果能够满足以下要求,指定的用户将能够从该项目中受益。
性能
整个世界的初始渲染过程必须保持在2以下几个星期。主服务器上的导入时间应该少于一天,而渲染应该保持在两周以内。更新应每周一次。
learnability
重要的是,没有以前矢量瓦片或坞站体验的用户可以从尽可能少的障碍开始。
成本
云实例到渲染全球的价格一度在1,500美元左右。更新应该只花费初始投资的一小部分。由于OSM2矢量瓦片将提供持续更新,因此重要的是该过程和结果是可重复的。
兼容性
与MapboxStreets的兼容性为用户提供了广泛的访问权限样式和编辑器。因此,矢量瓦片必须包含MapboxStreets包含的所有要素集。
矢量瓦片大小
单个矢量瓦片的大小不应大于500KB。
8. ARCHITECTURE AND DESIGN
8.1 架构
该项目的体系结构分为导入阶段(EtlProcess)、更改后的瓦片检测阶段和导出阶段(渲染Vector瓦片。本节介绍组件及其用途。
每个组件都是一个具有单一用途的Docker映像[12]。然后,将Docker容器(组件)链接到数据库容器,并为其提供额外的输入数据以执行其功能。将组件隔离到Docker镜像中可以确保某些组件的复杂安装和依赖关系不会导致问题。另外,通过使用DockerCompose,可以使用不同的容器定义整个ETL流程,并简化容器的部署和扩展。
8.1.1 导入组件
导入组件负责导入OpenStreetMap数据、外部数据源和sql实用程序,如视图、触发器、索引和函数,以帮助执行渲染ing和Changed瓦片的检测过程。
8.1.1.1 导入外部
导入外部组件负责将所有未直接从OpenStreetMap映射到PostGIS数据库的数据导入。图27显示了用于将数据导入PostGIS数据库的外部数据源和程序。GDAL工具OGR2OGR用于将各种数据源导入PostGIS数据库。
8.1.1.2 导入OSM
import-OSM组件获取导入文件夹中的第一个PBF文件,并将其导入PostGIS。之后,它使用IMPORT-EXTERNAL中的NaturalEarth数据更新比例尺,以更新比例尺,并基于导入的数据创建通用表。数据是使用imposm3diff模式导入的,整个PLAND文件最多可能需要14个小时。
8.1.1.3 导入SQL
import-SQL组件负责提供不同层中使用的SQL。它还为不同的分类生成sql代码,并为不同层生成检测更改的瓦片和表管理命令的代码。
8.1.2 更改的瓦片检测组件
改变的瓦片检测组件处理基于某个OpenStreetMapPLANET文件创建OpenStreetMapDiff文件、导入OpenStreetMapDiff文件以及用最新的改变更新过时的OpenStreetMapPLANET文件。以下各节显示每个组件中发生的情况。
8.1.2.1 更新OSM差异
update-osm-diff组件将PLANET文件作为输入,并创建一个OpenStreetMapdiff文件,其中包含自从下载PLANET文件以来发生的所有更改。这个使用osmupdate工具执行此任务。
8.1.2.2 导入OSM差异
import-osm-diff组件将使用updateosm-diff组件创建的OpenStreetMapdiff文件作为输入,并将所有更改导入数据库。
8.1.2.3 合并OSM差异
Merge-osm-diff组件将旧的PLAND文件和最新的DIFF文件作为输入,并将所有更改合并到旧的PLAND文件中。此外,更新PLANET文件的时间戳是为了在下次运行update-osm-diff进程时拥有正确的diff文件。osmConvert工具用于将最新的diff文件合并到旧的PLAND文件中。
8.1.2.4 更改的瓦片
Changed-瓦片组件负责执行更改后的瓦片的瓦片逻辑,并使用pgjad将更改后的SQL逻辑列表存储在文本文件中。用于检测更改的导入的实际逻辑包含在瓦片-sql组件中。
8.1.3 分布式瓦片渲染组件
为了满足性能要求,需要一种分布式渲染体系结构来将进程扩展到多个主机和进程。渲染ING管道的中心组件是消息队列,它包含渲染ING作业和结果所有其他组件都与消息队列交互以接受或确认作业。
8.1.3.1 生成作业
生成作业组件负责创建导出组件使用的JSON作业。它支持两种类型的作业:
-
金字塔:渲染inga瓦片金字塔的工作(例如,从z8一直到z14)。用于首字母世界的渲染。
-
列表:要按数据位置分组的瓦片列表的批处理作业。用于渲染ING已更改瓦片。
GENERATE-JOBS将作业作为单个JSON对象输出到标准输出。可以使用像Pipecat这样的工具在作业服务器上调度它们。
8.1.3.2 导出
导出组件负责使用osm2向量渲染s.tm2源和PostGIS组件对向量瓦片进行瓦片。导出可以与RabbitMQ之类的消息队列一起运行,或者对于较小的提取,可以与独立消息队列一起运行,在这些消息队列中,不需要将工作划分为几个部分。
8.1.3.3 合并作业
合并作业组件负责从队列中获取结果消息,下载附加的MB瓦片文件,并将其合并到最新的PLANETMB瓦片文件中。
8.2 数据库和图层架构
在本节中,将解释不同的层以及与之相关的数据库架构,并对其进行说明。每一层都包含一个图表,显示表格、缩放级别视图之间的关系和模型(第3节。2.2)和矢量瓦片层(图37)。数据库模式是非规范化的,与满足渲染ING的性能约束无关。它针对快速读取进行了大量优化,因为数据库模式的唯一用例是从postgis数据库生成矢量瓦片。图37中的箭头表示数据流。
8.2.1 障碍
层屏障_LINE包含挡路的一条道路或路径的障碍。常见的特征是结构墙、栅栏或像自行车栅栏和大门这样的门禁。屏障_LINE图层中也包含人工对象(如桥墩)或自然屏障(如悬崖)。障碍是相当详细的信息,因此仅与最高缩放级别14相关。
8.2.2 水
水层包含海洋、湖泊或大河等水体。由于水对地图的质量至关重要,因此表4所示的不同数据源用于不同的缩放级别。water_label层显示湖体(不是海水)的标签。由于超大型多边形质心的计算成本较高,水点表需要提前进行渲染计算。
开放街图中的海岸线对变化比较敏感,开放街图Data 项目负责修复破碎的海岸线并进行彻底检查。开放街图Data项目还照顾到将海洋分割成若干个较小的瓦片多边形,从而导致更好的数据库性能。水层在变焦级4上使用简化的Os _ Ocean 蓼 gen0生成的海洋多边形,在变焦级5至变焦级14上使用原始的Os _ Ocean _蓼生成的多边形。
为了在低缩放级别选择合适的水体,NaturalEarth数据集[20]以shapefile格式提供诸如水的物理特征的人工精选数据。对于湖泊和海洋,在缩放级别0到4上选择了不同分辨率(1:110M、1:50M和1:10M)的水多边形。
8.2.3 道路
道路是地图中最重要的要素之一。道路横跨按类型过滤的所有缩放级别。在最低缩放级别时,仅显示高速公路,而在较高缩放级别时,住宅和服务道路也会显示渲染。由于OpenStreetMap中道路的复杂层次结构,每个缩放级别都包含自定义过滤器,以控制在哪个缩放级别上显示哪种道路。ROAD和ROAD_LABEL图层查询ROAD_GEOMETRY表中的数据,该表中同时存在线串和多边形(对于较大的大道和广场)。ROAD_LABEL图层由指定了道路名称的线串组成,然后矢量瓦片客户端负责在道路线串上绘制道路标签文本。为了避免在道路上有太多的标签(特别是与高速公路标志相关的),道路按其附近进行分组,并按其长度排序,以降低标签密度。
8.2.4 建筑物和房屋统计员
建筑物是多边形,例如房屋或摩天大楼。它们仅显示在最高缩放级别14上,但已显示在缩放级别13的大型建筑除外。建筑物是高倍变焦时最常见的特征之一。
HUMENUM_LABEL图层包含用门牌号标记的BuildIngs或单个点。仅限 出现 在缩放级别14上面。
8.2.5 行政区划
admin层包含国家、州或省等行政边界的线串。边界被视为线串,因为在OpenStreetMap中边界经常断开,并且不能再作为多边形重建。因此,使用线串更安全,尽管这提供的制图样式选项较少。
由于在不同的缩放级别上需要不同的细节级别,因此来自自然地球[20]的文化数据集已经在低缩放级别下用于国家、省和争议区域的边界,而在较高的缩放级别下越精确使用OpenStreetMap数据。
8.2.6 土地利用和土地利用叠加
图层LANDUSE包含特殊分区土地的多边形。土地利用中最常见的特征是林区以及国家公园、沼泽、商业、工业和军事区。非常大的多边形被分割成几个部分到LANDUSE_SPLIT_POLYGON表中,较大的多边形被概括为较低的缩放级别。LANDUSE图层中的多边形根据缩放级别按区域过滤,以便在低缩放级别下仅显示最大的多边形。
8.2.7 POI标签
兴趣点(POI)是与地图上的特定点(如教堂、学校、旅游者 景点, 酒店,并非OpenStreetMap中映射的所有POI都与视觉地图相关。要在地图上显示,相关点至少需要具有由类型字段派生的名称或图标。
用户 BE 不堪重负 使用兴趣点图标太多。因此,字段localRank包含升序重要性等级,地图客户端可以使用该升序重要性等级来确定重要POI的优先级。非常显眼的POI还有一个基于其覆盖面积的比例尺。POI的排名计算与第3节中描述的位置标签排名非常相似。3.4.
8.2.8 国家和国家
国家、州和海洋的标签的位置和重要性很重要[1],而且对正确使用也很重要。由于直接从OpenStreetMap导入时很难保证这些功能的质量,因此国家和州的标签都是手工精选的。
来自天桥API[5]的数据被转换为GeoJSON,并手动编辑和增强标签等级,以获得最佳可能的标签放置和重要性排名。这项努力是值得的,因为国家和州的数据不太频繁地变化。国家标签并不是出现在所有缩放级别上,而是根据它们的比例值进行过滤,以显示像意大利这样的国家在像梵蒂冈这样的不太重要的城邦之前。
8.2.9 地点
地点标签对于构建具有良好文本层次结构的漂亮地图至关重要。重要的是,只以低缩放级别显示世界城市,然后逐渐显示越来越多的地方。通过矢量瓦片中的scalerank和localrane域进行过滤。scalerank字段源自NaturalEarth中的ne_10m_填充_Places表,并合并到Place_Point表中。除了将几何图形的质心用作标签点的住宅区和岛屿外,大多数地点标签在OpenStreetMap中映射为点。因为地点标签非常精细和重要,所以每个缩放级别都有自定义过滤器来控制哪些地点是相关的。职位的排名计算在第3节中进行了说明。3.4.
8.2.10 机场和机场
这一层空中通道包含了用于空中旅行的基础设施。最常见的特征是机场及其停机坪、跑道和滑行道。机场是大型地标,因此所有功能在变焦级别10之后都已存在。图层由多边形和线串组成,因为跑道通常是多边形,而滑行道主要是线串。
AIRAME_LABEL层包含机场端口的标签(一个点或机场多边形的质心),因为机场是重要的定向点。scalerank字段根据覆盖面积和类型描述机场的重要性。机场通常有存储在ref字段中的官方缩写(IATA、FAA、ICAO或自定义参考代码)。
8.2.11 海洋、大湖和海湾
对于海洋,大型湖泊和海湾在船体上有一个弯曲的标签是有利的,因为该标签不会干扰其他标签,如地点。
由于这些特征不能作为多边形使用,因此标签线串不能计算,而必须手工绘制。对于100多个最重要的湖泊和海湾,已经绘制了定制的线条。元数据仍然来自OpenStreetMap,但几何图形是自定义的。由于这些自然特征不会改变,这不会造成问题。
线串根据等级字段按照较高缩放级别的升序进行过滤,并且仅在较低缩放级别0到6下显示。
8.2.12 山峰
山峰是标有名称和海拔的山和火山的点。因为客户端的逻辑能力有限,所以高程是以米和英尺为单位计算的。
8.2.13 火车站
火车站包括铁路、地铁和电车站。由于这些公共交通要素的样式通常与其他兴趣点不同,因此它们包含在单独的RAIL_STATION_LABEL_LAYER中。
9. PROJECT MANAGEMENT
9.1 软件开发过程
基于Scrum的敏捷方法被用作该项目的过程模型。项目的维护人员充当联合产品所有者,而Backlog不仅由产品所有者管理,还由社区管理,社区向愿望列表添加功能,甚至向存储库贡献代码。
在每次冲刺开始时,都会评估待办事项的特性,并将其安排在下一个版本中。每次冲刺(两到三周)之后,都会发布一个新的稳定版本。
与Scrum相比,Scrum没有Sprint评审和回顾,但定期与论文顾问会面,告知项目状态。定期与技术顾问会面有助于共同解决问题。
GitHub
GitHub用于计划和跟踪任务和里程碑。为了提供Scrum面板和燃尽图,使用了ZenHub浏览器插件。
与其他项目管理工具相比,它有很大的优势,因为修订控制和问题跟踪处于同一位置。非项目成员可以理解某些决策背后的想法,并将他们的想法直接与团队成员交流,这对开放源码项目非常重要。
已使用以下存储库创建了名为osm2Vector瓦片s的组织:
-
OSM2矢量瓦片%s包含创建矢量瓦片%s的分布式工作流
-
瓦片服务器-gl-light精简了瓦片服务器-gl的分支,用于服务MB瓦片和Prede-改进的MapBoxGL样式,重点是从osm2向量瓦片提供向量瓦片
-
Imposm3自定义分支Imposm3,支持时间戳字段
-
mapbox-gl-瓦片与osm2矢量样式兼容的mapboxGL样式集合。
-
Rabbitmq官方RabbitMQDocker镜像自定义分支,额外支持消息超时配置
-
学士学位论文乳胶源
-
前一篇研究论文的学习论文乳胶来源
9.2 时间表
因为OSM2Vector瓦片的成员已经熟悉了技术和工作领域,所以不需要任何细化阶段。每个Sprint都与下一个版本紧密地结合在一起。
9.3 里程碑
每个里程碑都标志着矢量瓦片s的特殊发布版本。
10. QUALITY MEASURES
为了保证适当的质量,采取了许多措施。以下部分将分别介绍每种测量方法。
10.1 测试
OSM2Vector瓦片由许多不同语言的不同组件组成,这些组件都可以协同工作,这使得测试非常具有挑战性。本节描述如何在此项目中进行测试。
10.1.1 映射报告工具
创建映射报告工具是为了验证所有导入的OpenStreetMap数据是否在矢量瓦片%s内使用。这有助于识别应从导入映射中删除的OpenStreetMap键/值对,因为它们不在矢量瓦片%s内使用。
表8显示了映射报告工具的示例输出。它列出每个表的行数,并将它们与特定图层中使用的行数进行比较。如果百分比值低于100%,则图层不会使用导入映射中指定的所有要素。因此,应该删除这些OpenStreetMap键/值对。
10.1.2 集成测试
在TravisCI[3]中,对于每次提交的一个小数据样本,完成了整个工作流程。因为整个工作流都是用DockerCompose配置的[11],所以CI服务器必须按顺序执行所有导入步骤。这是一种检查所有组件是否正确协同工作的直接方法,虽然这是一个简单的设置,但它在项目开发期间提供了极大的帮助,可以捕获诸如缺失表或SQL拼写错误之类的错误。
10.1.3 结构试验
创建矢量瓦片比较工具是为了分析单个矢量瓦片的内容。这有助于识别在哪种缩放级别上显示哪种类型的数据,并确保与MapBoxStreetsv7相比,osm2矢量瓦片中存在相同数量的要素。
10.1.4 视觉测试
除了比较矢量瓦片的内容外,还创建了可视化比较工具,用于在不同缩放级别下可视化预览和比较地图。
图63显示了VisualCompare工具的屏幕截图。左手边是OSM2Vector瓦片s,右手边是MapboxStreetsv7。两者都使用OSM明亮视觉样式。
本文作者:风帆远航
本文链接:https://www.cnblogs.com/flying-birds-xyg/p/16023313.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步