Mapnik是一个强大的使用地理空间数据创建地图的强大工具包 ,其核心是一个 C++ 的共享库提供空间数据访问和可视化的算法和模式,特别是包含一些地理对象,如地图、层、数据源、特征和地理几何等。它提供了一些功能,可以用来设计具有良好视觉效果的地图。Mapnik会产生地图,地图对象是Mapnik的API的核心。地图对象提供了生成图像输出格式的方法(通常是PNG或者是PDF)。
Mapnik的应用主要包括三个方面:它可以作为一个 C++ 代码的共享库;它可以用来编写 Python 脚本;还可以用来编写和处理 XML 配置文件。
Mapnik地图内部有很多图层,每一层都与数据源密切相关。每种典型的数据源(例如,Shapefile数据源、in-memory数据源、Raster数据源)都具有多种要素(如点、线、面等)。一个数据源可以指示一个shapefile文件、空间数据库、光栅图像文件或大量的其他空间数据源。在大多数情况下,建立一个数据源层是很容易的。
理解 Mapnik 的工作机制必须注意,使用Mapnik来渲染地图时顺序非常重要。它使用Painter算法来决定Z轴次序,即图层按一定顺序描绘,“顶”层在其他层之上,最后描绘。
在每一层中,地理空间数据可视化的显示是通过一种叫做symbolizer的东西控制的。虽然在Mapnik有许多不同类型的symbolizers可以利用,但是我们这里感兴趣的是三种symbolizers。
一种样式定义了图层中对象是怎么渲染的。一种样式包含了一种或多种规则,可以有选择性的限制其输出。过滤出数据源提供的对象的一个子集。例如只显示那些具有特殊属性的对象。过滤式可以选择的--对于简单的地图通常每层有一个规则,再没有其他的过滤器。每一个规则持有一个或者多个符号,这是用于在实际输出时绘制几何图形的。根据符号类和设置几何图型可以以很多种形式产生。
import mapnik
m = mapnik.Map(400,200,"+proj=latlong +datum=WGS84")
m.background = mapnik.Color('steelblue')
mapnik.render_to_file(m,'xworld.png', 'png')
map.srs
为要生成地图的投影, m.srs
缺省为: +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
创建一个给定宽度和高度的地图,设置背景的颜色为“steelblue”。
from IPython.display import Image
Image('xworld.png')
s = mapnik.Style()
r=mapnik.Rule()
polygon_symbolizer = mapnik.PolygonSymbolizer()
polygon_symbolizer.stroke = mapnik.Color('#0f0f0f')
r.symbols.append(polygon_symbolizer)
line_symbolizer = mapnik.LineSymbolizer()
# line_symbolizer.stroke = mapnik.Color('rgb(50%,50%,50%)')
r.symbols.append(line_symbolizer)
s.rules.append(r)
m.append_style('My Style',s)
上面 s
与 r
,分别是地图对象的样式与规则,
polygon_symbolizer
与 line_symbolizer
分别定义了多边形与线状要素的样式;
然后,符号添加到规则中,规则添加到样式中,样式再加入到地图中。
ds = mapnik.Shapefile(file='/data/gdata/GSHHS_c.shp')
layer = mapnik.Layer('world')
注: layer.srs
是数据源的源投影,需要和数据坐标的投影匹配,
否则地图可能是空白的。在这种情况下,默认的srs
mapnik假设和数据的投影匹配。如果不是这种情况的话,需要把
layer.srs
设置成正确的值。
现在把数据集加到层里面。最后需要确定我们上面创建的样式也适用于层,根据其字符串参考,如下:
layer.datasource = ds
layer.styles.append('My Style')
m.layers.append(layer)
m.srs='+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
m.zoom_all()
最后渲染地图。把数据写成png格式然后保存到当前目录的 world.png
。
mapnik.render_to_file(m,'xworld2.png', 'png')
Image('xworld2.png')
注意:如果你重新运行脚本的话,生成的地图将会被覆写。
现在你可以用文本编辑器打开脚本,改变维数,颜色或者数据源(记住当你改变数据源时要使用正确的srs)。
import mapnik
m = mapnik.Map(600, 300)
m.background = mapnik.Color('steelblue')
s = mapnik.Style()
r = mapnik.Rule()
polygon_symbolizer = mapnik.PolygonSymbolizer()
polygon_symbolizer.fill = mapnik.Color('#f2eff9')
r.symbols.append(polygon_symbolizer)
line_symbolizer = mapnik.LineSymbolizer()
line_symbolizer.stroke = mapnik.Color('rgb(50%,50%,50%)')
line_symbolizer.stroke_width = 0.1
r.symbols.append(line_symbolizer)
s.rules.append(r)
m.append_style('My Style', s)
ds = mapnik.Shapefile(file='/data/gdata/GSHHS_c.shp')
layer = mapnik.Layer('world')
layer.datasource = ds
layer.styles.append('My Style')
m.layers.append(layer)
m.zoom_all()
mapnik.render_to_file(m, 'xx_a.png', 'png')
print("rendered image to 'world.png'")
rendered image to 'world.png'
from IPython.display import Image
Image('xx_a.png')
使用XML渲染地图
不同版本的 Mapnik 接口改变也比较多,从而导致 Python 绑定存在许多问题。目前在 Python Mapnik 的开发中, 很多的 issue 处于 open 状态,有的问题已经存在一年多了。 使用 Python + XML 是目前比较现实的方法。
使用Mapnik还有一个值得研究的方法。 Mapnik不但以编程方式创建symbolizers、规则、样式和图层, Mapnik还允许你使用一个地图定义文件来存储所有的信息。 这是一个用于定义生成地图的不同的Mapnik对象的XML格式的文件。
还要说明一点,你可以选择使用地图定义软件,而不是使用Python代码来创建不同的Mapnik对象通过手动的方式。 这是一个XML格式的文件,它定义了所有地图内的symbolizers、过滤器,样式和图层。 然后你Python代码只需创建一个新mapnik.Map对象,并告诉Mapnik从XML格式的文件中加载地图的内容。 这允许你地图定义的内容与Python代码分离开, 它能够生成地图并且以同样的方式作为一个HTML模板引擎分离形式和内容在Web应用程序中。
使用XML样式表来渲染地图
此页面将引导你通过使用python绑定和XML文件来改变地图的样式。
结果如下图所示:
首先你需要用一个python脚本来设置基本的地图参数和XML样式表中的点。
复制下面的代码然后粘贴到 world_map.py
中。
import mapnik
stylesheet = '/data/gdata/world_style.xml'
image = 'xworld2.png'
m = mapnik.Map(600, 300)
# m = mapnik.Map(1400, 600)
mapnik.load_map(m, stylesheet)
mapnik.render_to_file(m,'xworld2.png', 'png')
m.zoom_all()
mapnik.render_to_file(m, image)
print("rendered image to '%s'" % image)
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Cell In[13], line 6 4 m = mapnik.Map(600, 300) 5 # m = mapnik.Map(1400, 600) ----> 6 mapnik.load_map(m, stylesheet) 7 mapnik.render_to_file(m,'xworld2.png', 'png') 8 m.zoom_all() RuntimeError: Shape Plugin: shapefile '/gdata/GSHHS_c.shp' does not exist encountered during parsing of layer 'world' in Layer at line 10 of '/data/gdata/world_style.xml'
Image('xworld2.png')
最后创建world_style.xml
,参考是world_map.py
。
复制XML,把文件储存在world_style.xml
,和world_map.py
也在同一目录下。
现在运行Python脚本:
python world_map.py
它将会输出和入门教程匹配的相同的文件中的一个png图像。
查看这个样式文件:
!cat /gdata/world_style.xml