近年来,越来越多地图应用在浏览器端展示,如谷歌地图、OpenStreetMap、百度地图等国内外知名的地图服务商都是以浏览器展示为主要应用。浏览器展示地图非常方便,不需要单独下载一个软件来作为地图的展示工具。但是在浏览器端有着性能、带宽等诸多限制,本文来简单介绍下栅格、矢量甚至地形切片的原理,以及一些成熟的工具的应用。
什么是切片(tile)?
2005年Google地图首先采用Web墨卡托投影,此投影不是公认的大地测量系统,使用球形显影椭球坐标系。相对于 WGS 84/World Mercator (CRS code 3395) ,在地图上(地面上21公里) ,比例尺误差为0.7% ,北方误差高达43公里。Web墨卡托投影的非官方EPSG编码为900913,后来EPSG官方给它3857这个正式编码。Google地图在空间坐标系为EPSG:3857的基础上,推出了Tiled web map(OpenStreetMap的专业术语为slippy map),这就是今天WEB地图切片的雏形。
Google地图切片的惯例
- 瓦片为256x256像素
- 在最上层的缩放级别为0,此时展示整个世界
- 每增加一个缩放层级,长和宽两个维度的切片数量都增加一倍
- 空间参考系为WEB墨卡托,维度在 85.06°S 到 85.06°N
OpenStreetMap的标准–Slippy Map Tilenames(也叫XYZ)
XYZ标准遵循Google地图切片的惯例,也增加了一些内容:
- 每个层级切片有一个x和一个y编号
- PNG格式的瓦片图像
- 图片是通过WEB服务器提供的,url类似于 http://…/z/x/y.png ,其中z是缩放级别,x和y标识瓦片
“切片”的意义
所有使用切片的地图服务一般来说,主要目的有两点:
1. 切片地图可以给使用者一种正在查看整张地图的错觉
OpenStreetMap将其命名为Slippy Map(滑动地图),就是根据这个特性。传统的oms和wms协议,返回的是某个区域的的地图,每次移动都会是地图重新加载;而切片地图,则是以瓦片的形式展示,瓦片的排列方式是固定的,滚动地图时只会加载不存在的部分,不会使整个地图刷新。
2. 切片地图可以提升性能
由于切片索引对应的坐标的唯一性,切片完全可以提前做,在加载的时候只需要访问切好的目录,实际性能表现应该比oms和wms这种处理原图方式性能更好
目前常用的WEB地图切片标准
当前比较常用的WEB地图切片,分别有三个Tile Map Service(TMS)、Web Map Tile Service(WMTS)和 Bing Maps Tile System。其中 Bing Maps Tile System 的涉及较少,只有 Bing Maps 在用,它的原理是 Quadtree,本人了解有限这里不再展开篇幅介绍。接下里重点介绍Tile Map Service 和 Web Map Tile Service。
Tile Map Service(TMS)
Tile Map Service(下文称TMS)是 OSGeo 提出并且维护的标准,但这是一个社区标准,它未被 OSGeo 认可为基金会的官方项目或工作产品。在其 OSGeo 的TMS规范的官方文档中,详细描述了TMS的url规则、返回值一级一些异常处理情况。总结如下:
- TMS的URL格式为 http://tms.osgeo.org/1.0.0/{name}/{z}/{x}/{y}.{format}
- TMS作为资源部署到WEB服务器,接口需要返回资源描述(text/xml)
- TMS的每个瓦片像素大小一般为 256x256,所有层级瓦片大小一致,且都为正方形
- TMS有四个Profiles:
- none:表示没有资源
- global-geodetic:
- srs 必须为 EPSG:4326
- 像素满足公式 $units-per-pixel = 0.703125 / 2^n$
- global-mercator
- srs 必须为 OSGEO:41001
- 像素满足公式 $units-per-pixel = 78271.516 / 2^n$
- local
- 可以使用任何坐标系
- 像素满足公式 $units-per-pixel = 2^n$
- TMS可以用多种文件格式(jpg、png等),在TileFormat中展示
- TMS以左下角为原点x的序号从左到右,y的序号从下到上
Web Map Tile Service(WMTS)
Web Map Tile Service(下文称WMTS)是ogc提出的标准,这是一个ogc的官方标准,在官方界面上,ogc提供了WMTS的规范pdf下载,此pdf有100多页3万多个单词,如果读者感兴趣,可以去研究一下,这里简单的总结了下:
- WMTS受TMS的启发,在TMS之后实现的(WMTS在2010年左右提出)
- WMTS可提供三种数据:
- ServiceMetadata:服务的元数据它描述了特定服务器实现的能力和信息持有量。GetCapabilities 操作获取。
- Tile:切片数据,GetTile 操作获取
- FeatureInfo:其他数据,提供有关位于瓦片地图特定像素的要素的信息,GetFeatureInfo 操作获取
- WMTS可以在不同层级下提供不同大小的瓦片,不同层级的瓦片大小可以不同,所有瓦片为矩形
- WMTS可以用多种格式
- WMTS以左上角为原点x的序号从左到右,y的序号从上到下
- WMTS支持 KVP、SOAP、RESTful
TMS vs. WMTS
TMS和WMTS的不同点
TMS的原点在左下角;WMTS的原点在左上角
TMS返回的主要数据切片的数据;WMTS可以返回除切片外的其他数据
TMS的切片必须是正方形并且所有层级的切片大小一样;WMTS的切片形状满足矩形,不同层级的切片大小不一样
TMS只支持web服务器提供切片;WMTS支持KVP、SOAP以及RESTful
总结:TMS规范了XYZ的标准,WMTS在TMS基础上扩展了更多功能。由于TMS更简单,个人认为大多数场景下TMS就够了。
目前来看最受欢迎的是XYZ标准,或者说未完全实现的TMS规范。大多数人只需要一个XYZ标准的url其他根据默认的配置就能够展示地图,所以很多服务并没有完全实现TMS(但是他们还是称自己的服务为TMS,据说他们觉得GSGeo的规范太复杂了)。而WMTS功能非常强大,但是它太复杂了,WMTS规范正文60多页,加上对象定义等一些必要内容,总页数达到了100多页,非常复杂。许多GIS服务提供商连规范字数少很多的TMS(可能字数只有WMTS文档的5分之一)都没有完全实现,更别说WMTS了。而且以WMTS的规范内容来看,就有一种SOA时代的气息。我更看好TMS.
切片格式
栅格数据
栅格数据的切片格式其实没什么好说的,一般就是标准的图像格式png(Portable Network Graphics)、jpeg(Joint Photographic Experts Group)和gif(Graphics Interchange Format)等,一般情况下使用png情况比较多,其透明的特性能够适配多种展示风格。
矢量数据
矢量数据的切片格式目前常用的是mvt等,当然也可以将矢量栅格化,使用png等格式的图片展示。
Mapbox-Vector-Tiles(MVT)
MVT是一种高效的编码,非常方便的就能在web上使用,而且能够携带其他属性属性。
地形数据
本文的地形数据格式指Cesium支持的地形格式 heightmap 和 quantized-mesh 两种。
heightmap
quantized-mesh
切片程序
gdal_retile.py
gdal_retile.py 是 GDAL 项目自带的一个工具,专门用来切片和建立金字塔。它的原理很简单:根据图片计算出x和y的范围,根据x和y对原图进行切片。
1 | gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeight] |
GeoWebCache
GeoWebCache 是现在最常用的切片程序之一,但是绝大多数人都没有单独使用过它,大家都是在 Geoserver 中使用的它,可能很多人还不知道,Geoserver 的 “Tile Caching” 的功能都是 GeoWebCache 提供的。 GeoWebCache 是一个单独的项目,这个项目总体来说还是比较活跃的在 Github 上几乎每天都有更新,上个release 是在去年七月份发布的(当前时间是2023-02,GeoWebCache 的上个 release 版本是 2023-07-27 的 1.21.1),但是GeoWebCache官方网站给人一种没人维护的气息,官方网站上的最新版本仅仅更新到1.15。
我们来认识一下 GeoWebCache 是怎么工作的。我们平时基本将 GeoWebCache 和 Geoserver 看作一体的,我们平时发布地图可能会有如下流程:
- 创建工作空间
- 创建存储空间,这里主要是将实际上的数据源与注册到 Geoserver
- 发布图层,使 Geoserver 发布对应存储空间的数据,外部可用 WMS 等协议访问此图层数据
- 在“Tile Caching”中选择“切片图层”点击“Seed/Truncate”操作
- 设置参数进行切片
其中只有第五步是在 GeoWebCache 中操作的,而且 GeoWebCache 并没有直接访问数据源,GeoWebCache 访问的是 Geoserver 的 WMS 服务。
GeoWebCache is a Java web application used to cache map tiles coming from a variety of sources such as OGC Web Map Service (WMS). It implements various service interfaces (such as WMS-C, WMTS, TMS, Google Maps KML, Virtual Earth) in order to accelerate and optimize map image delivery. It can also recombine tiles to work with regular WMS clients.
GeoWebCache 是一个 JavaWeb 应用程序,用于缓存来自 OGC Web Map Service (WMS)等各种来源的地图块。它实现了各种服务接口(WMS-C, WMTS, TMS, Google Maps KML, Virtual Earth) ,以加速和优化地图图像传输。它还可以重新组合切片,以便与常规 WMS 客户机一起工作。
NextGisWeb
NextGis 是一家坐落于爱沙尼亚共和国的地图提供商,是俄罗斯最早的地图提供商之一,目前来说名气相对较小。NextGisWeb 是 NextGis 面向 Web 端实现的一套 WebGis 的开源系统,编程语言是 Python。NextGisWeb 是我使用的最方便、最灵活的 WebGis 系统之一,他们的概念很简单,发布图层只需要简单的几项配置就能完成,与 Geoserver 繁琐的配置并不相同,从这点上来看 NextGis 确实称得上 “next”。NextGisWeb 的灵活性来源于他关于所有发布资源的设计。NextGisWeb 将其发布的每一个资源都赋予一个资源ID(ResourceId),NextGisWeb 利用 TMS 提供指定资源列表的服务,从设计上来说所有资源都可以从一个 TMS 请求中返回,这些指定的资源会在返回前组合起来。
1 | http://192.168.1.31:20000/api/component/render/tile?resource=146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346,348,350,352,354,356,358,360,362,364,366,374,376,378,380,382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416,417,419,421,423,425,427,429,431,433,435,437,439,441,443,445&x=115438&y=51941&z=17 |
然而极大的灵活性也伴随着一些实际的问题,这里面最大的问题就是性能。
我们仔细研究一下 NextGisWeb 对于资源的组合过程:
NextGisWeb 还有一个地方不是很让人喜欢,它需要通过HTTP协议上传本地的数据格式化为他需要的文件,才能进行发布。当需要发布的是栅格图时,需要将本地图片上传,意味着使用 NextGisWeb 发布图层,占用空间至少为原来的两倍。
NextGisWeb 其实很不错了,空间占用没有办法结局,但是性能问题还是有解决方案的。NextGisWeb 可以与之前介绍的 GeoWebCache 一起使用,组成 NextGisWeb + GeoWebCache,我相信在一些场景下也能发挥不错的效果。
cesium-terrain-builder
目前讨论的地形文件格式分别是 heightmap 和 quantized-mesh,这两个格式都是 Cesium 提出的,Geo-Data 组织就实现了一个名叫 cesium-terrain-builder 的项目对DEM或DSM进行切片,原始的 cesium-terrain-builder 不支持 quantized-mesh 格式,目前使用的是 homme/cesium-terrain-builder。
使用上来说还是挺简单的,不过这个项目太久没有维护了。
总结
其实在了解关于切片的知识后完全可以自己来实现切片程序,而且只要满足最基本的XYZ标准,就基本可以支持一些前端的地图框架了(openlayer、cesium)。