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