2

I have a list of thousands coordinates (lat, long). I want to find nearest road and distance to it for each point. I tried to use OSMNX: loaded all roads from osmnx and calculate distance from each point to each road (code is below). But it takes a very long time to compute.

roads = gdf[["geometry", "u", "v","ref","name","highway","lanes"]].values.tolist()

# calculate and attach distance
roads_with_distances = [(road, Point(tuple(reversed((59.961517, 30.340880)))).distance(road[0])) for road in roads] #ox

# sort by distance
roads_with_distances = sorted(roads_with_distances, key=lambda x: x[1])
# Select closest road
closest_road = roads_with_distances[0]
# Check whether you are actually "on" the road
if round(closest_road[1],4) < 0.0001: print('Hit the road, Jack!')

Example of my data (coord column):

enter image description here

Example of OSMNX road data (road==Linestring):

enter image description here

Is there a efficient way to find nearest road and ditance (in metres)? I am looking for a Python method.

Dmitry
  • 35
  • 4
  • please add some random/sample data with a working minimum example. Probably a Tree will do the job just fine https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.BallTree.html it support haversine which is what you want – Willem Hendriks Oct 29 '21 at 10:07
  • @WillemHendriks I added more info to a post. The above code gives me a nearest road info, for example, name and distance. But I don't need even a road name, just a distance. – Dmitry Oct 29 '21 at 10:19
  • Can you add test data as code- generated and/or samples? – Willem Hendriks Oct 29 '21 at 10:57

1 Answers1

2

Yes you can do this directly (and fast) with OSMnx. You didn't provide a complete reproducible code example but it appears that currently you're just running a big for-loop with each iteration calling the shapely geometry's distance method. This will be very slow.

Instead, take a look at the OSMnx documentation and usage examples. OSMnx's nearest_edges function can accomplish what you're aiming for: the nearest street and the distance to it in meters.

import osmnx as ox

# get a street network and randomly sample 10,000 points
G = ox.graph_from_place('Piedmont, CA, USA', network_type='drive')
G_proj = ox.project_graph(G)
points = ox.utils_geo.sample_points(ox.get_undirected(G_proj), 10000)

%time ne1 = ox.nearest_edges(G_proj, X=points.x, Y=points.y, return_dist=True)
# wall time: 2.91 s

%time ne2 = ox.nearest_edges(G_proj, X=points.x, Y=points.y, interpolate=10, return_dist=True)
# wall time: 302 ms

The first method uses an r-tree to find precise nearest edges. The second method uses a k-d tree to find approximate (via 10-meter point interpolation) nearest edges. The second method is ~10x faster than the first method. Note that you don't have to project your graph: if it's unprojected, the nearest_edges function will automatically use a BallTree and haversine for nearest edge solving. See also this answer.

gboeing
  • 5,691
  • 2
  • 15
  • 41