a4deaac7c7d996ddc8e15f8aea84c850c04f0fbb
[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     xml = etree.parse(gpx_file)
34     gpx = pygpx.GPX()
35     gpx.ReadTree(xml)
36
37     bbox = gpx.bound_box()
38     pprint(bbox)
39     cx=(bbox[0][1]+bbox[1][1])/2
40     cy=(bbox[0][0]+bbox[1][0])/2
41     print cx,cy
42     w=(bbox[1][1]-bbox[0][1])*1.2
43     h=(bbox[1][0]-bbox[0][0])*1.2
44     print w,h
45     bounds = (cx-w/2,cy-h/2,cx+w/2,cy+h/2)
46     print bounds
47
48     m = mapnik.Map(imgx,imgy)
49     mapnik.load_map(m,mapfile)
50
51     m.background = mapnik.Color('rgb(255,255,255)')
52     
53     # ensure the target map projection is mercator
54     m.srs = merc.params()
55
56     bbox = mapnik.Box2d(*bounds)
57
58     pprint(bbox)
59
60     transform = mapnik.ProjTransform(longlat,merc)
61     merc_bbox = transform.forward(bbox)
62     m.zoom_to_box(merc_bbox)
63
64     style = mapnik.Style()
65     rule = mapnik.Rule()
66
67     point_symbolizer = mapnik.MarkersSymbolizer()
68     point_symbolizer.allow_overlap = True
69     point_symbolizer.opacity = 0.8 # semi-transparent
70     rule.symbols.append(point_symbolizer)
71
72     style.rules.append(rule)
73     m.append_style('GPS_tracking_points', style)
74
75     layer = mapnik.Layer('GPS_tracking_points')
76     layer.datasource = mapnik.Ogr(file=gpx_file, layer='track_points')
77     layer.styles.append('GPS_tracking_points')
78     m.layers.append(layer)
79
80     im = mapnik.Image(imgx,imgy)
81     mapnik.render(m, im)
82     im.save(map_uri,'png')
83     sys.stdout.write('output image to %s!\n' % map_uri)
84
85
86 def render_all(db,mapfile,imgx,imgy):
87
88     import sqlite3
89     from os.path import dirname    
90
91     conn = sqlite3.connect(db)
92     cur = conn.cursor()
93     updcur = conn.cursor()
94
95     cur.execute ("select id,filename from tracks where preview_name is null")
96     
97     list=cur.fetchall()
98     
99     for rec in list:        
100     
101       id = rec[0]
102       filename = rec[1]
103       preview_name = dirname(filename) + '/' + str(id) + '.png'
104
105       print id,filename,preview_name
106
107       try:      
108         render_map(mapfile,preview_name.encode('utf8'),filename,imgx,imgy)
109         updcur.execute("update tracks set preview_name=? where id=?", (preview_name,id))
110         conn.commit()
111       except:
112         raise
113
114
115 def main():
116
117     parser = OptionParser()
118     parser.add_option("-m", "--map", dest="mapfile",
119       help="use map file", metavar="MAP")
120     parser.add_option("-o", "--output", dest="outfile",
121       help="output image to file", metavar="OUT")
122     parser.add_option("-g", "--gpx", dest="gpxfile",
123       help="track to render", metavar="GPX")
124     parser.add_option("-x", "--x-size", dest="x",
125       help="image width", metavar="X")
126     parser.add_option("-y", "--y-size", dest="y",
127       help="image height", metavar="Y")
128     parser.add_option("-d", "--db", dest="db",
129       help="render all not process files in database", metavar="DB")
130     (options, args) = parser.parse_args()
131
132     if options.mapfile:  
133       mapfile = options.mapfile
134     else:
135       mapfile = "/etc/mapnik-osm-carto-data/veloroad-transparent.xml"
136
137     if options.outfile:  
138       map_uri = options.outfile
139     else:
140       map_uri = "image.png"
141
142     if options.x:  
143       imgx = int(options.x)
144     else:
145       imgx= 400
146     if options.y:  
147       imgy = int(options.y)
148     else:
149       imgy= 400
150
151     if options.db:
152       render_all(options.db,mapfile,imgx,imgy) 
153     else:
154       if options.gpxfile:  
155         gpx_file = options.gpxfile
156         render_map(mapfile,map_uri,gpx_file,imgx,imgy)
157       else:
158         print "No input file"
159         exit(1)
160
161 if __name__ == "__main__":
162
163     main()