В Ubuntu 22.04 сломали проекции в Mapnik, приходится использовать альтернативный...
[pyrungps.git] / pyrungps / render_tiles.py
1 #!/usr/bin/env python
2 # coding: UTF-8
3
4 import sqlite3
5 import math
6 from pprint import pprint
7
8 def queue_render(db,filename,forced_max_zoom=None):
9
10   conn = sqlite3.connect(db)
11   conn.text_factory = str
12   cur = conn.cursor()
13         
14   cur.execute("select minlat,minlon,maxlat,maxlon from tracks where filename=?" , (filename,))
15   minlat,minlon,maxlat,maxlon=cur.fetchone()
16   queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom)
17
18 def deg2num(lat_deg, lon_deg, zoom):
19   lat_rad = math.radians(lat_deg)
20   n = 2.0 ** zoom
21   xtile = int((lon_deg + 180.0) / 360.0 * n)
22   ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
23   return (xtile, ytile)
24             
25 def queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom=None):
26
27   conn = sqlite3.connect(db)
28   
29   # определяем примерный стартовый зум
30
31   minzoom=8
32
33   if forced_max_zoom:
34     maxzoom=forced_max_zoom
35   else:
36     maxzoom=minzoom
37     while True:
38       minx,miny=deg2num(minlat,minlon,maxzoom)
39       maxx,maxy=deg2num(maxlat,maxlon,maxzoom)
40       
41       print(maxzoom,':',minx,'-',maxx,'/',miny,'-',maxy)
42       if (maxx-minx>16) or (maxy-miny>12) or (maxzoom==16):
43         break
44       else:
45         maxzoom=maxzoom+1   
46   
47   if maxzoom<minzoom:
48     minzoom=maxzoom
49   
50   ins = conn.cursor()
51   print(minlat,minlon,maxlat,maxlon,minzoom,maxzoom)
52   ins.execute('insert into render_queue(minlat,maxlat,minlon,maxlon,minzoom,maxzoom) values(?,?,?,?,?,?)',(minlat,maxlat,minlon,maxlon,minzoom,maxzoom))
53
54   conn.commit()        
55
56 def process_queue(db,map,force=False,backend="renderd"):
57
58   from os import system
59
60   conn = sqlite3.connect(db)
61   cur = conn.cursor()
62   cur.execute('select id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom from render_queue')
63   list=cur.fetchall()
64
65   for rec in list:
66   
67     id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom=rec
68     
69     if backend == "tirex" or backend == "default":    
70
71       command = 'map='+map+ \
72         ' z='+str(minzoom)+'-'+str(maxzoom)+ \
73         ' lat='+str(minlat)+','+str(maxlat)+ \
74         ' lon='+str(minlon)+','+str(maxlon)
75
76       if force:
77         command = 'tirex-batch -n 0 --prio=50 '+command
78       else:
79         command = 'tirex-batch -n 0 --prio=50 '+command+' -f not-exists'  
80
81       print(command  )
82       
83       if system(command)==0:
84         dcur=conn.cursor()
85         dcur.execute('delete from render_queue where id=?',(id,))
86         conn.commit()
87
88     elif backend == "renderd":
89     
90       print(minlat,minlon,maxlat,maxlon)
91     
92       for zoom in range(minzoom,maxzoom+1):
93         minx,miny=deg2num(minlat,minlon,zoom)
94         maxx,maxy=deg2num(maxlat,maxlon,zoom)
95
96         if minx>maxx:
97           tx=minx
98           maxx=minx
99           minx=tx
100
101         if miny>maxy:
102           ty=miny
103           maxy=miny
104           miny=ty
105
106         print(zoom,minx,miny,maxx,maxy)
107
108         maps = map.split(',')
109         
110         for map_name in maps:
111
112           command = 'render_list -a -m '+map+ \
113                     ' -z '+str(zoom)+' -Z '+str(zoom)+ \
114                     ' -x '+str(minx)+' -X '+str(maxx)+ \
115                     ' -y '+str(miny)+' -Y '+str(maxy)
116           if force:
117             command = command+ ' --force'
118     
119           print(command  )
120       
121           if not system(command) == 0:
122             return
123
124       dcur=conn.cursor()
125       dcur.execute('delete from render_queue where id=?',(id,))
126       conn.commit()
127
128 def main():
129
130   from optparse import OptionParser
131   
132   parser = OptionParser()
133   parser.add_option("-d", "--data", dest="directory",
134     help="Data directory", metavar="DIR")
135   parser.add_option("-m", "--map", dest="map",
136     help="Map name", metavar="MAP")
137   parser.add_option("-z", "--zoom", dest="zoom",
138     help="Maximal zoom (forced), used with coordinates pairs (minlat minlon maxlat maxlon) or filename in arguments", metavar="MAP")
139   parser.add_option("-f", "--force", dest="force", 
140     help="Force tile regeneration (on/off), default off")
141   parser.add_option("-r", "--renderer", dest="renderer", 
142     help="Rendering backend: tirex or renderd")
143   (options, args) = parser.parse_args()  
144
145   db=options.directory+'/gpx.db'
146   map=options.map  
147   zoom=options.zoom
148   if not zoom:
149     zoom=12
150   force=(options.force=='on')
151
152   if options.renderer:
153     renderer=options.renderer
154   else:
155     print("Using default rendering backend...")
156     renderer="default"
157
158   if len(args)==1:
159     filename,=args
160     print("Rendering file: "+filename+"\n")
161     queue_render(db,filename)
162   elif len(args)==4:
163     minlat,minlon,maxlat,maxlon=args
164     print("Rendering region "+minlat+'..'+maxlat+' / '+minlon+'..'+maxlon+"\n")
165     queue_tiles(db,float(minlat),float(minlon),float(maxlat),float(maxlon),int(zoom))
166
167   if map:
168     print("Processing map(s) "+map+"\n")
169     process_queue(db,map,force,renderer)
170   
171 if __name__ == "__main__":
172
173   main()          
174