comtop0 2019-06-28
最近的工作重心放在了后端地图渲染引擎上,因此接触到了mapnik,用了一段时间感觉它的功能相当丰富,具有很强的拓展性,生态也比较强大,想对学习过程做一个记录。OK,废话少说。
Mapnik是一款开源的具有地图渲染功能的库,它能够为Postgis,Shapefile,Geojson,SQLite等在内的多种数据源提供空间数据计算与可视化服务,包括png瓦片,矢量瓦片,utfGrid,同时它支持自定义渲染样式配置,具有很高的灵活性,提供了c++,python,node接口。目前在开源社区上已有较多成熟的产品基于Mapnik做了封装,例如windshaft,tileliev-mapnik等等。
矢量瓦片在我理解是将矢量所表示的空间数据和属性数据按照特定的编码方式(Google Protocol Buffers)进行编码,Google Protocol Buffers是一种兼容多语言、多平台、易扩展的数据序列化格式,采用这种编码方式,能够最大程度保证矢量数据的精度,提高客户端和服务端的渲染效率以及查询效率,详情可以参考:https://github.com/jingsam/ve... 以及 https://github.com/mapbox/vec...
以PostGIS为例Mapnik库进行矢量瓦片渲染时整个工作流程是:首先根据url中z,x,y参数计算出该瓦片的坐标范围extent,然后将extent与每一个几何要素的最小外包矩形进行overlay计算得到该瓦片内的所有geometry对象,最后通过Postgis的库函数ST_AsMVT将所有几何对象聚合成矢量瓦片,伪代码如下:
let vt = new Mapnik.VectorTile(z, x, y); let map = new Mapnik.Map(256,256,‘+init=epsg:3857’); map.fromStringSync(xml);//xml为配置对象,具体参看https://github.com/mapnik/mapnik/wiki/XMLConfigReference map.render(vt, (err, tile) => { if (err) throw err; //tile即为所得数据 console.log(tile.getData()) })
栅格瓦片就是将空间数据按照指定的颜色样式以图片的形式进行绘制,栅格瓦片多应用于底图的绘制,由于空间数据被绘制成了图片,在前端可视化时候就是绘制在canvas上的像素点,因此它的属性信息会丢失,需要配合utfGrid同步使用。栅格瓦片的渲染流程与矢量瓦片类似,只是最后一步不是聚合,而是按照指定的样式进行逐一像素点绘制;在mapnik中,栅格瓦片的渲染主要有两种方式,1)直接渲染;2)通过矢量瓦片渲染,伪代码分表如下:
let image = new Mapnik.Image(256, 256); let map = new Mapnik.Map(256,256,‘+init=epsg:3857’); map.fromStringSync(xml); map.render(image, {}, function(err, image) { if (err) throw err; image.encodeSync('png') });
let vt = new Mapnik.VectorTile(z, x, y); vt.addDataSync(tile);//tile即为前文提到所生成的矢量瓦片 let map = new Mapnik.Map(256,256,‘+init=epsg:3857’); map.fromStringSync(xml); vt.render(this.map, new Mapnik.Image(256,256),function(error,buffer) { if (error) throw error; buffer.encodeSync('png') });
比较简单的介绍了mapnik的地理数据渲染功能,之后会做一个比较简易的地图渲染服务器,初次使用技术博客,可能不太到位,还请各位前辈多指教