6

How do I fund the nearest LINESTRING near a point?

First I have a list of LINESTRING and point value. How do I have the nearest LINESTRING to the POINT (5.41 3.9) and maybee the distance?

from shapely.geometry import Point, LineString

line_string = [LINESTRING (-1.15.12 9.9, -1.15.13 9.93), LINESTRING (-2.15.12 8.9, -2.15.13 8.93)]
point = POINT (5.41 3.9)

#distance 
line_string [0].distance(point)

So far I think I got the distance value by doing line_string [0].distance(point) for the first LINESTRING so far but I just want to make sure I am going about it the right way.

helpme
  • 163
  • 3
  • 9

2 Answers2

4

Here's a function that takes a list of LineStrings and a point , and returns the LineString closest to the point, as well as the distance.

from shapely.geometry import Point, LineString

# set up lines and points
line_string_list = [LineString([(-1,1),(1,.5)]), LineString([(-1,-.5),(.5,-1)]), LineString([(-1,0),(.5,-.5)])]
point = Point(.25,-.75)

def closest_line(lines, point):
    # get distances
    distance_list = [line.distance(point) for line in line_string_list]
    shortest_distance = min(distance_list) # find the line closest to the point
    return(lines[distance_list.index(shortest_distance)], # return the closest line
           shortest_distance) # return the distance to that line
    
print(closest_line(line_string_list, point))
Lone Survivr
  • 372
  • 1
  • 9
3
  • your sample geometry is invalid for line strings, have modified
  • it's simple to achieve with sjoin_nearest()
import geopandas as gpd
import shapely.wkt
import shapely.geometry

line_string = ["LINESTRING (-1.15.12 9.9, -1.15.13 9.93)", "LINESTRING (-2.15.12 8.9, -2.15.13 8.93)"]
# fix invalid wkt string...
line_string = ["LINESTRING (-1.15 9.9, -1.15 9.93)", "LINESTRING (-2.15 8.9, -2.15 8.93)"]
point = "POINT (5.41 3.9)"

gdf_p = gpd.GeoDataFrame(geometry=[shapely.wkt.loads(point)])
gdf_l = gpd.GeoDataFrame(geometry=pd.Series(line_string).apply(shapely.wkt.loads))

df_n = gpd.sjoin_nearest(gdf_p, gdf_l).merge(gdf_l, left_on="index_right", right_index=True)

df_n["distance"] = df_n.apply(lambda r: r["geometry_x"].distance(r["geometry_y"]), axis=1)

df_n

geometry_x index_right geometry_y distance
0 POINT (5.41 3.9) 0 LINESTRING (-1.15 9.9, -1.15 9.93) 8.89008

distance in meters

  • use a CRS that is in meters. UTM has it's limitations if all points are not in same zone
import geopandas as gpd
import shapely.wkt
import shapely.geometry

line_string = ["LINESTRING (-1.15.12 9.9, -1.15.13 9.93)", "LINESTRING (-2.15.12 8.9, -2.15.13 8.93)"]
# fix invalid wkt string...
line_string = ["LINESTRING (-1.15 9.9, -1.15 9.93)", "LINESTRING (-2.15 8.9, -2.15 8.93)"]
point = "POINT (5.41 3.9)"

gdf_p = gpd.GeoDataFrame(geometry=[shapely.wkt.loads(point)], crs="epsg:4326")
gdf_l = gpd.GeoDataFrame(geometry=pd.Series(line_string).apply(shapely.wkt.loads), crs="epsg:4326")
gdf_p = gdf_p.to_crs(gdf_p.estimate_utm_crs())
gdf_l = gdf_l.to_crs(gdf_p.crs)


df_n = gpd.sjoin_nearest(gdf_p, gdf_l).merge(gdf_l, left_on="index_right", right_index=True)

df_n["distance"] = df_n.apply(lambda r: r["geometry_x"].distance(r["geometry_y"]), axis=1)

df_n
Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
  • 1
    thank you so much. I am assuming index_right tells us its in the 0 position of the list. not sure if you know this but is there a way to find the distance between the POINT and LINESTRING? – helpme Jan 07 '22 at 21:44
  • 2
    in this case yes. `index_right` is the index of the geodataframe containing line strings, given way this dataframe was created it will correspond to the list index. The reason I did pandas `merge()` was to get the geometry that corresponds to the index on the same row – Rob Raymond Jan 07 '22 at 22:08
  • 1
    very smart. But how would you find the distance between the POINT and LINESTRING if possible? – helpme Jan 07 '22 at 22:11
  • 2
    updated answer to do distance as well – Rob Raymond Jan 07 '22 at 22:15
  • thank you is there a way to turn the distance into meters? – helpme Jan 14 '22 at 18:05
  • updated - beware this has it's limitations. read about UTM CRS – Rob Raymond Jan 14 '22 at 23:17