使用DEM和矢量数据绘制地图

要生成一副图片地图,可以使用ArcGIS、QGIS等工具,也可以使用代码实现。我这里介绍的当然是用代码实现,而且是利用开源软件。毕竟桌面版GIS工具的介绍太多了,大家的地图都做的很漂亮。
用代码渲染地图就不得不提到GDAL和Mapnik。GDAL是处理GIS数据最常用的库,这里我们就要用到gdaldem处理DEM数据。Mapnik是渲染地图的最基本工具,我们要使用它来生成地图。
要绘制一个地图首先需要定义清楚绘制什么样的地图,是地形图还是街道图还是卫星影像图,然后根据地图内容的需求将需要的各种类型空间数据准备好,有了这些数据才能绘制出地图。
在这里我介绍的是如何绘制一个地形图,需要使用到的是DEM(数字高程模型)数据,和矢量数据。DEM数据是用来表示地形的高低起伏,一般来说DEM数据是存储为GeoTiff格式的。矢量数据我在这里主要是绘制水系,格式是Shape file。这次的重点是如何绘制地图,因此有关数据就不多做解释了,如果对这两种数据不了解可以自行查询一下。
接下来就是具体的过程介绍了。
第一步,我们需要对DEM数据进行简单的处理。主要目的是为了得到三种数据,第一种是色彩,主要是表现地形的高低,不同的颜色代表不同的海拔高度,可以直观的看出高度情况。第二种是山影,主要是为了让渲染出来的地图更具有立体性。第三种是坡度,不同的颜色可以代表地形的陡峭程度,当然还可以叠加上坡向的表示。
渲染色彩图首先需要创建一个配置文件,在使用gdaldem命令生成色彩数据的时候需要用到它。
比如创建一个空的配置文件叫做: color-relief.cfg,内容如下:

0 110 220 110 900 240 250 160 1300 230 220 170 1900 220 220 220 2500 250 250 250 nv2552552550

其中每一行代表了一个海拔高度值对应的颜色是什么,第一列的数字是海拔高度值,后面3列是RGB颜色色值。这里需要注意的是最后的nv代表nodata-value,如果不配置这一项的话,没有数据的部分就会被渲染成黑色,这一行最后一列多了一个0,是它的透明度值,0代表完全透明,100代表完全不透明。
然后使用gdaldem创建色彩数据
gdaldem color-relief dem.tif color_relief.cfg color_relief.tif-alpha

color_relief.tif文件长这样:
使用DEM和矢量数据绘制地图
文章图片

能看出来哪里高哪里低了,但是它看起来很平对吧。所以还需要多种数据叠加
创建color_slope.cfg,用于产生坡度数据
0 255 255 255 90 0 0 0

这个文件中每一行代表一个坡度对应什么颜色,第一列是坡度,后面3列是RGB色值。在这个例子中,产生的坡度数据会自动从0-90度填充从白色到黑色的渐变色。
产生坡度数据同样使用gdaldem命令
gdaldem slope dem.tif slope.tif gdaldem color-relief slope.tif color_slope.txt slopeshade.tif-alpha

现在只缺少山影数据了
gdaldem hillshade dem.tif hillshade.tif

我还准备了一个矢量数据,其中包含了河流和水库等水域信息,这个数据不需要单独处理,在Mapnik的地图样式配置文件中,可以同时使用多种不同的数据格式配图。
数据准备工作都已经完成,接下来就需要创建Mapnik渲染地图所需的地图样式配置文件了,我的配置文件terrain_lake.xml是这样的:
[type] = 'Waters' color relief style gdalcolor_relief.tif hillshade style gdalslopeshade.tif hillshade style gdalhillshade.tif lake style shapeland_use_utf8.shp

在这个配置文件中,可以针对不同数据定义多种样式和多个图层,每个图层可以指定不同的样式,非常方便使用。准备好配置文件后,我这里使用的是nodejs版本的binding调用mapnik渲染,代码如下:
var mapnik = require("mapnik"); var fs = require("fs"); mapnik.register_default_fonts(); mapnik.register_default_input_plugins(); var map = new mapnik.Map(300, 300); map.load("./terrain_lake.xml", function(err, map) { map.zoomAll(); var im = new mapnik.Image(300, 300); map.render(im, function(err, im) { im.encode("png", function(err, buffer) { fs.writeFile("map.png", buffer); }); }); });

最终的结果是这样的:
使用DEM和矢量数据绘制地图
文章图片

最近我负责的项目中有很多地图需要渲染,使用了Mapnik进行批量处理,效果非常理想,而且Nodejs调用可以实现异步,效率也很高,圆满的完成了客户的需求。
Mapbox公司的开源项目中还有基于mapnik的瓦片服务,功能也很强大,如果使用编程手段生成地图的话,我认为Mapnik是比较理想的选择。(https://gisbook.cn/data/china-dem)
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
【使用DEM和矢量数据绘制地图】使用DEM和矢量数据绘制地图
文章图片

    推荐阅读