diff --git a/api/obs/api/routes/exports.py b/api/obs/api/routes/exports.py index 4fa1ce3..c28154c 100644 --- a/api/obs/api/routes/exports.py +++ b/api/obs/api/routes/exports.py @@ -4,6 +4,7 @@ from contextlib import contextmanager import zipfile import io import re +import math from sqlite3 import connect import shapefile @@ -15,6 +16,9 @@ from sanic.exceptions import InvalidUsage from obs.api.app import api, json as json_response from obs.api.utils import use_request_semaphore +import logging +log = logging.getLogger(__name__) + class ExportFormat(str, Enum): SHAPEFILE = "shapefile" @@ -64,13 +68,13 @@ def shapefile_zip(shape_type=shapefile.POINT, basename="events"): async def export_events(req): async with use_request_semaphore(req, "export_semaphore", timeout=30): bbox = req.ctx.get_single_arg( - "bbox", default="-180,-90,180,90", convert=parse_bounding_box + "bbox", default="-180,-90,180,90" ) fmt = req.ctx.get_single_arg("fmt", convert=ExportFormat) - events = await req.ctx.db.stream_scalars( - select(OvertakingEvent).where( - OvertakingEvent.geometry.bool_op("&&")(func.ST_Transform(bbox, 3857)) + events = await req.ctx.db.stream( + text( + f"select ST_AsGeoJSON(ST_Transform(geometry,4326)) AS geometry,distance_overtaker,distance_stationary,way_id,direction,speed,time_stamp,course,zone from layer_obs_events(ST_Transform(ST_MakeEnvelope({bbox},4326),3857),19,NULL,'1900-01-01'::timestamp,'2100-01-01'::timestamp) " ) ) @@ -82,16 +86,19 @@ async def export_events(req): writer.field("direction", "N", decimal=0) writer.field("course", "N", decimal=4) writer.field("speed", "N", decimal=4) + writer.field("zone", "C") async for event in events: - writer.point(event.longitude, event.latitude) + coords = json.loads(event.geometry)['coordinates'] + writer.point(*coords) writer.record( distance_overtaker=event.distance_overtaker, distance_stationary=event.distance_stationary, - direction=-1 if event.direction_reversed else 1, + direction=event.direction, way_id=event.way_id, course=event.course, speed=event.speed, + zone=event.zone # "time"=event.time, ) @@ -100,19 +107,22 @@ async def export_events(req): if fmt == ExportFormat.GEOJSON: features = [] async for event in events: + geom = json.loads(event.geometry) features.append( { "type": "Feature", - "geometry": json.loads(event.geometry), + "geometry": geom, "properties": { - "distance_overtaker": event.distance_overtaker, - "distance_stationary": event.distance_stationary, - "direction": -1 if event.direction_reversed else 1, + "distance_overtaker": event.distance_overtaker if event.distance_overtaker is not None and not math.isnan(event.distance_overtaker) else None, + "distance_stationary": event.distance_stationary if event.distance_stationary is not None and not math.isnan(event.distance_stationary) else None, + "direction": event.direction if event.direction is not None and not math.isnan(event.direction) else None, "way_id": event.way_id, - "course": event.course, - "speed": event.speed, - "time": event.time, + "course": event.course if event.course is not None and not math.isnan(event.course) else None, + "speed": event.speed if event.speed is not None and not math.isnan(event.speed) else None, + "time": event.time_stamp, + "zone": event.zone }, + } ) diff --git a/tile-generator/layers/obs_events/layer.sql b/tile-generator/layers/obs_events/layer.sql index 99e81e2..85effdb 100644 --- a/tile-generator/layers/obs_events/layer.sql +++ b/tile-generator/layers/obs_events/layer.sql @@ -1,5 +1,7 @@ +DROP FUNCTION IF EXISTS layer_obs_events; + CREATE OR REPLACE FUNCTION layer_obs_events(bbox geometry, zoom_level int, user_id integer, min_time timestamp, max_time timestamp) -RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, distance_stationary float, direction int, course float, speed float, zone zone_type, way_id bigint) AS $$ +RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, distance_stationary float, direction int, course float, speed float, time_stamp timestamp, zone zone_type, way_id bigint) AS $$ SELECT overtaking_event.id::bigint as event_id, @@ -9,6 +11,7 @@ RETURNS TABLE(event_id bigint, geometry geometry, distance_overtaker float, dist (case when direction_reversed then -1 else 1 end)::int as direction, course, speed, + time as time_stamp, CASE WHEN road.zone IS NULL THEN 'urban' else road.zone END as zone, overtaking_event.way_id::bigint as way_id FROM overtaking_event diff --git a/tile-generator/layers/obs_events/obs_events.yaml b/tile-generator/layers/obs_events/obs_events.yaml index 9cfb2f2..4c43dcb 100644 --- a/tile-generator/layers/obs_events/obs_events.yaml +++ b/tile-generator/layers/obs_events/obs_events.yaml @@ -16,6 +16,8 @@ layer: Direction of travel, as reported by GPS, in degree from North. speed: | Speed of travel, as reported by GPS, in meters per second (?). + time_stamp: | + the time of the overtaking zone: | rural or urban defaults: