I want to retrieve the nearest coordinate point based on circle radius in kilometers and plot the result on scatter mapbox. But I dont know how to plot the circle shape radius. Anyone knows how to plot the circle shape radius?
So far my result just only data in circle radius without its circle shape. This is my code
import plotly.graph_objects as go
import plotly.express as px
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371
return c * r
center_point = pd.DataFrame({'Longitude':[long_input], 'Latitude':[lat_input]})
test_point = df_latlong[['Longitude','Latitude']].reset_index().drop('index',axis=1)
lat1 = center_point['Latitude'][0]
lon1 = center_point['Longitude'][0]
df_nearest = []
for i, (index, row) in enumerate(df_latlong.iterrows()):
lat2 = test_point['Latitude'][i]
lon2 = test_point['Longitude'][i]
a = haversine(lon1, lat1, lon2, lat2)
df_nearest.append(a)
df_latlong['Distance'] = df_nearest
df_radius = df_latlong[df_latlong['Distance'] <= 5] #5 kilometers for radius
fig_map3 = px.scatter_mapbox(df_radius, lon=df_radius['Longitude'], lat=df_radius['Latitude'],
hover_name='#WELL', zoom=9, width=300, height=500)
fig_map3.update_layout(mapbox_style='open-street-map', margin={'r':0, 't':0, 'l':0, 'b':0})
fig_map3.show()
it has circle shape radius based on centroid that I have defined in center_point. How can I plot black circle like that? The radius has 5 kilometers. Any idea? Thanks!
First I created some sample data in the same geographic region as the data you showed in your screenshots.
Then, we can calculate the (latitude, longitude) points for a circle with radius r, center point, and number of sample points using the approximation given by @Stéphane (for your question, the 5 km radius you want around your center point is small enough that this approximation holds well).
Note: I tried to [unsuccessfully] calculate the exact coordinates of the circle using geog.propogate
as outlined here, but it wasn't generating the correct coordinates for a circle around the center coordinate.
Then you can pass the (latitude, longitude) points of the circle to go.Scattermapbox
, set the mode to 'lines', and add the trace to your figure.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from math import radians, cos, sin, asin, sqrt, pi
def haversine(lon1, lat1, lon2, lat2):
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
r = 6371
return c * r
## create a sample dataframe to reproduce your data
lat_input, long_input = -0.622929, 117.575513,
lat_min, lat_max = -0.59, -0.68
long_min, long_max = 117.543, 117.614
np.random.seed(42)
df_latlong = pd.DataFrame({
'Latitude': np.random.uniform(lat_min, lat_max, size=20),
'Longitude': np.random.uniform(long_min, long_max, size=20),
'#WELL': ["TN-test"]*20
})
center_point = pd.DataFrame({'Longitude':[long_input], 'Latitude':[lat_input]})
test_point = df_latlong[['Longitude','Latitude']].reset_index().drop('index',axis=1)
lat1 = center_point['Latitude'][0]
lon1 = center_point['Longitude'][0]
df_nearest = []
for i, (index, row) in enumerate(df_latlong.iterrows()):
lat2 = test_point['Latitude'][i]
lon2 = test_point['Longitude'][i]
a = haversine(lon1, lat1, lon2, lat2)
df_nearest.append(a)
df_latlong['Distance'] = df_nearest
df_radius = df_latlong[df_latlong['Distance'] <= 5] #5 kilometers for radius
fig_map3 = px.scatter_mapbox(df_radius, lon=df_radius['Longitude'], lat=df_radius['Latitude'],
hover_name='#WELL', zoom=9, width=300, height=500)
radius = 5 * 1000 # m - the following code is an approximation that stays reasonably accurate for distances < 100km
# parameters
N = 360 # number of discrete sample points to be generated along the circle
# generate points
circle_lats, circle_lons = [], []
for k in range(N):
# compute
angle = pi*2*k/N
dx = radius*cos(angle)
dy = radius*sin(angle)
circle_lats.append(lat1 + (180/pi)*(dy/6378137))
circle_lons.append(lon1 + (180/pi)*(dx/6378137)/cos(lat1*pi/180))
circle_lats.append(circle_lats[0])
circle_lons.append(circle_lons[0])
fig_map3.add_trace(go.Scattermapbox(
lat=circle_lats,
lon=circle_lons,
mode='lines',
marker=go.scattermapbox.Marker(
size=1, color="BlueViolet"
),
))
fig_map3.update_layout(mapbox_style='open-street-map', margin={'r':0, 't':0, 'l':0, 'b':0}, width=500)
fig_map3.show()