diff --git a/api/obs/api/routes/exports.py b/api/obs/api/routes/exports.py index 50d6a40..dbf1097 100644 --- a/api/obs/api/routes/exports.py +++ b/api/obs/api/routes/exports.py @@ -14,30 +14,6 @@ from obs.api.app import app, json as json_response from .mapdetails import get_single_arg -@app.get(r"/export/events.json") -async def tiles(req): - x = get_single_arg(req, "x", convert=int) - y = get_single_arg(req, "y", convert=int) - zoom = get_single_arg(req, "zoom", convert=int) - - features = [] - async for event in get_events(req.ctx.db, zoom, x, y): - features.append({ - "type": "Feature", - "geometry": json.loads(event.geometry), - "properties": { - "distance_overtaker": event.distance_overtaker, - "distance_stationary": event.distance_stationary, - "direction": -1 if event.direction_reversed else 1, - "way_id": event.way_id, - "course": event.course, - "speed": event.speed, - "time": event.time, - } - }) - - geojson = {"type": "FeatureCollection", "features": features} - return json_response(geojson) class ExportFormat(str, Enum): SHAPEFILE = "shapefile" @@ -54,12 +30,16 @@ def parse_bounding_box(s): 3857, ) + @contextmanager def shapefile_zip(): import io, shapefile + zip_buffer = io.BytesIO() shp, shx, dbf = (io.BytesIO() for _ in range(3)) - writer = shapefile.Writer(shp=shp, shx=shx, dbf=dbf, shapeType=shapefile.POINT, encoding="utf8") + writer = shapefile.Writer( + shp=shp, shx=shx, dbf=dbf, shapeType=shapefile.POINT, encoding="utf8" + ) yield writer, zip_buffer @@ -73,21 +53,24 @@ def shapefile_zip(): ) import zipfile + zf = zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) - zf.writestr('events.shp', shp.getbuffer()) - zf.writestr('events.shx', shx.getbuffer()) - zf.writestr('events.dbf', dbf.getbuffer()) - zf.writestr('events.prj', PRJ) + zf.writestr("events.shp", shp.getbuffer()) + zf.writestr("events.shx", shx.getbuffer()) + zf.writestr("events.dbf", dbf.getbuffer()) + zf.writestr("events.prj", PRJ) zf.close() + @app.get(r"/export/events") async def export_events(req): - bbox = get_single_arg(req, "bbox", default="-180,-90,180,90", convert=parse_bounding_box) + bbox = get_single_arg( + req, "bbox", default="-180,-90,180,90", convert=parse_bounding_box + ) fmt = get_single_arg(req, "fmt", convert=ExportFormat) events = await req.ctx.db.stream_scalars( - select(OvertakingEvent) - .where(OvertakingEvent.geometry.bool_op("&&")(bbox)) + select(OvertakingEvent).where(OvertakingEvent.geometry.bool_op("&&")(bbox)) ) if fmt == ExportFormat.SHAPEFILE: @@ -108,7 +91,7 @@ async def export_events(req): way_id=event.way_id, course=event.course, speed=event.speed, - #"time"=event.time, + # "time"=event.time, ) return raw(zip_buffer.getbuffer()) @@ -116,19 +99,21 @@ async def export_events(req): elif fmt == ExportFormat.GEOJSON: features = [] async for event in events: - features.append({ - "type": "Feature", - "geometry": json.loads(event.geometry), - "properties": { - "distance_overtaker": event.distance_overtaker, - "distance_stationary": event.distance_stationary, - "direction": -1 if event.direction_reversed else 1, - "way_id": event.way_id, - "course": event.course, - "speed": event.speed, - "time": event.time, + features.append( + { + "type": "Feature", + "geometry": json.loads(event.geometry), + "properties": { + "distance_overtaker": event.distance_overtaker, + "distance_stationary": event.distance_stationary, + "direction": -1 if event.direction_reversed else 1, + "way_id": event.way_id, + "course": event.course, + "speed": event.speed, + "time": event.time, + }, } - }) + ) geojson = {"type": "FeatureCollection", "features": features} return json_response(geojson)