2017-10-20 16:47:53 +02:00
|
|
|
import os
|
|
|
|
|
|
|
|
from django.conf import settings
|
2017-10-24 13:59:42 +02:00
|
|
|
from django.core.exceptions import PermissionDenied
|
2017-10-20 16:21:25 +02:00
|
|
|
from django.http import Http404, HttpResponse, HttpResponseNotModified
|
2017-10-24 13:59:42 +02:00
|
|
|
from django.shortcuts import get_object_or_404
|
2017-10-10 14:39:11 +02:00
|
|
|
from shapely.geometry import box
|
|
|
|
|
2017-10-24 13:59:42 +02:00
|
|
|
from c3nav.mapdata.cache import MapHistory
|
2017-10-20 16:21:25 +02:00
|
|
|
from c3nav.mapdata.models import Level, MapUpdate, Source
|
2017-10-19 17:20:55 +02:00
|
|
|
from c3nav.mapdata.render.svg import SVGRenderer
|
2017-10-10 14:39:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
def tile(request, level, zoom, x, y, format):
|
2017-10-23 19:25:15 +02:00
|
|
|
import cProfile
|
|
|
|
import pstats
|
|
|
|
pr = cProfile.Profile()
|
|
|
|
pr.enable()
|
|
|
|
|
2017-10-10 14:39:11 +02:00
|
|
|
zoom = int(zoom)
|
|
|
|
if not (0 <= zoom <= 10):
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
bounds = Source.max_bounds()
|
|
|
|
|
|
|
|
x, y = int(x), int(y)
|
|
|
|
size = 256/2**zoom
|
|
|
|
minx = size * x
|
2017-10-10 19:31:51 +02:00
|
|
|
miny = size * (-y-1)
|
2017-10-10 14:39:11 +02:00
|
|
|
maxx = minx + size
|
|
|
|
maxy = miny + size
|
|
|
|
|
|
|
|
if not box(bounds[0][1], bounds[0][0], bounds[1][1], bounds[1][0]).intersects(box(minx, miny, maxx, maxy)):
|
|
|
|
raise Http404
|
|
|
|
|
2017-10-19 17:20:55 +02:00
|
|
|
renderer = SVGRenderer(level, miny, minx, maxy, maxx, scale=2**zoom, user=request.user)
|
|
|
|
|
2017-10-23 22:49:45 +02:00
|
|
|
update_cache_key = MapUpdate.current_cache_key()
|
2017-10-20 16:21:25 +02:00
|
|
|
access_cache_key = renderer.access_cache_key
|
|
|
|
etag = update_cache_key+'_'+access_cache_key
|
|
|
|
|
|
|
|
if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
|
|
|
|
if if_none_match == etag:
|
|
|
|
return HttpResponseNotModified()
|
|
|
|
|
2017-10-20 16:47:53 +02:00
|
|
|
f = None
|
|
|
|
if settings.CACHE_TILES:
|
|
|
|
dirname = os.path.sep.join((settings.TILES_ROOT, update_cache_key, level, str(zoom), str(x), str(y)))
|
|
|
|
filename = os.path.sep.join((dirname, access_cache_key+'.'+format))
|
|
|
|
|
|
|
|
try:
|
|
|
|
f = open(filename, 'rb')
|
|
|
|
except FileNotFoundError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
content_type = 'image/svg+xml' if format == 'svg' else 'image/png'
|
|
|
|
|
|
|
|
if not settings.CACHE_TILES or f is None:
|
|
|
|
try:
|
|
|
|
renderer.check_level()
|
|
|
|
except Level.DoesNotExist:
|
|
|
|
raise Http404
|
2017-10-10 14:39:11 +02:00
|
|
|
|
2017-10-20 16:47:53 +02:00
|
|
|
svg = renderer.render()
|
|
|
|
if format == 'svg':
|
|
|
|
data = svg.get_xml()
|
|
|
|
filemode = 'w'
|
|
|
|
elif format == 'png':
|
|
|
|
data = svg.get_png()
|
|
|
|
filemode = 'wb'
|
|
|
|
else:
|
|
|
|
raise ValueError
|
2017-10-19 17:20:55 +02:00
|
|
|
|
2017-10-20 16:47:53 +02:00
|
|
|
if settings.CACHE_TILES:
|
|
|
|
# noinspection PyUnboundLocalVariable
|
|
|
|
os.makedirs(dirname, exist_ok=True)
|
|
|
|
# noinspection PyUnboundLocalVariable
|
|
|
|
with open(filename, filemode) as f:
|
|
|
|
f.write(data)
|
2017-10-10 14:39:11 +02:00
|
|
|
else:
|
2017-10-20 16:47:53 +02:00
|
|
|
data = f.read()
|
2017-10-10 14:39:11 +02:00
|
|
|
|
2017-10-23 19:25:15 +02:00
|
|
|
pr.disable()
|
|
|
|
s = open('/tmp/profiled', 'w')
|
|
|
|
sortby = 'cumulative'
|
|
|
|
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
|
|
|
|
ps.print_stats()
|
|
|
|
|
2017-10-20 16:47:53 +02:00
|
|
|
response = HttpResponse(data, content_type)
|
2017-10-20 16:21:25 +02:00
|
|
|
response['ETag'] = etag
|
|
|
|
response['Cache-Control'] = 'no-cache'
|
|
|
|
|
2017-10-10 14:39:11 +02:00
|
|
|
return response
|
2017-10-24 13:59:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
def history(request, level, mode, format):
|
|
|
|
if not request.user.is_superuser:
|
|
|
|
raise PermissionDenied
|
|
|
|
level = get_object_or_404(Level, pk=level)
|
|
|
|
|
|
|
|
if mode == 'render' and level.on_top_of_id is None:
|
|
|
|
raise Http404
|
|
|
|
|
|
|
|
history = MapHistory.open(os.path.join(settings.CACHE_ROOT, 'level_%s_%d' % (mode, level.pk)))
|
|
|
|
if format == 'png':
|
|
|
|
response = HttpResponse(content_type='image/png')
|
|
|
|
history.to_image().save(response, format='PNG')
|
|
|
|
elif format == 'data':
|
|
|
|
response = HttpResponse(content_type='application/octet-stream')
|
|
|
|
history.write(response)
|
|
|
|
else:
|
|
|
|
raise ValueError
|
|
|
|
return response
|