root/trunk/demo/python/rundemo.py

Revision 703, 10.6 kB (checked in by artem, 8 weeks ago)

reverting back to 700

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