>>> from env_helper import info; info()
页面更新时间: 2023-07-08 22:52:14
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-10-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

9.8. 绘制点状要素

最后来了解一下点状要素的绘制。

点是最简单的要素,为什么要放到最后来说呢。 主要是因为点的显示除了样式之外,文本标记的配合显示也比较独特。 关于点要素及其显示方式,只能用简约而不简单来形容了。

使用Mapnik绘制点有两种方式: PointSymbolizer允许你在给定的点上绘制图像, ShieldSymbolizer将图像和文本标记结合起来产生一个“盾”。 现在分别来看一下是如何使用的。

9.8.1. PointSymbolizer

PointSymbolizer能在点上绘制图片,默认的构造函数没有提供参数,并显示每一个点作为一个 4 × 4 像元的黑色方点:

>>> def renderit(line_sym=None, poly_sym=None, point_sym=None, shpfile=None, fig_index=0):
>>>     m = mapnik.Map(600, 300, "+proj=latlong +datum=WGS84")
>>>     s = mapnik.Style()
>>>     r = mapnik.Rule()
>>>
>>>
>>>     if poly_sym:
>>>         r.symbols.append(poly_sym)
>>>     if point_sym:
>>>         r.symbols.append(point_sym)
>>>     if line_sym:
>>>         r.symbols.append(line_sym)
>>>     s.rules.append(r)
>>>     m.append_style('My Style', s)
>>>     lyr = mapnik.Layer('world', "+proj=latlong +datum=WGS84")
>>>     # lyr.datasource = mapnik.Shapefile(file='/gdata/world_borders.shp')
>>>     if shpfile:
>>>         lyr.datasource = mapnik.Shapefile(file=shpfile)
>>>     else:
>>>         lyr.datasource = mapnik.Shapefile(file=os.path.join(BASE_PATH, 'fig_data_line.shp'))
>>>     lyr.styles.append('My Style')
>>>     m.layers.append(lyr)
>>>     # bbox = mapnik.Box2d(118, 36.6, 124.6, 40.7)
>>>     # m.zoom_to_box(bbox)
>>>     m.zoom_all()
>>>     return m
>>>
>>> import os, mapnik
>>>
>>> shpfile='/gdata/fig_data/fig_data_poly.shp'
>>> ply_sym = mapnik.PolygonSymbolizer()
>>> ply_sym.fill = mapnik.Color('#f2eff9')
>>> li_sym = mapnik.LineSymbolizer()
>>> pt_sym = mapnik.PointSymbolizer()
>>> m = renderit(point_sym=pt_sym, line_sym=li_sym,
>>>     poly_sym=ply_sym,shpfile=shpfile)
>>> m.zoom_all()
>>> mapnik.render_to_file(m, 'xx_sym.png')

你可以为图片文件提供名称、类型、尺寸,PointSymbolizer将使用这些特征绘制每个点。

result

图 9.6 result

需要知道的是PointSymbolizer绘制影像会覆盖到你所想要的点上。 可能需要在影片的周围留白(或者透明) ,这样影像中你想要的部分就会出现在你想要的点上。 例如,如果你希望在一个确切的位置绘制一根针脚,你可能需要设置格式。

额外的(透明的)空白确保针脚的点位于图像的中央,使影像正好在地图所需的位置上。

无论你是否提供影像,PointSymbolizer都有两个用来修正行为的属性:

  • symbolizer.allow_overlap = True :如果你将这个属性设置成 True ,即使影像重叠,所有的点都将会被绘制。缺省情况下不会重叠。

  • symbolizer.opacity = 0.75 :透明或者不透明怎样来绘制影像。值为 0.0 ,则绘制的影像是完全透明的,而值为 1.0 (默认情况下),则绘制的影像是完全不透明的。

9.8.2. ShieldSymbolizer

ShieldSymbolizer允许你绘制标记,并将文本与图片结合。 在本章节中,我们将会着眼于ShieldSymbolizer绘制点。 ShieldSymbolize绘制的是一个和文本标记相关的影像:

ShieldSymbolizerTextSymbolizerPointSymbolizer 在呈现相同的数据时具有相同的工作方式。 仅有的不同就是 ShieldSymbolizer 确保文本和影像呈现在一起; 你永远也得不到一个没有文本的影像,或者反之亦然。 当你创建一个 ShieldSymbolizer ,你需要提供较多的参数。

symbolizer = mapnik.ShieldSymbolizer( fieldName, font, fontSize, color,
    imageFile, imageFormat, imageWidth, imageHeight)

其中:

  • fieldName是作为文本字段所要显示的字段或者属性的名称。

  • font是绘制文本所使用的字型名称。

  • fontSize是文本的尺寸的,以点数为单位。

  • color是Mapnik颜色对象定义用来绘制文本的颜色。

  • imageFile是掌握显示影像的文件的名字(和可选的路径)

  • imageFormat是定义图像文件格式的字符串(PNG or TIFF)

  • imageWidth是该影像文件的宽度,以像元为单位。

  • imageHeight是影像文件的高度,以像元为单位。

因为ShieldSymbolizerTextSymbolizer的一个子类, 所有TextSymbolizer可以利用的定位和格式的选项同样对ShieldSymbolizer也有用。 由于,他也绘制一个影像,一个ShieldSymbolizer同样拥有PointSymbolizeallow_overlap和opacity属性。

请注意你可能需要调用ShieldSymbolizerdisplacement()方法来正确的定位文本, 若在默认情况下文本直接出现在点上,即图像的中央。

>>> import mapnik
>>> import os
>>>
>>> stylesheet =  'test_fig_poly_shield.xml'
>>>
>>> m = mapnik.Map(600, 200)
>>> mapnik.load_map(m, stylesheet)
>>>
>>> m.zoom_all()
>>> # env = m.envelope()
>>> # print(env)
>>> # box = mapnik.Box2d(env.minx - .1, env.miny - .3, env.maxx + .3, env.maxy + .3)
>>> # m.zoom_to_box(box)
>>>
>>> mapnik.render_to_file(m, 'xx_test_fig_poly_shield.png')
>>>
_images/xx_test_fig_poly_shield.png

9.8.3. 使用TextSymbolizer来绘制点符号

这里要介绍一种变通的技巧,直接使用TextSymbolizer来绘制点符号。

在前面两节中,我们介绍了使用 PointSymbolizerShieldSymbolizer 两种方式对点状要素进行绘制的方法, 除了默认的情况,都要求使用图片来绘制点状符号。 除去分辨率的因素,由于需要指定图片的大小, 在更换图片或是需要更换出图的大小时,都有一个重新设置的问题。

考虑一下前面提到过的标注,使用字体的时候,只需要指定字体大小(按一定的规范), 则会自动计算产生精美的结果。也可以使用标注的方式来绘制点符号。

前提是要有相应的字库。