e6a50210e36cf5e1d96c2540abcabbf79f2ec267
[pyrungps.git] / generate_image.py
1 #!/usr/bin/env python
2
3 try:
4     import mapnik2 as mapnik
5 except:
6     import mapnik
7
8 import sys, os
9
10 from lxml import html,etree
11 from optparse import OptionParser
12
13 from pprint import pprint
14
15 import pygpx
16
17 # Set up projections
18 # spherical mercator (most common target map projection of osm data imported with osm2pgsql)
19 merc = mapnik.Projection('+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 +over')
20
21 # long/lat in degrees, aka ESPG:4326 and "WGS 84" 
22 longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
23 # can also be constructed as:
24 #longlat = mapnik.Projection('+init=epsg:4326')
25
26 # ensure minimum mapnik version
27 if not hasattr(mapnik,'mapnik_version') and not mapnik.mapnik_version() >= 600:
28     raise SystemExit('This script requires Mapnik >=0.6.0)')
29
30
31 def render_map(mapfile,map_uri,gpx_file,imgx,imgy):
32
33     with open(gpx_file,'r') as f:
34       data = f.read()
35
36     xml = etree.fromstring(data)
37     gpx = pygpx.GPX()
38     gpx.ReadTree(xml)
39
40     bbox = gpx.bound_box()
41     pprint(bbox)
42     cx=(bbox[0][1]+bbox[1][1])/2
43     cy=(bbox[0][0]+bbox[1][0])/2
44     print cx,cy
45     w=(bbox[1][1]-bbox[0][1])*1.2
46     h=(bbox[1][0]-bbox[0][0])*1.2
47     print w,h
48     bounds = (cx-w/2,cy-h/2,cx+w/2,cy+h/2)
49     print bounds
50
51     m = mapnik.Map(imgx,imgy)
52     mapnik.load_map(m,mapfile)
53
54     m.background = mapnik.Color('rgb(255,255,255)')
55     
56     # ensure the target map projection is mercator
57     m.srs = merc.params()
58
59     bbox = mapnik.Box2d(*bounds)
60
61     pprint(bbox)
62
63     transform = mapnik.ProjTransform(longlat,merc)
64     merc_bbox = transform.forward(bbox)
65     m.zoom_to_box(merc_bbox)
66
67     style = mapnik.Style()
68     rule = mapnik.Rule()
69
70     line_symbolizer = mapnik.LineSymbolizer()
71     line_symbolizer.stroke = mapnik.Color('rgb(125, 125, 0)')
72     rule.symbols.append(line_symbolizer)
73
74     point_symbolizer = mapnik.MarkersSymbolizer()
75     point_symbolizer.allow_overlap = True
76     point_symbolizer.opacity = 0.8 # semi-transparent
77     rule.symbols.append(point_symbolizer)
78
79     style.rules.append(rule)
80     m.append_style('GPS_tracking_points', style)
81
82     layer = mapnik.Layer('GPS_tracking_points')
83     layer.datasource = mapnik.Ogr(file=gpx_file, layer='track_points')
84     layer.styles.append('GPS_tracking_points')
85     m.layers.append(layer)
86
87     im = mapnik.Image(imgx,imgy)
88     mapnik.render(m, im)
89     im.save(map_uri,'png')
90     sys.stdout.write('output image to %s!\n' % map_uri)
91
92
93 def render_all(db,mapfile,imgx,imgy):
94
95     import sqlite3
96     from os.path import dirname    
97
98     conn = sqlite3.connect(db)
99     cur = conn.cursor()
100     updcur = conn.cursor()
101
102     cur.execute ("select id,filename from tracks where preview_name is null")
103     
104     list=cur.fetchall()
105     
106     for rec in list:        
107     
108       id = rec[0]
109       filename = rec[1]
110       preview_name = dirname(filename) + '/' + str(id) + '.png'
111
112       print id,filename,preview_name
113
114       try:      
115         render_map(mapfile,preview_name.encode('utf8'),filename,imgx,imgy)
116         updcur.execute("update tracks set preview_name=? where id=?", (preview_name,id))
117         conn.commit()
118       except:
119         raise
120
121
122 def main():
123
124     parser = OptionParser()
125     parser.add_option("-m", "--map", dest="mapfile",
126       help="use map file", metavar="MAP")
127     parser.add_option("-o", "--output", dest="outfile",
128       help="output image to file", metavar="OUT")
129     parser.add_option("-g", "--gpx", dest="gpxfile",
130       help="track to render", metavar="GPX")
131     parser.add_option("-x", "--x-size", dest="x",
132       help="image width", metavar="X")
133     parser.add_option("-y", "--y-size", dest="y",
134       help="image height", metavar="Y")
135     parser.add_option("-d", "--db", dest="db",
136       help="render all not process files in database", metavar="DB")
137     (options, args) = parser.parse_args()
138
139     if options.mapfile:  
140       mapfile = options.mapfile
141     else:
142       mapfile = "/etc/mapnik-osm-carto-data/veloroad-transparent.xml"
143
144     if options.outfile:  
145       map_uri = options.outfile
146     else:
147       map_uri = "image.png"
148
149     if options.x:  
150       imgx = int(options.x)
151     else:
152       imgx= 400
153     if options.y:  
154       imgy = int(options.y)
155     else:
156       imgy= 400
157
158     if options.db:
159       render_all(options.db,mapfile,imgx,imgy) 
160     else:
161       if options.gpxfile:  
162         gpx_file = options.gpxfile
163         render_map(mapfile,map_uri,gpx_file,imgx,imgy)
164       else:
165         print "No input file"
166         exit(1)
167
168 if __name__ == "__main__":
169
170     main()