diff --git a/backend/app/get_nearest_centreline_node.py b/backend/app/get_nearest_centreline_node.py new file mode 100644 index 0000000..c15bfa7 --- /dev/null +++ b/backend/app/get_nearest_centreline_node.py @@ -0,0 +1,48 @@ +from app.db import getConnection +from json import loads as loadJSON + +SQL = ''' +WITH nearest_centreline AS ( + SELECT + intersection_id, + geom::geography <-> ST_MakePoint(%(longitude)s, %(latitude)s)::geography AS distance + FROM gis_core.intersection_latest + ORDER BY geom <-> ST_SetSRID(ST_MakePoint(%(longitude)s, %(latitude)s), 4326) ASC + LIMIT 1 +) + +SELECT + intersection_id AS centreline_id, + ST_AsGeoJSON(geom) AS geojson, + distance, + ARRAY_AGG(DISTINCT linear_name_full_from) AS street_names +FROM nearest_centreline +JOIN gis_core.intersection_latest AS ci USING (intersection_id) +GROUP BY + intersection_id, + geom, + distance +''' + +def get_nearest_centreline_node(longitude, latitude): + """ + Return the nearest node from the latest city centreline network + + arguments: + longitude (float): longitude of the point to search around + latitude (float): latitude of the point to search around + """ + node = {} + with getConnection() as connection: + with connection.cursor() as cursor: + cursor.execute(SQL, {'longitude': longitude, 'latitude': latitude}) + centreline_id, geojson, distance, street_names = cursor.fetchone() + node = { + 'centreline_id': centreline_id, + 'street_names': street_names, + 'geometry': loadJSON(geojson), + 'distance': distance + } + connection.close() + return node + diff --git a/backend/app/get_node.py b/backend/app/get_node.py index 3d5a892..3c0955f 100644 --- a/backend/app/get_node.py +++ b/backend/app/get_node.py @@ -2,6 +2,7 @@ import json from app.db import getConnection +from app.get_nearest_centreline_node import get_nearest_centreline_node SQL = ''' SELECT @@ -17,7 +18,7 @@ here_nodes.geom; ''' -def get_node(node_id): +def get_node(node_id, conflate_with_centreline=False): node = {} with getConnection() as connection: with connection.cursor() as cursor: @@ -28,5 +29,11 @@ def get_node(node_id): 'street_names': street_names, 'geometry': json.loads(geojson) } + if conflate_with_centreline: + lon = node['geometry']['coordinates'][0] + lat = node['geometry']['coordinates'][1] + node['conflated'] = { + 'centreline': get_nearest_centreline_node(lon, lat) + } connection.close() return node diff --git a/backend/app/routes.py b/backend/app/routes.py index 6962435..374012c 100644 --- a/backend/app/routes.py +++ b/backend/app/routes.py @@ -1,6 +1,6 @@ import json, re from datetime import datetime -from flask import jsonify +from flask import jsonify, request from app import app from app.db import getConnection from app.get_closest_nodes import get_nodes_within @@ -54,12 +54,18 @@ def node(node_id): arguments: node_id (int): identifier of the node in the latest Here map version + optional GET arg ?doConflation will also return the nearest node in the centreline network """ try: node_id = int(node_id) except: return jsonify({'error': "node_id should be an integer"}) - return jsonify(get_node(node_id)) + + doConflation = False + if request.args.get('doConflation') is not None: + doConflation = True + + return jsonify(get_node(node_id, doConflation)) # test URL /link-nodes/30421154/30421153 #shell function - outputs json for use on frontend