Uses Shapely basic linear referencing capabilities to find nearest bus to each stop.
Prerequisites
- Python 3 environment
- JupyterLab
pip install jupyterlab
Installation
pip install -r requirements.txt
Run notebook
jupyter notebook
Uses Shapely basic linear referencing capabilities to find nearest bus to each stop.
Prerequisites
pip install jupyterlab
Installation
pip install -r requirements.txt
Run notebook
jupyter notebook
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#### Map out the route\n", | |
"Waypoints define the route geometry. Stops are stops. Bus positions are the locations of the buses along the route for a given moment in time." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"route: MULTILINESTRING ((1 0, 2 0), (2 0, 3 2), (3 2, 3 3), (3 3, 2 3), (2 3, 0 3), (0 3, 0 2), (0 2, 1 2), (1 2, 1 0))\n" | |
] | |
} | |
], | |
"source": [ | |
"from shapely.geometry import Point, LineString, MultiLineString\n", | |
"\n", | |
"waypoints = [((1,0),(2,0)),((2,0),(3,2)),((3,2),(3,3)),((3,3),(2,3)),((2,3),(0,3)),((0,3),(0,2)),((0,2),(1,2)),((1,2),(1,0))]\n", | |
"stops = [(3,2),(2,3),(1,2)] # 3 stops\n", | |
"bus_positions = [(1,0),(3,3),(1.5,3),(0,2)] # 4 buses\n", | |
"route = MultiLineString(waypoints)\n", | |
"print('route: ', route)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#### Calculate the distances along the route for each stop and bus\n", | |
"Find the closest arriving bus. The closest arriving bus is not necessarily the closest because it could have passed the stop. The linear referencing function we use for projecting distance honors directionality along the route." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"\n", | |
"STOP 1\n", | |
"distance along route: 3.236068\n", | |
"\tbus 1\n", | |
"\t\tdistance along route: 0.000000\n", | |
"\t\tdistance to stop: 3.236068\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 2\n", | |
"\t\tdistance along route: 4.236068\n", | |
"\t\tdistance to stop: -1.000000\n", | |
"\t\tbus is inbound: False\n", | |
"\tbus 3\n", | |
"\t\tdistance along route: 5.736068\n", | |
"\t\tdistance to stop: -2.500000\n", | |
"\t\tbus is inbound: False\n", | |
"\tbus 4\n", | |
"\t\tdistance along route: 8.236068\n", | |
"\t\tdistance to stop: -5.000000\n", | |
"\t\tbus is inbound: False\n", | |
"\tCLOSEST BUS: 1, distance: 3.236068\n", | |
"\n", | |
"STOP 2\n", | |
"distance along route: 5.236068\n", | |
"\tbus 1\n", | |
"\t\tdistance along route: 0.000000\n", | |
"\t\tdistance to stop: 5.236068\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 2\n", | |
"\t\tdistance along route: 4.236068\n", | |
"\t\tdistance to stop: 1.000000\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 3\n", | |
"\t\tdistance along route: 5.736068\n", | |
"\t\tdistance to stop: -0.500000\n", | |
"\t\tbus is inbound: False\n", | |
"\tbus 4\n", | |
"\t\tdistance along route: 8.236068\n", | |
"\t\tdistance to stop: -3.000000\n", | |
"\t\tbus is inbound: False\n", | |
"\tCLOSEST BUS: 2, distance: 1.000000\n", | |
"\n", | |
"STOP 3\n", | |
"distance along route: 9.236068\n", | |
"\tbus 1\n", | |
"\t\tdistance along route: 0.000000\n", | |
"\t\tdistance to stop: 9.236068\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 2\n", | |
"\t\tdistance along route: 4.236068\n", | |
"\t\tdistance to stop: 5.000000\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 3\n", | |
"\t\tdistance along route: 5.736068\n", | |
"\t\tdistance to stop: 3.500000\n", | |
"\t\tbus is inbound: True\n", | |
"\tbus 4\n", | |
"\t\tdistance along route: 8.236068\n", | |
"\t\tdistance to stop: 1.000000\n", | |
"\t\tbus is inbound: True\n", | |
"\tCLOSEST BUS: 4, distance: 1.000000\n" | |
] | |
} | |
], | |
"source": [ | |
"def calc_bus_dist(bus_idx, bus_pos):\n", | |
" bus_point = Point(bus_pos)\n", | |
" bus_lrs = route.project(bus_point)\n", | |
" print('\\tbus %i' % (bus_idx+1))\n", | |
" print('\\t\\tdistance along route: %f' % bus_lrs)\n", | |
" return bus_lrs\n", | |
"\n", | |
"stop_idx = 0\n", | |
"for stop in stops:\n", | |
" print('\\nSTOP %i' % (stop_idx+1))\n", | |
" stop_point = Point(stop)\n", | |
" stop_lrs = route.project(stop_point)\n", | |
" print('distance along route: %f' % stop_lrs)\n", | |
" \n", | |
" bus_idx = 0\n", | |
" stop_bus_distances = []\n", | |
" arriving_buses = []\n", | |
" for bus_pos in bus_positions:\n", | |
" bus_lrs = calc_bus_dist(bus_idx, bus_pos)\n", | |
" stop_bus_dist = stop_lrs - bus_lrs\n", | |
" print('\\t\\tdistance to stop: %f' % stop_bus_dist)\n", | |
" stop_bus_distances.append(stop_bus_dist)\n", | |
" \n", | |
" bus_is_coming = stop_bus_dist > 0\n", | |
" print('\\t\\tbus is inbound: %s' % bus_is_coming)\n", | |
" if bus_is_coming:\n", | |
" arriving_buses.append((bus_idx, stop_bus_dist))\n", | |
" bus_idx = bus_idx+1\n", | |
" \n", | |
" if len(arriving_buses):\n", | |
" closest_bus = min(arriving_buses, key=lambda n: (n[1], -n[0]))\n", | |
" print('\\tCLOSEST BUS: %i, distance: %f' % (closest_bus[0]+1,closest_bus[1]))\n", | |
" \n", | |
" stop_idx = stop_idx+1" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Shapely==1.6.4.post2 |