-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0_fuzz_site_coordinates.R
executable file
·47 lines (44 loc) · 1.66 KB
/
0_fuzz_site_coordinates.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env Rscript
library(tidyverse)
# "Fuzz" the true site coordinates to be used for the map
# This will only run if `data/site_coordinates_unfuzzed.csv` exists.
# That file is NOT included in the public GitHub repository.
# This script *is* included to help convince people that the published
# `data/site_coordinates.csv` function has a principled connection to
# reality...
## Haversine distance function to help sanity check fuzzing
haversine <- function(lat1, lon1, lat2, lon2) {
lat1 <- lat1*pi / 180
lon1 <- lon1*pi / 180
lat2 <- lat2*pi / 180
lon2 <- lon2*pi / 180
delta_lat <- lat2 - lat1
delta_lon <- lon2 - lon1
x <- 1 - cos(delta_lat) + cos(lat1)*cos(lat2)*(1-cos(delta_lon))
d <- 2*6371*asin(sqrt(0.5*x))
return(d)
}
## Fuzz coordinates one at a time...
coords <- read_csv("data/site_coordinates_unfuzzed.csv")
for(i in 1:nrow(coords)) {
while(TRUE) {
lat <- coords$Latitude[i]
lon <- coords$Longitude[i]
# Pick a random distance between 100km and 200km and a random direction
fuzz_dist_km <- rnorm(1, 150, 25)
fuzz_bearing <- runif(1, 0, 2*pi)
# km per deg lat/lon based on https://stackoverflow.com/a/1253545
new_lat <- lat + (fuzz_dist_km / 110.574)*sin(fuzz_bearing)
new_lon <- lon + (fuzz_dist_km / (111.320*cos(lat*pi/180)))*cos(fuzz_bearing)
# Ensure distance between new and old coords is within +/- 1% of
# intended fuzz distance, because who knows if above Stack
# Overflow solution is correcgt?
dist <- haversine(lat, lon, new_lat, new_lon)
if(dist/fuzz_dist_km <= 1.01 & dist/fuzz_dist_km >= 0.99) {
break
}
}
coords$Latitude[i] <- new_lat
coords$Longitude[i] <- new_lon
}
write_csv(coords, "data/site_coordinates.csv")