Avoiding construction sites dynamically¶
Note: All notebooks need the environment dependencies as well as an openrouteservice API key to run
In this example, we'd like to showcase how to use the directions API and to avoid a number of construction sites while routing.
The challenge here is to prepare the data appropriately and construct a reasonable GET request.
import folium
import pyproj
import requests
from openrouteservice import client
from shapely import geometry
from shapely.geometry import Point, LineString, Polygon, MultiPolygon
Rostock is beautiful, but, as in most other pan-European cities, there are a lot of construction sites. Wouldn't it be great if we could plan our trip avoiding these sites and consequently save lots of time!?
Construction sites in Rostock¶
We take the open data from the Rostock authorities. It's hard (to impossible) to find construction site polygons, so these are points, and we need to buffer them to a polygon to be able to avoid them when they cross a street.
For the investigatory in you: yes, no CRS is specified on the link (shame on you, Rostock!). It's fair enough to assume it comes in WGS84 lat/long though (my reasoning: they show Leaflet maps plus GeoJSON is generally a web exchange format, and many web clients (Google Maps, Leaflet) won't take CRS other than WGS84). Since degrees are not the most convenient unit to work with, let's first define a function which does the buffering job with UTM32N projected coordinates:
url = 'https://geo.sv.rostock.de/download/opendata/baustellen/baustellen.json'
def create_buffer_polygon(point_in, resolution=10, radius=10):
convert = pyproj.Transformer.from_crs("epsg:4326", 'epsg:32632') # WGS84 to UTM32N
convert_back = pyproj.Transformer.from_crs('epsg:32632', "epsg:4326") # UTM32N to WGS84
point_in_proj = convert.transform(*point_in)
point_buffer_proj = Point(point_in_proj).buffer(radius, resolution=resolution) # 10 m buffer
# Iterate over all points in buffer and build polygon
poly_wgs = []
for point in point_buffer_proj.exterior.coords:
poly_wgs.append(convert_back.transform(*point)) # Transform back to WGS84
return poly_wgs
# Set up the fundamentals
api_key = 'your_key' # Individual api key
ors = client.Client(key=api_key) # Create client with api key
rostock_json = requests.get(url).json() # Get data as JSON
map_params = {'tiles': 'Stamen Toner',
'location': ([54.13207, 12.101612]),
'zoom_start': 12}
map1 = folium.Map(**map_params)
# Populate a construction site buffer polygon list
sites_poly = []
for site_data in rostock_json['features']:
site_coords = site_data['geometry']['coordinates']
folium.features.Marker(list(reversed(site_coords)),
popup='Construction point<br>{0}'.format(site_coords)).add_to(map1)
# Create buffer polygons around construction sites with 10 m radius and low resolution
site_poly_coords = create_buffer_polygon(site_coords,
resolution=2, # low resolution to keep polygons lean
radius=10)
sites_poly.append(site_poly_coords)
site_poly_coords = [(y, x) for x, y in site_poly_coords] # Reverse coords for folium/Leaflet
folium.vector_layers.Polygon(locations=site_poly_coords,
color='#ffd699',
fill_color='#ffd699',
fill_opacity=0.2,
weight=3).add_to(map1)
map1