在访问一幅地图上的给定的地理空间数据之前,你需要设置一个Mapnik 数据源对象。并用它充当Mapnik和地理空间数据的桥梁。
通常,创建的数据源是使用如下所述的函数之一。 然后,添加这个数据源到需要使用这个数据的Mapnik的图层对象中:
layer.datasource = datasource
一个简单的数据源对象可以被很多图层共用,也可以仅仅被一个图层使用。 Mapnik支持不同类型的数据源,除了开源工具生产或服务的数据,也有一些是商业数据库存储的数据。
import mapnik
datasource = mapnik.Shapefile(file="/data/gdata/GSHHS_c.shp")
如果shape文件在不同的目录,可以使用os.path.join()
来定义完整的路径。
例如,你可以在一个目录中打开与你Python程序相关的shape文件:
import os
datasource = mapnik.Shapefile(file=os.path.join("/gdata", 'GSHHS_c.shp'))
当你打开一个shape文件数据源,shape文件的属性可以用在过滤器的表达式中,并且作为由TextSymbolizer显示的字段。 在默认情况下,shape文件中的文本都被假定为UTF-8字符编码。如果你需要使用不同的编码,你可以使用编码参数,例如:
datasource = mapnik.Shapefile(file="/data/gdata/GSHHS_c.shp", encoding="latin1")
datasource = mapnik.SQLite(file="mapData.db", table="countries", geometry_field="outline", key_field="id")
在countries表中的所有字段都可用在Mapnik过滤器中,也可用TextSymbolizer进行展示。
各种symbolizers将使用存储在outline字段中的几何结构来绘制线条、多边形等等。
import mapnik
datasource = mapnik.Gdal(file="/data/gdata/foo.tif")
Mapnik提供了另一种阅读TIFF格式光栅图像的方法,使用栅格数据源。在一般情况下,使用GDAL数据源比栅格更加灵活,也更方便。
OGR
OGR数据源使你在地图上显示任何一个OGR兼容载体上的数据。 OGR数据源的便利构造至少需要两个命名参数:
datasource = mapnik.Ogr(file="...", layer="...")
file
的参数就是 OGR 兼容的数据文件的名称, 而layer
则是在数据文件中被需要的图层的名字。例如,你通过 OGR 驱动读取一个
shape文件。
datasource = mapnik.Ogr(file="shapefile.shp", layer="shapefile")
更有用的是,你可以从OGR支持的任何矢量格式的数据文件来加载数据。
OGR加载虚拟数据表
我们特别感兴趣的是虚拟的DataSource(VRT)格式。 VRT格式是XML格式的文件,它允许你设置没有存储在盘上的一个简单的文件的OGR数据源。 在前面的章节中我们可以看到, 它是怎样在地图上显示来源于MySQL数据库中的数据, 事实上,Mapnik本身并没有执行一个MySQL的数据源。 虽然在OGR网页上已经解释的很透彻了,但是VRT文件格式还是比较复杂的。 下面是一个例子,你能使用VRT文件设置一个MySQL虚拟数据源:
<OGRVRTDataSource>
<OGRVRTLayer name="myLayer">
<SrcDataSource>MYSQL:mydb,user=user,password=pass,
tables=myTable</SrcDataSource>
<SrcSQL>
SELECT name,geom FROM myTable
</SrcSQL>
</OGRVRTLayer>
</OGRVRTDataSource>
<SrcDataSource>
组成中包含了设置OGR
MySQL数据源的字符串。这个字符串的格式为:
MySQL:<dbName>,user=<username>,password=<pass>,tables=<tables>
用数据库的名称代替<dbName>
,username
和pass
是访问MySQL数据库的用户名和密码,
tables
是你要从数据库检索数据的列表。
如果你从多个数据表中检索数据,你需要用分号单独列出数据表,例如:
tables=lakes;rivers;coastlines
注意:在<SrcDataSource>
和</SrcDataSource>
之间的所有文本都必须是单独一行的。
在<SrcSQL>
组成里面的文本应该是一个MySQL的select
语句,
它是从数据库表中检索出来所需要的信息。
对于PostGIS的数据源,在传递到Mapnik之前,你可以用它来过滤掉不需要的记录,这样将会显著提高性能。
VRT文件应该被保存到磁盘中。
例如,上述虚拟文件所定义的内容将会保存到一个文件名为myLayer.vrt
的文本文件中。
然后你可以在Mapnik中用这个文件来定义OGR数据源,例如:
datasource = mapnik.Ogr(file="myLayer.vrt", layer="myLayer")
PointDatasource
PointDatasource对于Mapnik是一个相对比较新的功能。 点数据不是来源于数据文件,而是在程序运行的时候创建的数据。 它可以让你手动定义一些将要出现在地图上的数据点。 建立一个点数据源是非常简单的,即你只需创建PointDatasource对象:
datasource = mapnik.PointDatasource()
然后,你可以使用PointDatasource的 add_point()
来添加单个点源。
这种方法需要四个参数:
long
:点的经度。lat
:点的纬度。key
:点的属性名称。value
:点的属性值。
通常你会对每个数据点使用相同的key
,并且为适当的字符串设置value
,
然后你可以在地图上显示这些字符串。
例如:下面的代码,结合PointDatasource与TextSymbolizer在特定的经度或纬度的地图上放置标记。
import os
import mapnik
stylesheet = '/data/gdata/world_population.xml'
m = mapnik.Map(600,300)
mapnik.load_map(m, stylesheet)
m.background = mapnik.Color('steelblue')
s = mapnik.Style()
r = mapnik.Rule()
# polygon_symbolizer = mapnik.PolygonSymbolizer(mapnik.Color('#FF3366'))
polygon_symbolizer = mapnik.PolygonSymbolizer()
polygon_symbolizer.fill = mapnik.Color('#f2eff9')
r.symbols.append(polygon_symbolizer)
s.rules.append(r)
m.append_style('My Style2',s)
wkt_geom = 'POLYGON ((5.0 -5, -26.0 -5, -26 -30.0, 5.0 -30.0, 5.0 -5.0))'
csv_string = '''
wkt,Name
"%s","test"
''' % wkt_geom
ds = mapnik.Datasource(**{"type":"csv","inline":csv_string})
注意下面的投影,与地图一致。
layer2 = mapnik.Layer('world', '+proj=latlong +datum=WGS84')
layer2.datasource = ds
layer2.styles.append('My Style2')
m.layers.append(layer2)
bbox = mapnik.Box2d(-180.0,-90.0,180.0,90.0)
m.zoom_to_box(bbox)
# m.zoom_all()
mapnik.render_to_file(m,'xx_ds_pt.png', 'png')
# print "rendered image to 'world.png'"
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Cell In[7], line 9 7 m.zoom_to_box(bbox) 8 # m.zoom_all() ----> 9 mapnik.render_to_file(m,'xx_ds_pt.png', 'png') 10 # print "rendered image to 'world.png'" RuntimeError: Shape Plugin: no attribute 'NAME' in '/gdata/GSHHS_c'. Valid attributes are: id,level,source,parent_id,sibling_id,area,Shape_Leng,Shape_Area.
from IPython.display import Image
Image('./xx_ds_pt.png')