1

I have a main polygon of polygons that have areas mapped out on a map

enter image description here

and a bunch of points such as sample below

    NAME   lt         ln
      1 12.9336806  77.6122669
      2 12.974768   77.767745
      3 12.9314583  77.6299858
      4 12.943219   77.6213569
      5 12.95120049 77.56729126
      6 13.0292902  77.54489136
      7 13.00134159 77.60814171
      8 13.0347 77.653
      9 12.88734436 77.57913454

some of these would be inside and some of these would be outside the polygon I need to find the distance to boundary for each point in meters Here's the code I have worked on so far

import io
import pandas as pd
import geopandas as gpd
import shapely



df = pd.read_csv(io.StringIO("""NAME   value   geometry  
BNG   10000    POLYGON ((77.544620205933 13.080009969947, 77.54687842279 13.081767336162, 77.543973488861 13.09731788964, 77.563642026 13.099993855304, 77.56128297238899 13.109043490523, 77.574909239345 13.109806495724, 77.57990367382099 13.111021266518, 77.58119926142 13.107866932403, 77.583009833151 13.105214129905, 77.593084532791 13.105888221511, 77.599030888611 13.105889067656, 77.62177194696 13.1176238629, 77.63936316400201 13.104531490855, 77.653018935256 13.091558385666, 77.656070270591 13.07934476693, 77.65723333077899 13.067046935098, 77.676682673508 13.056350290571, 77.68731712299 13.048701049623, 77.724215763145 13.060700785769, 77.76648309927501 13.04163756999, 77.764118477398 13.023743607526, 77.768440059357 13.005858466046, 77.772117911153 12.982577525022, 77.76335031312099 12.945178985189, 77.75820798369701 12.934327952869, 77.74246556424499 12.924961348198, 77.73714593953 12.921040614018, 77.73568869579699 12.910050558543, 77.732945869708 12.888278169276, 77.714259993233 12.85631617411, 77.716948505652 12.834909462871, 77.72935798040599 12.813457521761, 77.723914671957 12.805395461228, 77.710746601545 12.79465477261, 77.693115335332 12.798979730761, 77.66432544275099 12.806643557235, 77.669395756776 12.81497669372, 77.670110870893 12.817190820933, 77.668036487634 12.818358785314, 77.66556141954101 12.819564868588, 77.66314328866601 12.820386894414, 77.660971921021 12.820204627205, 77.658887393155 12.819796762003, 77.657789918208 12.820037502885, 77.656654892334 12.819990555544, 77.655642132701 12.820113541267, 77.65450062703501 12.820163297278, 77.653233057546 12.820945348698, 77.65182813770799 12.823038949471, 77.649192083934 12.825237144547, 77.643529489244 12.828291916414, 77.64062420542 12.830086107711, 77.635036712581 12.832889760396, 77.629375445718 12.834718303092, 77.625559538657 12.837090788265, 77.624490160519 12.837479895226, 77.62098884206399 12.838770677593, 77.616839205796 12.840154466343, 77.613285019928 12.842066501745, 77.60995319848701 12.843589250082, 77.61629878717 12.853375524099, 77.598528893524 12.857138857722, 77.59700466352101 12.853487786931, 77.59383285945 12.852635226043, 77.591691023642 12.850443770367, 77.58825493007301 12.849941544208, 77.581962100082 12.842891030037, 77.576350183541 12.836781502148, 77.563507031494 12.84115347288, 77.54892176156601 12.847344964928, 77.52772752862499 12.857720266329, 77.524428994232 12.85897438922, 77.53784301286299 12.879390494455, 77.528855221802 12.883991848334, 77.47377570825201 12.907246757608, 77.481996327453 12.959693115283, 77.48516249948101 12.976879345887, 77.487642026001 12.987540940378, 77.48885933023099 12.99828214478, 77.487923029953 13.002272680094, 77.486128422791 13.007433950863, 77.48409983545 13.011687626541, 77.483345925385 13.015071660086, 77.48336449151699 13.018288398117, 77.48410333543499 13.023659809358, 77.48003566079799 13.028194892116, 77.478938427979 13.039606109147, 77.48239022164999 13.054444934849, 77.495326306396 13.062343354028, 77.50338860803301 13.059745771181, 77.512206036621 13.064447067198, 77.516443089539 13.066212422937, 77.518963528686 13.066890861125, 77.51988453393599 13.067223534285, 77.52174967675801 13.06789063889, 77.537261899047 13.074075787597, 77.53987395196501 13.075475741235, 77.542056851441 13.077293710937, 77.544620205933 13.080009969947)))

gdf = gpd.GeoDataFrame(df, geometry=df["geometry"].apply(shapely.wkt.loads), crs="epsg:4386")

gdf.plot(column="value")



df2 = pd.read_csv(io.StringIO("""
NAME   lt   ln
1     12.9336806      77.6122669
2    12.974768    77.767745
3    12.9314583   77.6299858
4    12.943219    77.6213569
5    12.95120049      77.56729126
6    13.0292902   77.54489136
7    13.00134159      77.60814171
8    13.0347          77.653
9    12.88734436      77.57913454
"""), sep="\s\s+", engine="python")



df2['lat'] = df2['lt'].astype(float)
df2['lon'] = df2['ln'].astype(float)


gdf2 = gpd.GeoDataFrame(df2,geometry=gpd.points_from_xy(df2.lon, df2.lat, crs="EPSG:4326"))



gdf2['dist']=gdf.boundary.distance(gdf2)

gdf2['dis_out']=gdf.exterior.distance(gdf2)

this gives the distance just for the 1st point. How do I fix this?

1 Answer 1

3

Attention, you are trying to calculate the Euclidean distance in meters between geometries in degrees (WSG 84, longitude, latitude, EPSG:4326, unit Degree) which is wrong. There are many question/answers on the subject in GisSE.

The problem, gdf and gdf2 GeoDataFrames (with Folium)

enter image description here

The solution to your problem is to iterate through each point

# your solution = only first point
gdf.boundary.distance(gdf2)
0    0.077765
1         NaN
2         NaN
....

Iterate through each point:

for geom in gdf2.geometry:
    # Euclidean distance ! wrong value
    print(geom.distance(gdf.geometry[0].boundary)) 
0.07776484509652448
0.002474967018698133
0.07922425936786882
0.08894198216262451
0.07733999013577779
0.04442633843608382
0.08201938554485819
0.03038325224184784
0.03589586767972705

Therefore:

gdf2['dist'] = [geom.distance(gdf.geometry[0].boundary) for geom in gdf2.geometry]
# or 
gdf2['dist'] = gdf2.apply(lambda x: x.geometry.distance(gdf.geometry[0].boundary), axis=1)

For the correct Euclidean distance value in meters, you need to change the projection of the GeoDataFrame (EPSG:32643 UTM zone 43N, unit=m for example):

 gdf  = gdf.to_crs(32643)
 gdf2 = gdf2.to_crs(32643)
 for geom in a.geometry:
     # Euclidean distance in meters
     print(geom.distance(poly.geometry[0].boundary))  
 8603.109809027037
 268.94762076616416
 8762.466599082121
 9837.199184304245
 8526.103395875243
 4904.016802234688
 9016.260930752227
 3347.819307529263
 3951.6689346359485
2
  • if I use gdf2 = gpd.GeoDataFrame(df2,geometry=gpd.points_from_xy(df2.lon, df2.lat, crs="EPSG:32643")) and then run the gdf2['dist'] = gdf2.apply(lambda x: x.geometry.distance(gdf.geometry[0].boundary), axis=1) does that work ?
    – Ani
    Jun 25, 2022 at 12:41
  • 2
    no, because your original coordinates are in degrees (EPSG 4326)
    – gene
    Jun 25, 2022 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.