Source code for measprocess.geospatial

import overpy
import geopandas as gpd
from shapely.geometry import LineString, Polygon
from scipy.spatial.distance import cdist
import numpy as np
import warnings
import time

[docs]def make_overpy_request(request_body, retries): for _ in range(retries): try: api = overpy.Overpass() result = api.query( request_body ) except (overpy.exception.OverpassTooManyRequests, overpy.exception.OverpassGatewayTimeout): warnings.warn("Overpass Too Many Requests --- Retry in 5 seconds") time.sleep(5) else: return result
[docs]def get_geoseries_streets(measurement_coords, retries=5): ''' Obtain the street shapes in the area spanned by the measurement_coords. :param measurement_coords: A geopandas geoseries of Points(lon, lat) representing the measurement positions in a EPSG:4326 projection :return: A geopandas geoseries consiting of LineStrings representing the streets in EPSG:4326 ''' if measurement_coords.crs != "EPSG:4326": raise ValueError("Make sure to pass data with EPSG:4326 projection") long, lat = measurement_coords.x, measurement_coords.y bounds = (lat.min(), long.min(), lat.max(), long.max()) result = make_overpy_request( f""" [out:json][timeout:25]; ( way['highway']['highway'!='footway']['highway'!='platform']['highway'!='steps']{bounds}; ); out body; >; out skel qt; """, retries ) street_series = gpd.GeoSeries( LineString( ((node.lon, node.lat) for node in way.nodes) ) for way in result.ways ).set_crs("EPSG:4326") return street_series
[docs]def get_geoseries_blockages(measurement_coords, retries=5): ''' Obtain the blockage shapes in the area spanned by the measurement_coords. :param measurement_coords: A geopandas geoseries of Points(lon, lat) representing the measurement positions in a EPSG:4326 projection :return: A geopandas geoseries consiting of Polygons representing the blockages in EPSG:4326 ''' if measurement_coords.crs != "EPSG:4326": raise ValueError("Make sure to pass data with EPSG:4326 projection") long, lat = measurement_coords.x, measurement_coords.y bounds = (lat.min(), long.min(), lat.max(), long.max()) result = make_overpy_request( f""" [out:json][timeout:25]; ( way['building']{bounds}; relation["building"]{bounds}; ); out body; >; out skel qt; """, retries ) blockages = gpd.GeoSeries( Polygon( ((node.lon, node.lat) for node in way.nodes) ) for way in result.ways ).set_crs("EPSG:4326") return blockages
[docs]def project_onto_streets(point_series, street_series, epsg="EPSG:31287", plot=False): ''' Todo: Muss noch angepasst werden! ''' if point_series.crs != epsg or street_series.crs != epsg: raise ValueError("GeoSeries does not match value set by epsg argument (Default EPSG:31287)") projected = [] for point in point_series: street_ind = street_series.distance(point).argmin() projected.append( street_series.loc[street_ind].interpolate(street_series.loc[street_ind].project(point)) ) projected = gpd.GeoSeries(projected) projected = projected.set_crs(epsg) deviation_projection = projected.distance(point_series) if plot: plt.figure() plt.title("Deviation Histogram") deviation_projection.plot.hist(bins=50) plt.show() fig, (ax1, ax2) = plt.subplots(1,2, figsize=(20, 10)) ax1.set_title("Raw Measurements") ax2.set_title("After Projection") ax1.scatter(point_series.x, point_series.y, label="Point Series") clb = ax2.scatter(projected.x, projected.y, c=deviation_projection, label="Projected Series") for street in street_series: ax1.plot(*street.xy, color="black") ax2.plot(*street.xy, color="black") bar = fig.colorbar(clb) bar.ax.set_title('Deviation [Meters]') ax1.legend() ax2.legend() plt.show() return projected, deviation_projection