目录

上一个主题

8.7. 绘制标注

下一个主题

8.9. 数据显示的规则

>>> from env_helper import info; info()
页面更新时间: 2022-12-28 08:26:47
运行环境:
    Linux发行版本: Debian GNU/Linux 11 (bullseye)
    操作系统内核: Linux-5.10.0-20-amd64-x86_64-with-glibc2.31
    Python版本: 3.9.2

8.8. 绘制点状要素

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

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

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

8.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()
>>>     # line_sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP
>>>     # line_sym.stroke_linejoin = mapnik.stroke_linejoin.ROUND_JOIN
>>>     # line_sym.stroke_dasharray = [(3,4)]
>>>     # line_sym.stroke_linecap = mapnik.stroke_linecap.SQUARE_CAP
>>>
>>>     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

图 8.6 result

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

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

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

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

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

8.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()方法来正确的定位文本, 若在默认情况下文本直接出现在点上,即图像的中央。

image0

8.8.3. 使用TextSymbolizer来绘制点符号

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

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

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

前提是要有相应的字库。这里我选择使用的是ESRI公司在ArcGIS软件中携带的字体 [2]。

使用SpatiaLite数据库文件,对表进行更新:

alter table dxt25w_E49C001001_respt_point add sty char(1);
-- 
update dxt25w_E49C001001_respt_point set sty='(' where gb=31091;
-- 
update dxt25w_E49C001001_respt_point set sty='5' where gb=31090;
-- 
update dxt25w_E49C001001_respt_point set sty='R' where gb=31080;
-- 区县
update dxt25w_E49C001001_respt_point set sty='H' where gb=31060 or gb=31061;
-- 
update dxt25w_E49C001001_respt_point set sty='P' where gb=31050;
-- 
update dxt25w_E49C001001_respt_point set sty='Q' where gb=31030;
-- 地区盟
update dxt25w_E49C001001_respt_point set sty='O' where gb=31040;

将字体设置为ESRI Default Marker Regular,即可产生相应的效果。

[1] 使用图像处理软件可以做到这一点,如开源图像处理软件 GIMP

[2] 这个涉及到版权问题,使用时请慎重