source: subversion/applications/rendering/pyrender/renderer_default.py @ 30322

Last change on this file since 30322 was 8514, checked in by spaetz, 11 years ago

fixup to last commit. python index are 0-based, of course.

File size: 8.7 KB
Line 
1#!/usr/bin/python
2#-----------------------------------------------------------------------------
3# Basic cairo renderer, that can plot OSM ways as coloured lines
4#-----------------------------------------------------------------------------
5# Copyright 2008, authors:
6# * Oliver White
7# * Sebastian Spaeth
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) 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, see <http://www.gnu.org/licenses/>.
21#----------------------------------------------------------------------------
22from render_cairo_base import OsmRenderBase
23
24roadColours = [
25  #tag=value:'r,g,b,width' with r,g,b between [0,1]
26  #a width of 0 means filling an area with a color
27  ('highway=motorway','0,0,0,13'),
28  ('highway=motorway','0.5,0.5,1,9'),
29  ('highway=motorway_link','0,0,0,13'),
30  ('highway=motorway_link','0.5,0.5,1,9'),
31  ('highway=trunk','0,0,0,10'),    # primary casing
32  ('highway=trunk','1,0.5,0.5,6'), # primary core
33  ('highway=primary','0,0,0,10'),    # primary casing
34  ('highway=primary','1,0.5,0.5,6'), # primary core
35  ('highway=secondary','0,0,0,8'),   # secondary casing
36  ('highway=secondary','1,0.5,0,4'),
37  ('highway=tertiary','0,0,0,6'),    # tertiary casing
38  ('highway=tertiary','1,0.5,0,2'),
39  ('highway=residential','0,0,0,4'),
40  ('highway=residential','0.75,0.75,0.75,2'),
41  ('highway=unclassified','0,0,0,4'),
42  ('highway=unclassified','0.75,0.75,0.75,2'),
43  ('highway=track','0.8,0.6,0.2,2'),
44  ('highway=footway','0.9,0.9,0.3,1'),
45  ('railway=rail','0,0,0,1'),
46  ('waterway=river','0.1,0.1,0.8,4'),
47  ('waterway=stream','0.1,0.1,0.8,2'),
48  ('landuse=forest','0.1,0.7,0.1,0'),
49  ('natural=wood','0.1,0.7,0.1,0'),
50  ('natural=water','0.1,0.1,0.8,0'),
51  ]
52
53waterColours = [
54  ('natural=water','0.1,0.1,0.8,0'),
55  ('waterway=river','0.1,0.1,0.8,8'),
56  ('waterway=riverbank','0.1,0.1,0.8,3'),
57  ('waterway=canal','0.1,0.1,0.8,6'),
58  ('waterway=stream', '0.1,0.1,0.8,2'),
59  ('waterway=aqueduct','0.1,0.1,0.8,6'),
60  ('waterway=drain','0.1,0.1,0.8,2'),
61  ('waterway=ditch','0.1,0.1,0.8,2'),
62  ('natural=coastline','0.1,0.1,0.8,6'),
63  ]
64
65powerColours = [
66  ('power=line','0,0,0,8'),
67  ('power=sub_station','0,0,0,0'),
68  ('power=substation','1,0,0,0'), # debug colour to show misspelling!
69  ]
70
71buildingColours = [
72  ('building=*','0,0,0,0'),
73  ]
74 
75def HTMLColorToRGB(colorstring):
76    """ convert #RRGGBB to an (R, G, B) tuple """
77    colorstring = colorstring.strip()
78    if colorstring[0] == '#': colorstring = colorstring[1:]
79    if len(colorstring) != 6:
80        raise ValueError, "input #%s is not in #RRGGBB format" % colorstring
81    r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:]
82    r, g, b = [int(n, 16) for n in (r, g, b)]
83    r, g, b = [float(n) / 256.0 for n in (r, g, b)]
84    return (r, g, b)
85
86
87def convert(colorstring):
88  (r,g,b) = HTMLColorToRGB(colorstring)
89  text = "%1.2f,%1.2f,%1.2f,%d" % (r,g,b,6)
90  return(text)
91 
92metroColours = [
93  ('line=Bakerloo', convert('996633')),
94  ('line=Central', convert('CC3333')),
95  ('line=Circle', convert('FFCC00')),
96  ('line=District', convert('006633')),
97  ('line=EastLondon', convert('FF9900')),
98  ('line=HammersmithAndCity', convert('CC9999')),
99  ('line=Jubilee', convert('868F98')),
100  ('line=Metropolitan', convert('660066')),
101  ('line=Northern', convert('000000')),
102  ('line=Piccadilly', convert('000099')),
103  ('line=Victoria', convert('0099CC')),
104  ('line=WaterlooAndCity', convert('66CCCC')),
105  ('line=Tramlink', convert('808080')),
106  ('line=DLR', convert('8080FF')),
107  ('railway=rail', '0,0,0,1'),
108  ('railway=station', '0,0,0,0'),
109  ]
110
111cycleColours = [
112  #tag=value:'r,g,b,width' with r,g,b between [0,1]
113  #a width of 0 means filling an area with a color
114  ('highway=footway','0.4,0,0,2'),
115  ('highway=cycleway','0,0.8,0,5'),
116  ('highway=bridleway','0,0.8,0,5'),
117  ('highway=residential','0.6,0.6,0.6,5'),
118  ('highway=unclassified','0.6,0.6,0.6,5'),
119  ('highway=tertiary','0.6,0.6,0.6,6'),
120  ('highway=secondary','0.6,0.6,0.6,6'),
121  ('highway=primary','0.6,0.6,0.6,7'),
122  ('highway=trunk','0.6,0.6,0.6,8'),
123  ('highway=motorway','0.6,0.6,0.6,9'),
124  ('cycleway=lane','0,0.8,0,3'),
125  ('cycleway=track','0,0.8,0,3'),
126  ('cycleway=opposite_lane','0,0.8,0,3'),
127  ('cycleway=opposite_track','0,0.8,0,3'),
128  ('cycleway=opposite','0,0.8,0,3'),
129  ('ncn_ref=*','1,0,0,5'),
130  ('rcn_ref=*','1,0,0.3,5'),
131  ('ncn=*','1,0,0,5'),
132  ('rcn=*','1,0,0.3,5'),
133  ]
134
135landuseColours = [
136  ('landuse=*', '0.6,0.6,0.6,0'),
137  ]
138
139boundaryColours = [
140  ('boundary=*', '0.6,0,0.6,2'),
141  ]
142
143nonameColours = [
144  ('name=~', '0.8,0,0,3'),
145  ]
146   
147unfinishedColours = [
148  ('todo=*', '0.8,0,0,3'),
149  ('to_do=*', '0.8,0,0,3'),
150  ('fixme=*', '0.8,0,0,3'),
151  ('fix_me=*', '0.8,0,0,3'),
152  ('FIXME=*', '0.8,0,0,3'),
153  ('note=*', '0,0.8,0,3'),
154  ('notes=*', '0,0.8,0,3'),
155  ]
156
157stylesheets = {
158  'underground':metroColours,
159  'default':roadColours,
160  'water':waterColours,
161  'power':powerColours,
162  'cycle':cycleColours,
163  'landuse':landuseColours,
164  'boundaries':boundaryColours,
165  'buildings':buildingColours,
166  'noname':nonameColours,
167  'unfinished':unfinishedColours,
168  };
169
170def wayStyles(layer, tags):
171  styles = []
172  stylesheet = stylesheets.get(layer, None)
173  if(stylesheet == None):
174    return([])
175 
176  for (ident, style) in stylesheet: #roadColours:
177    (tag,value) = ident.split('=')
178    if(tags.get(tag,'default') == value):
179      styles.append(style)
180    elif((value == '*') and (tags.get(tag, None) != None)):
181      styles.append(style)
182    elif((value == '~') and (tags.get(tag, None) == None)):
183      styles.append(style)
184  if(not styles):
185    styles.append('0.8,0.8,0.8,1') # default/debug
186  return(styles) 
187
188class RenderClass(OsmRenderBase):
189 
190  # Specify the background for new tiles
191  def imageBackgroundColour(self, mapLayer=None):
192    return(0,0,0,0)
193 
194  # draws a complete way
195  def draw_way(self, w):
196      layeradd = 0
197      for style in wayStyles(self.mapLayer, w['t']):
198        (r,g,b, width) = style.split(",")
199        width = int(width)
200       
201        layer = float(w['t'].get('layer',0)) + layeradd
202        ctx = self.getCtx(layer)
203        layeradd = layeradd + 0.1
204       
205        ctx.set_source_rgb(float(r),float(g),float(b))
206        ctx.set_line_width(width)
207        xy = []
208
209        for n in w['n']: 
210          # project that into image coordinates
211          xy.append(self.proj.project(float(n['lat']), float(n['lon'])))
212          #print "%f,%f -> %f, %f" % (n['lat'], n['lon'], x,y)
213
214        #return a list of 2*xy control points for bezier curving
215        #set to None to disable bezier curving
216        #filter zoom>15; disable 'buildings' layer; also not building=* 
217        if self.z > 15 \
218        and self.mapLayer != 'buildings' \
219        and not w['t'].has_key('building'):
220            bezier_cp = self.beziercurve(xy)
221        else: bezier_cp = None
222
223        # draw lines on the image
224        # first return starting point of path
225        x,y = xy[0] 
226        ctx.move_to(x, y)
227        # next, draw all path segments
228        for (x,y) in xy[1:]: 
229          if bezier_cp != None:
230              cp1_x,cp1_y = bezier_cp.pop(0)
231              cp2_x,cp2_y = bezier_cp.pop(0)
232              ctx.curve_to(cp1_x,cp1_y,cp2_x,cp2_y,x ,y)
233          else: ctx.line_to(x, y)
234
235        #finally fill with area color or stroke a path
236        if width > 0: ctx.stroke()
237        else: ctx.fill()
238
239  # Draw a complete tile
240  def draw(self):
241    """Draw a complete tile. This is the main function that is used by the
242    plug-in rendering system. Context information is available through:
243    self.mapLayer= Layer that should be used for drawing (e.g. 'underground')
244    self.z       = Zoom level that we draw
245    """
246    # Ways
247    for w in self.osm.ways.values():
248      self.draw_way(w)
249
250    # POIs
251    if(0):
252      for poi in self.osm.poi:
253        n = poi['id']
254        (lat,lon) = self.osm.nodes[n]
255        (x,y) = self.proj.project(lat,lon)
256        s = 1
257        self.drawContext.rectangle((x-s,y-s,x+s,y+s),fill='blue')
258
259
260
261#-----------------------------------------------------------------
262# Test suite - call this file from the command-line to generate a
263# sample image
264if(__name__ == '__main__'):
265  a = RenderClass()
266  filename = "sample_"+__file__+".png"
267  # a.RenderTile(15, 16372, 10895, filename) # london
268  a.RenderTile(14, 8166, 5447, 'default', filename) # Z14
269 
270  print "------------------------------------"
271  print "Saved image to " + filename
Note: See TracBrowser for help on using the repository browser.