User:Moresby/Understanding Mapnik/Adding text to the map

From OpenStreetMap Wiki
Jump to: navigation, search
Understanding Mapnik
A Mapnik tutorial
Starting with Python
Using XML and CSS
CartoCSS and PostGIS
060-text.png - towns, cities, roads and motorways marked, labelled with text

Placing text on a map can be a complicated process. Here we look at the basics, putting labels on our places and roads.

  1 #!/usr/bin/python
  2 
  3 # Load the Python mapnik libraries.
  4 import mapnik
  5 
  6 # Create a new map.
  7 m = mapnik.Map(480, 320)
  8 
  9 # Set the background colour.
 10 m.background = mapnik.Color('ghostwhite')
 11 
 12 # Create a stroke object for railways.
 13 stroke_rail = mapnik.Stroke()
 14 stroke_rail.color = mapnik.Color('black')
 15 stroke_rail.dasharray = [ (6, 2) ]
 16 stroke_rail.width = 2
 17 
 18 # Create point, line and text symbolizers.
 19 point_symbolizer_city = mapnik.PointSymbolizer(mapnik.PathExpression('circle_red_16x16.png'))
 20 point_symbolizer_town = mapnik.PointSymbolizer(mapnik.PathExpression('circle_red_8x8.png'))
 21 line_symbolizer_rail = mapnik.LineSymbolizer(stroke_rail)
 22 line_symbolizer_road = mapnik.LineSymbolizer()
 23 line_symbolizer_mainroad = mapnik.LineSymbolizer(mapnik.Color('black'), 2)
 24 line_symbolizer_motorway = mapnik.LineSymbolizer(mapnik.Color('lightblue'), 4)
 25 
 26 text_symbolizer_roads = mapnik.TextSymbolizer()
 27 text_symbolizer_roads.name = '[name]'
 28 text_symbolizer_roads.face_name = 'DejaVu Sans Book'
 29 text_symbolizer_roads.halo_radius = 2
 30 text_symbolizer_roads.label_placement = mapnik.label_placement.line
 31 
 32 text_symbolizer_towns = mapnik.TextSymbolizer()
 33 text_symbolizer_towns.name = '[name]'
 34 text_symbolizer_towns.face_name = 'DejaVu Sans Book'
 35 text_symbolizer_towns.halo_radius = 3
 36 text_symbolizer_towns.displacement = (0, 7)
 37 
 38 text_symbolizer_cities = mapnik.TextSymbolizer()
 39 text_symbolizer_cities.name = '[name]'
 40 text_symbolizer_cities.face_name = 'DejaVu Sans Book'
 41 text_symbolizer_cities.halo_radius = 3
 42 text_symbolizer_cities.displacement = (0, 11)
 43 text_symbolizer_cities.fill = mapnik.Color('red')
 44 text_symbolizer_cities.text_size = 12
 45 
 46 # Create new rules and add the symbolizers.
 47 r_city = mapnik.Rule()
 48 r_city.symbols.append(point_symbolizer_city)
 49 r_city.symbols.append(text_symbolizer_cities)
 50 r_city.filter = mapnik.Filter('[type] = "city"')
 51 
 52 r_town = mapnik.Rule()
 53 r_town.symbols.append(point_symbolizer_town)
 54 r_town.symbols.append(text_symbolizer_towns)
 55 r_town.filter = mapnik.Filter('[type] = "town"')
 56 
 57 r_rail = mapnik.Rule()
 58 r_rail.symbols.append(line_symbolizer_rail)
 59 r_rail.filter = mapnik.Filter('[type] = "rail"')
 60 
 61 r_road = mapnik.Rule()
 62 r_road.symbols.append(line_symbolizer_road)
 63 r_road.symbols.append(text_symbolizer_roads)
 64 r_road.filter = mapnik.Filter('[type] = "road"')
 65 
 66 r_mainroad = mapnik.Rule()
 67 r_mainroad.symbols.append(line_symbolizer_mainroad)
 68 r_mainroad.symbols.append(text_symbolizer_roads)
 69 r_mainroad.filter = mapnik.Filter('[type] = "mainroad"')
 70 
 71 r_motorway = mapnik.Rule()
 72 r_motorway.symbols.append(line_symbolizer_motorway)
 73 r_motorway.symbols.append(text_symbolizer_roads)
 74 r_motorway.filter = mapnik.Filter('[type] = "motorway"')
 75 
 76 # Create new styles and add the rules.
 77 s_point = mapnik.Style()
 78 s_point.rules.append(r_town)
 79 s_point.rules.append(r_city)
 80 
 81 s_line = mapnik.Style()
 82 s_line.rules.append(r_rail)
 83 s_line.rules.append(r_road)
 84 s_line.rules.append(r_mainroad)
 85 s_line.rules.append(r_motorway)
 86 
 87 # Add the styles to the map.
 88 m.append_style('point_style', s_point)
 89 m.append_style('line_style', s_line)
 90 
 91 # Specify our data sources.
 92 ds_point = mapnik.CSV(file='data-places.csv')
 93 ds_line = mapnik.CSV(file='data-roads.csv')
 94 
 95 # Create new layers for the map, add the data sources and styles to
 96 #   those layers.
 97 l_point = mapnik.Layer('point_layer')
 98 l_point.datasource = ds_point
 99 l_point.styles.append('point_style')
100 l_line = mapnik.Layer('line_layer')
101 l_line.datasource = ds_line
102 l_line.styles.append('line_style')
103 
104 # Add the layers to the map. We want the points to appear in front of the
105 #   lines, so we add the line layer first.
106 m.layers.append(l_line)
107 m.layers.append(l_point)
108 
109 # Zoom to the part of the map we are interested in.
110 m.zoom_to_box(mapnik.Box2d(0, 0, 480, 320))
111 
112 # Save the map as a PNG image.
113 mapnik.render_to_file(m, '060-text.png', 'png')

Save this program in a file called 060-text.py and run it by typing:

python 060-text.py

You should see no error messages, and you should see a new file in your working directory called 060-text.png. This is a new map image, and should be a light-coloured rectangle 480 pixels wide by 320 pixels high, with towns, cities and roads labelled with text, as shown above.

References