root/trunk/demo/python/rundemo.py

Revision 1665, 13.5 kB (checked in by artem, 2 days ago)

+ use mapnik2 for python module name
+ update rundemo.py

  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# $Id$
5#
6# This file is part of Mapnik (c++ mapping toolkit)
7# Copyright (C) 2005 Jean-Francois Doyon
8#
9# Mapnik is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License
11# as published by the Free Software Foundation; either version 2
12# of the License, or any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23# Import everything.  In this case this is safe, in more complex systems, you
24# will want to be more selective.
25
26import sys
27
28try:
29    import mapnik2
30except:
31    print '\n\nThe mapnik library and python bindings must have been compiled and \
32installed successfully before running this script.\n\n'
33    sys.exit(1)
34
35try:
36    import cairo
37    HAS_PYCAIRO_MODULE = True
38except ImportError:
39    HAS_PYCAIRO_MODULE = False
40
41# Instanciate a map, giving it a width and height. Remember: the word "map" is
42# reserved in Python! :)
43
44m = mapnik2.Map(800,600,"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs")
45
46# Set its background colour. More on colours later ...
47
48m.background = mapnik2.Color('white')
49
50# Now we can start adding layers, in stacking order (i.e. bottom layer first)
51
52# Canadian Provinces (Polygons)
53
54# Instanciate a layer.  The parameters depend on the type of data:
55# shape:
56#     type='shape'
57#     file='/path/to/shape'
58# raster:
59#     type='raster'
60#     file='/path/to/raster'
61# postgis:
62#     type='postgis'
63#     host='127.0.0.1'
64#     dbname='mydatabase'
65#     user='myusername'
66#     password='mypassword'
67#     table= TODO
68
69provpoly_lyr = mapnik2.Layer('Provinces')
70provpoly_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
71provpoly_lyr.datasource = mapnik2.Shapefile(file='../data/boundaries', encoding='latin1')
72
73# We then define a style for the layer.  A layer can have one or many styles.
74# Styles are named, so they can be shared across different layers.
75# Multiple styles per layer behaves functionally like multiple layers.  The
76# data is completely re-scanned for each style within one layer, and a style
77# will be drawn entirely "above" the previous one.  Performance wise using
78# multiple styles in one layer is the same has having multiple layers.
79# The paradigm is useful mostly as a convenience.
80
81provpoly_style = mapnik2.Style()
82
83# A Style needs one or more rules.  A rule will normally consist of a filter
84# for feature selection, and one or more symbolizers.
85
86provpoly_rule_on = mapnik2.Rule()
87
88# A Expression() allows the selection of features to which the symbology will
89# be applied.  More on Mapnik expressions can be found in Tutorial #2.
90# A given feature can only match one filter per rule per style.
91
92provpoly_rule_on.filter = mapnik2.Expression("[NAME_EN] = 'Ontario'")
93
94# Here a symbolizer is defined.  Available are:
95#     - LineSymbolizer(Color(),<width>)
96#     - LineSymbolizer(Stroke())
97#     - PolygonSymbolizer(Color())
98#     - PointSymbolizer(<file>,<type>,<width>,<height>)
99
100# Some of them can accept a Color() instance, which can be created with:
101#     - Color(<red>, <green>, <blue>)
102#     - Color(<red>, <green>, <blue>, <alpha>)
103#     - Color(<string>) where <string> will be something like '#00FF00'
104#       or '#0f0' or 'green'
105
106provpoly_rule_on.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(250, 190, 183)))
107provpoly_style.rules.append(provpoly_rule_on)
108
109provpoly_rule_qc = mapnik2.Rule()
110provpoly_rule_qc.filter = mapnik2.Expression("[NOM_FR] = 'Québec'")
111provpoly_rule_qc.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(217, 235, 203)))
112provpoly_style.rules.append(provpoly_rule_qc)
113
114# Add the style to the map, giving it a name.  This is the name that will be
115# used to refer to it from here on.  Having named styles allows them to be
116# re-used throughout the map.
117
118m.append_style('provinces', provpoly_style)
119
120# Then associate the style to the layer itself.
121
122provpoly_lyr.styles.append('provinces')
123
124# Then add the layer to the map.  In reality, it's the order in which you
125# append them to the map that will determine the drawing order, though by
126# convention it is recommended to define them in drawing order as well.
127
128m.layers.append(provpoly_lyr)
129
130# Drainage
131
132# A simple example ...
133
134qcdrain_lyr = mapnik2.Layer('Quebec Hydrography')
135qcdrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
136qcdrain_lyr.datasource = mapnik2.Shapefile(file='../data/qcdrainage')
137
138qcdrain_style = mapnik2.Style()
139qcdrain_rule = mapnik2.Rule()
140qcdrain_rule.filter = mapnik2.Expression('[HYC] = 8')
141qcdrain_rule.symbols.append(mapnik2.PolygonSymbolizer(mapnik2.Color(153, 204, 255)))
142qcdrain_style.rules.append(qcdrain_rule)
143
144m.append_style('drainage', qcdrain_style)
145qcdrain_lyr.styles.append('drainage')
146m.layers.append(qcdrain_lyr)
147
148# In this case, we have 2 data sets with similar schemas (same filtering
149# attributes, and same desired style), so we're going to
150# re-use the style defined in the above layer for the next one.
151
152ondrain_lyr = mapnik2.Layer('Ontario Hydrography')
153ondrain_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
154ondrain_lyr.datasource = mapnik2.Shapefile(file='../data/ontdrainage')
155
156ondrain_lyr.styles.append('drainage')
157m.layers.append(ondrain_lyr)
158
159# Provincial boundaries
160
161provlines_lyr = mapnik2.Layer('Provincial borders')
162provlines_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
163provlines_lyr.datasource = mapnik2.Shapefile(file='../data/boundaries_l')
164
165# Here we define a "dash dot dot dash" pattern for the provincial boundaries.
166
167provlines_stk = mapnik2.Stroke()
168provlines_stk.add_dash(8, 4)
169provlines_stk.add_dash(2, 2)
170provlines_stk.add_dash(2, 2)
171provlines_stk.color = mapnik2.Color('black')
172provlines_stk.width = 1.0
173
174provlines_style = mapnik2.Style()
175provlines_rule = mapnik2.Rule()
176provlines_rule.symbols.append(mapnik2.LineSymbolizer(provlines_stk))
177provlines_style.rules.append(provlines_rule)
178
179m.append_style('provlines', provlines_style)
180provlines_lyr.styles.append('provlines')
181m.layers.append(provlines_lyr)
182
183# Roads 3 and 4 (The "grey" roads)
184
185roads34_lyr = mapnik2.Layer('Roads')
186roads34_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
187# create roads datasource (we're going to re-use it later)
188
189roads34_lyr.datasource = mapnik2.Shapefile(file='../data/roads')
190
191roads34_style = mapnik2.Style()
192roads34_rule = mapnik2.Rule()
193roads34_rule.filter = mapnik2.Expression('([CLASS] = 3) or ([CLASS] = 4)')
194
195# With lines of a certain width, you can control how the ends
196# are closed off using line_cap as below.
197
198roads34_rule_stk = mapnik2.Stroke()
199roads34_rule_stk.color = mapnik2.Color(171,158,137)
200roads34_rule_stk.line_cap = mapnik2.line_cap.ROUND_CAP
201
202# Available options are:
203# line_cap: BUTT_CAP, SQUARE_CAP, ROUND_CAP
204# line_join: MITER_JOIN, MITER_REVERT_JOIN, ROUND_JOIN, BEVEL_JOIN
205
206# And one last Stroke() attribute not used here is "opacity", which
207# can be set to a numerical value.
208
209roads34_rule_stk.width = 2.0
210roads34_rule.symbols.append(mapnik2.LineSymbolizer(roads34_rule_stk))
211roads34_style.rules.append(roads34_rule)
212
213m.append_style('smallroads', roads34_style)
214roads34_lyr.styles.append('smallroads')
215m.layers.append(roads34_lyr)
216
217# Roads 2 (The thin yellow ones)
218
219roads2_lyr = mapnik2.Layer('Roads')
220roads2_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
221# Just get a copy from roads34_lyr
222roads2_lyr.datasource = roads34_lyr.datasource
223
224roads2_style_1 = mapnik2.Style()
225roads2_rule_1 = mapnik2.Rule()
226roads2_rule_1.filter = mapnik2.Expression('[CLASS] = 2')
227roads2_rule_stk_1 = mapnik2.Stroke()
228roads2_rule_stk_1.color = mapnik2.Color(171,158,137)
229roads2_rule_stk_1.line_cap = mapnik2.line_cap.ROUND_CAP
230roads2_rule_stk_1.width = 4.0
231roads2_rule_1.symbols.append(mapnik2.LineSymbolizer(roads2_rule_stk_1))
232roads2_style_1.rules.append(roads2_rule_1)
233
234m.append_style('road-border', roads2_style_1)
235
236roads2_style_2 = mapnik2.Style()
237roads2_rule_2 = mapnik2.Rule()
238roads2_rule_2.filter = mapnik2.Expression('[CLASS] = 2')
239roads2_rule_stk_2 = mapnik2.Stroke()
240roads2_rule_stk_2.color = mapnik2.Color(255,250,115)
241roads2_rule_stk_2.line_cap = mapnik2.line_cap.ROUND_CAP
242roads2_rule_stk_2.width = 2.0
243roads2_rule_2.symbols.append(mapnik2.LineSymbolizer(roads2_rule_stk_2))
244roads2_style_2.rules.append(roads2_rule_2)
245
246m.append_style('road-fill', roads2_style_2)
247
248roads2_lyr.styles.append('road-border')
249roads2_lyr.styles.append('road-fill')
250
251m.layers.append(roads2_lyr)
252
253# Roads 1 (The big orange ones, the highways)
254
255roads1_lyr = mapnik2.Layer('Roads')
256roads1_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
257roads1_lyr.datasource = roads34_lyr.datasource
258
259roads1_style_1 = mapnik2.Style()
260roads1_rule_1 = mapnik2.Rule()
261roads1_rule_1.filter = mapnik2.Expression('[CLASS] = 1')
262roads1_rule_stk_1 = mapnik2.Stroke()
263roads1_rule_stk_1.color = mapnik2.Color(188,149,28)
264roads1_rule_stk_1.line_cap = mapnik2.line_cap.ROUND_CAP
265roads1_rule_stk_1.width = 7.0
266roads1_rule_1.symbols.append(mapnik2.LineSymbolizer(roads1_rule_stk_1))
267roads1_style_1.rules.append(roads1_rule_1)
268m.append_style('highway-border', roads1_style_1)
269
270roads1_style_2 = mapnik2.Style()
271roads1_rule_2 = mapnik2.Rule()
272roads1_rule_2.filter = mapnik2.Expression('[CLASS] = 1')
273roads1_rule_stk_2 = mapnik2.Stroke()
274roads1_rule_stk_2.color = mapnik2.Color(242,191,36)
275roads1_rule_stk_2.line_cap = mapnik2.line_cap.ROUND_CAP
276roads1_rule_stk_2.width = 5.0
277roads1_rule_2.symbols.append(mapnik2.LineSymbolizer(roads1_rule_stk_2))
278roads1_style_2.rules.append(roads1_rule_2)
279
280m.append_style('highway-fill', roads1_style_2)
281
282roads1_lyr.styles.append('highway-border')
283roads1_lyr.styles.append('highway-fill')
284
285m.layers.append(roads1_lyr)
286
287# Populated Places
288
289popplaces_lyr = mapnik2.Layer('Populated Places')
290popplaces_lyr.srs = "+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs"
291popplaces_lyr.datasource = mapnik2.Shapefile(file='../data/popplaces',encoding='latin1')
292
293popplaces_style = mapnik2.Style()
294popplaces_rule = mapnik2.Rule()
295
296# And here we have a TextSymbolizer, used for labeling.
297# The first parameter is the name of the attribute to use as the source of the
298# text to label with.  Then there is font size in points (I think?), and colour.
299
300popplaces_text_symbolizer = mapnik2.TextSymbolizer(mapnik2.Expression("[GEONAME]"),
301                                           'DejaVu Sans Book',
302                                           10, mapnik2.Color('black'))
303
304# We set a "halo" around the text, which looks like an outline if thin enough,
305# or an outright background if large enough.
306popplaces_text_symbolizer.label_placement= mapnik2.label_placement.POINT_PLACEMENT
307popplaces_text_symbolizer.halo_fill = mapnik2.Color('white')
308popplaces_text_symbolizer.halo_radius = 1
309popplaces_text_symbolizer.avoid_edges = True
310popplaces_rule.symbols.append(popplaces_text_symbolizer)
311
312popplaces_style.rules.append(popplaces_rule)
313
314m.append_style('popplaces', popplaces_style)
315popplaces_lyr.styles.append('popplaces')
316m.layers.append(popplaces_lyr)
317
318# Draw map
319
320# Set the initial extent of the map in 'master' spherical Mercator projection
321m.zoom_to_box(mapnik2.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855)) 
322
323# Render two maps, two PNGs, one JPEG.
324im = mapnik2.Image(m.width,m.height)
325mapnik2.render(m, im)
326
327# Save image to files
328images_ = []
329im.save('demo.png', 'png') # true-colour RGBA
330images_.append('demo.png')
331im.save('demo256.png', 'png256') # save to palette based (max 256 colours) png
332images_.append('demo256.png')
333im.save('demo_high.jpg', 'jpeg100')
334images_.append('demo_high.jpg')
335im.save('demo_low.jpg', 'jpeg50')
336images_.append('demo_low.jpg')
337
338# Render cairo examples
339if HAS_PYCAIRO_MODULE and mapnik2.has_pycairo():
340   
341    svg_surface = cairo.SVGSurface('demo.svg', m.width,m.height)
342    mapnik2.render(m, svg_surface)
343    svg_surface.finish()
344    images_.append('demo.svg')
345
346    pdf_surface = cairo.PDFSurface('demo.pdf', m.width,m.height)
347    mapnik2.render(m, pdf_surface)
348    images_.append('demo.pdf')
349    pdf_surface.finish()
350
351    postscript_surface = cairo.PSSurface('demo.ps', m.width,m.height)
352    mapnik2.render(m, postscript_surface)
353    images_.append('demo.ps')
354    postscript_surface.finish()   
355
356else:
357    print '\n\nPycairo not available...',
358    if  mapnik2.has_cairo():
359        print ' will render Cairo formats using alternative method'
360       
361        mapnik2.render_to_file(m,'demo.pdf')
362        images_.append('demo.pdf')
363        mapnik2.render_to_file(m,'demo.ps')
364        images_.append('demo.ps')
365        mapnik2.render_to_file(m,'demo.svg')
366        images_.append('demo.svg')
367        mapnik2.render_to_file(m,'demo_cairo_rgb.png','RGB24')
368        images_.append('demo_cairo_rgb.png')
369        mapnik2.render_to_file(m,'demo_cairo_argb.png','ARGB32')
370        images_.append('demo_cairo_argb.png')
371
372print "\n\n", len(images_), "maps have been rendered in the current directory:"
373   
374for im_ in images_:
375    print "-", im_
376
377print "\n\nHave a look!\n\n"
378
379mapnik2.save_map(m,"map.xml")
Note: See TracBrowser for help on using the browser.