User:Moresby/Understanding Mapnik/Plotting lines
As well as plotting points, Mapnik allows us to plot lines. Here we plot some of the rail and road connections between our locations.
#!/usr/bin/python
# Load the Python mapnik libraries.
import mapnik
# Create a new map.
m = mapnik.Map(480, 320)
# Set the background colour.
m.background = mapnik.Color('ghostwhite')
# Create a line symbolizer.
line_symbolizer = mapnik.LineSymbolizer()
# Create a new rule and add the symbolizer.
r = mapnik.Rule()
r.symbols.append(line_symbolizer)
# Create a new style and add the rule.
s = mapnik.Style()
s.rules.append(r)
# Add the style to the map.
m.append_style('basic_style', s)
# Specify that our data is coming from a CSV file called "data-roads.csv".
ds = mapnik.CSV(file='data-roads.csv')
# Create a new layer for the map, called "main_map" and add the data
# source and style to that layer.
l = mapnik.Layer('main_map')
l.datasource = ds
l.styles.append('basic_style')
# Add the layer to the map.
m.layers.append(l)
# Zoom to the part of the map we are interested in.
m.zoom_to_box(mapnik.Box2d(0, 0, 480, 320))
# Save the map as a PNG image.
mapnik.render_to_file(m, '030-lines.png', 'png')
- There are only a few significant differences between this program and the one for plotting points:
- At line thirteen we create a LineSymbolizer, rather than a PointSymbolizer, and at line seventeen, we add that our rule's symbolizer list.
- At line 27 we get our line data from CSV file
data-roads.csv
, rather than point data fromdata-places.csv
.
We also need to have some data to plot. The following data represent some of the roads and rail links between some of the towns and cities we used earlier. Save the following lines in a file called data-roads.csv
:
name, type, wkt
"A1", mainroad, "LINESTRING(119 17, 108 133, 131 188, 113 308)"
"A10", mainroad, "LINESTRING(221 125, 179 51)"
"A11", road, "LINESTRING(409 231, 307 146, 259 39)"
"M11", motorway, "LINESTRING(220 -81, 259 39, 221 125)"
"A14", mainroad, "LINESTRING(483 119, 398 147, 307 146, 221 125, 131 188, -29 222)"
"A30", mainroad, "LINESTRING(221 125, 220 144, 248 204, 263 222)"
"A134", road, "LINESTRING(409 231, 398 147)"
"A141", road, "LINESTRING(213 297, 131 188)"
"A142", road, "LINESTRING(307 146, 263 222)"
"A421", road, "LINESTRING(108 133, 48 93)"
"A422", road, "LINESTRING( 48 93, -22 79)"
"A428", road, "LINESTRING(108 133, 221 125)"
"A505", road, "LINESTRING(179 51, 119 17)"
"A605", road, "LINESTRING(113 308, 120 300, 204 312, 213 297)"
"A1101", road, "LINESTRING(398 147, 263 222)"
"A1123", road, "LINESTRING(263 222, 164 190, 131 188)"
"A1198", road, "LINESTRING(179 51, 131 188)"
"railway", rail, "LINESTRING(113 308, 213 297, 263 222, 409 231)"
"railway", rail, "LINESTRING(263 222, 221 125)"
- This file is a simple comma-separated variable (CSV) file.
- The first line specifies what data is provided in the file. In this case it tells us to expect lines which each contain three values, to be labelled "name", "type" and "wkt". The field name "wkt" tells Mapnik that the data in the third field will be well-known text (WKT, see below), describing the position of our roads.
- The second line is blank. This is ignored by Mapnik.
- The remaining lines each represent one town or city, and contains the following fields, separated by commas:
- the name of the road
- a single value describing the road type:
road
,mainroad
,motorway
orrail
- the well-known text describing the position of the road
- The columns have been spaced to line up neatly to make the data more readable, but this isn't necessary: Mapnik splits each line where it finds a comma, and then tidies up any whitespace around it.
- The road names have been put in double quotes. For our data, this is not actually necessary.
Well-known text
The rather cryptically named "well-known text" is a standardised way of representing geometry objects, including points, lines and polygons. Here we are using the LineString WKT type to represent roads and railways. In the data-places.csv
file in previous examples, we could have represented town and city coordinates using the Point WKT type. This version of the data-places.csv
file gives identical results in our examples:
name, type, wkt
"Bedford", town, "POINT( 48 93)"
"Bury St Edmunds", town, "POINT(398 147)"
"Cambridge", city, "POINT(221 125)"
"Ely", city, "POINT(263 222)"
"Harlow", town, "POINT(220 -81)"
"Huntingdon", town, "POINT(131 188)"
"Kettering", town, "POINT(-29 222)"
"Letchworth", town, "POINT(119 17)"
"March", town, "POINT(213 297)"
"Newmarket", town, "POINT(307 146)"
"Peterborough", city, "POINT(113 308)"
"Royston", town, "POINT(179 51)"
"Saffron Walden", town, "POINT(259 39)"
"Sherington", town, "POINT(-22 79)"
"St Ives", town, "POINT(164 190)"
"St Neots", town, "POINT(108 133)"
"Stowmarket", town, "POINT(483 119)"
"Thetford", town, "POINT(409 231)"
Save this program in a file called 030-lines.py
and run it by typing:
python 030-lines.py
You should see no error messages, and you should see a new file in your working directory called 030-lines.png. This is a new map image, and should be a light-coloured rectangle 480 pixels wide by 320 pixels high, with a series of interconnected black lines, as shown above.