Calculate distance from a point.
This post is about how to calculate distance from a point
Identify your reference point
reference<-data.frame(name="reference",lat=54.18,long=7.89)
Convert it to a spatial object
reference_sp<-data.frame(lat=reference$lat,
lon=reference$lon)
sp::coordinates(reference_sp)<-~lon+lat
Then give the information of the other points to compare
colonies_sub<-data.frame(name=c("Ailsa Craig","Barra Head","Bass Rock","Bempton Cliff","Bull Rock","Clare Island", "Fair Isle", "Flannan Isles","Foula","Grassholm Island","Great Saltee", "Helgoland" , "Hermaness", "Ireland’s Eye", "Lambay", "Les Etac/Alderrney","Little Skellig","Mykinesholmur","Noss" ,"Ortac","Rouzic Island","Scar Rocks","St. Kilda","Sula sgeir","Sule Skerry","Sule Stack","Troup Head","Westray"),
colony_lat=c(55.25,56.78,56.08,54.15,51.59,53.80,59.54,58.29,60.13,51.73,52.12,54.18,60.71,53.40,53.49,49.70,51.78,62.10,60.14,49.72,48.90,54.67,57.81,59.10,59.08,59.02,57.69,59.29),
colony_long=c(-5.12,-7.64,-2.64,-0.17,-10.27,-10.00,-1.63,-7.59,-2.07,-5.48,-6.62,7.89,-0.88,-6.06,-6.02,-2.24,-10.51,-7.68,-1.02,-2.29,-3.44,-4.70,-8.56,-6.16,-4.41,-4.51,-2.29,-2.98))
head(colonies_sub)
name colony_lat colony_long
1 Ailsa Craig 55.25 -5.12
2 Barra Head 56.78 -7.64
3 Bass Rock 56.08 -2.64
4 Bempton Cliff 54.15 -0.17
5 Bull Rock 51.59 -10.27
6 Clare Island 53.80 -10.00
Convert this data frame into a spatial object
colonies_sp<-data.frame(lat=colonies_sub$colony_lat,
lon=colonies_sub$colony_long)
sp::coordinates(colonies_sp)<-~lon+lat
Give both objects the same coordinate system to make sure they are comparable
sp::proj4string(reference_sp)= sp::CRS("+init=epsg:4326")
sp::proj4string(colonies_sp)= sp::CRS("+init=epsg:4326")
Using the funcion distm from the package geosphere the distance can be calculated. Give the argument distHaversine. Read here what is Haversine.
maxdist_m<-(geosphere::distm(reference_sp,colonies_sp,fun = geosphere::distHaversine))
maxdist_km<-round(maxdist_m/1000,digits=2)
Load the package tidyverse to make some data wrangling
Use the function pivot_longer to reorder the information
distances<-as.data.frame(maxdist_km)%>%
pivot_longer(cols=c(V1:V28))
Assign to the data frame
colonies_sub$distance<-distances$value
Here are the results from the distance between the point and the reference point
head(colonies_sub)
name colony_lat colony_long distance
1 Ailsa Craig 55.25 -5.12 843.75
2 Barra Head 56.78 -7.64 1019.01
3 Bass Rock 56.08 -2.64 701.93
4 Bempton Cliff 54.15 -0.17 525.01
5 Bull Rock 51.59 -10.27 1249.65
6 Clare Island 53.80 -10.00 1168.49
Load the shapefiles from my package GermanNorthSea
library(GermanNorthSea)
Transform them to the assigned CRS using the package sf
Here I used 4326
German_land<-st_transform(GermanNorthSea::German_land, 4326)
German_EEZ<-st_transform(GermanNorthSea::German_EEZ, 4326)
German_SCA<-st_transform(GermanNorthSea::German_natura, 4326)
Base plot
To create a plot use ggplot2
First using a base plot of the North Sea, highlighting the economic exclusive zone of Germany
base_plot<-ggplot()+
geom_sf(data = German_EEZ, colour = "black", fill= NA, lwd = 0.5,linetype="dashed")+
geom_sf(data = German_land, colour = '#edf2f4', fill = '#2b2d42')+
coord_sf(xlim = c(-12, 10),ylim = c(48, 63))+
scale_x_continuous(breaks = c(-10,-5,0,5,10,20,30),labels = function(x) paste0(x, '\u00B0')) +
scale_y_continuous(breaks = c(45,50,55,60,65,70,75),labels = function(x) paste0(x, '\u00B0')) +
theme_bw()+
xlab('Longitude')+ylab('Latitude')+
theme(
panel.background = element_rect(fill = '#edf2f4'),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),legend.position='none',
panel.border = element_rect(colour = "black", fill=NA, size=1.5),
legend.spacing.y = unit(0.05, 'cm'),
legend.text=element_text(size=10),
legend.background = element_rect(fill='transparent',colour ="transparent"),
legend.box.background = element_rect(fill='transparent',colour ="transparent"),
legend.key = element_rect(fill = "transparent", colour = "transparent"),
axis.text.x = element_text(size=10,vjust = 10,color='#3d5a80'),
axis.text.y = element_text(color='#3d5a80',size=10,margin = margin(0,-1.00,0,1, unit = 'cm')),
axis.title = element_blank(),
axis.ticks.length=unit(-0.20, "cm"),
)
base_plot
Add the reference point to be able to plot
colonies_sub$reference_long<-reference$lon
colonies_sub$reference_lat<-reference$lat
Use the function geom_curve to create lines between the reference point and the other points.
curves_plot<-base_plot+
geom_curve(data= subset(colonies_sub,colonies_sub$name != 'Helgoland'),
aes(x = reference_long, y = reference_lat,
xend = colony_long, yend = colony_lat),
color = '#faa307',
curvature = 0.05, alpha = 0.5)
curves_plot
Add the other points using geom_point
points_plot<-curves_plot+
geom_point(data=colonies_sub,
aes(x = colony_long,y= colony_lat),
color='#faa307', fill='#ffba08',shape=16,size=2,stroke=1.5)+
geom_point(data=reference,
aes(x = long,y= lat),
color='#ff5400', fill='#ff5400',shape=16,size=4,stroke=1.5)
points_plot
letters_plot<-points_plot+
annotate("text", y = 54.15-0.21, x = -0.17+2.5,
label = "Bempton Cliff \n (525 km)",
size=3.5,color='#0d3b66')+
annotate("text", y = 56.08-0.21, x = -2.64+2.5,
label = "Bass Rock \n (701 km)",
size=3.5,color='#0d3b66')+
annotate("text", y = 57.69-0.21, x = -2.29+2.0,
label = "Troup Head \n (523 km)",
size=3.5,color='#0d3b66')+
annotate("text", y = 54.18-0.21, x = 7.89-1.9,
label = "Helgoland \n",
size=3.5,color='red')+
NULL
letters_plot
Alternatively using the package nngeo
Check my package GermanNorthSea
How to make maps in R blogpost