I'm trying to model a French city (Annecy) with osmnx
to test and develop shortest path algorithms. However, to have correct distances I must apply ox.project_graph
but I'm then unable to search for the nearest node of any GPS point within the city's boundaries...
Is there a way to project a single coordinates?
I think the problem comes from the coordinates as in the raw graph, the x and y coordinates are exactly the latitude and longitude whereas in the corrected graph, the values are completely different but I don't see any ways to change the x-y coordinates of my points individually...
Here is the code with the raw graph and a shortest point between 2 points:
import osmnx as ox
import networkx as nx
graphe_ville = ox.graph.graph_from_bbox(45.949160, 45.868544, 6.176136, 6.071052, network_type='drive', simplify=True, truncate_by_edge=False, clean_periphery =True)
graphe_ville = ox.add_edge_speeds(graphe_ville)
graphe_ville = ox.add_edge_travel_times(graphe_ville)
x_start, y_start = (6.148903, 45.909408)
x_arrival, y_arrival = (6.127705, 45.905936)
Start = ox.distance.nearest_nodes(graphe_ville, x_start, y_start)
Arrival = ox.distance.nearest_nodes(graphe_ville, x_arrival, y_arrival)
path = nx.dijkstra_path(graphe_ville,Start,Arrival)
fig, ax = ox.plot_graph_route(graphe_ville, path, route_linewidth=4,node_size=1, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
Here is the code I have to apply to get correct distance :
import osmnx as ox
import networkx as nx
city_graph = ox.graph.graph_from_bbox(45.949160, 45.868544, 6.176136, 6.071052, network_type='drive', simplify=True, truncate_by_edge=False, clean_periphery =True)
city_graph = ox.project_graph(city_graph) # Allows to get correct distance
city_graph = ox.consolidate_intersections(city_graph, rebuild_graph=True, tolerance=15, dead_ends=True) # Simplify the nodes (eg. for traffic circles)
city_graph = ox.add_edge_speeds(city_graph)
city_graph = ox.add_edge_travel_times(city_graph)
fig, ax = ox.plot_graph(city_graph, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
and if I try to add these lines to the previous code to have the shortest path between the same 2 points
x_start, y_start = (6.148903, 45.909408)
x_arrival, y_arrival = (6.127705, 45.905936)
Start = ox.distance.nearest_nodes(graphe_ville, x_start, y_start)
Arrival = ox.distance.nearest_nodes(graphe_ville, x_arrival, y_arrival)
path = nx.dijkstra_path(graphe_ville,Start,Arrival)
fig, ax = ox.plot_graph_route(graphe_ville, path, route_linewidth=4,node_size=1, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
Looking at this answer from @gboeing I've code this function that allows to return the closest node of a point given with its longitude and latitude
import osmnx as ox
import geopandas as gpd
from shapely.geometry import Point
def closest_node(P, G):
'''
P is list of two elements that represents the point : the longitude and the latitude (ie. P = [longitude, latitude])
G is the projected OSMnx graph you are working with
returns the ID of the closest node
'''
longitude, latitude = P
shapely_coordinates = gpd.GeoSeries(Point(longitude, latitude), crs='epsg:4326') # epsg:4326 is the Geodetic coordinate system for World which is used by the GPS
projected_point = shapely_coordinates.to_crs(G.graph['crs'])
return ox.distance.nearest_nodes(G, projected_point.x, projected_point.y)[0]