library(jsonlite) library(sf) library(dplyr) library(tidyr) library(ggplot2) library(geosphere) library(rnaturalearth) # API URL from the last 60 minutes api_spots <- "http://[300:6f6a:b087:4dda::8]/api/v1/spots?max_age=3600" # What time is it? time <- `attr<-`(Sys.time(),"tzone","UTC") # Get the spots spots_raw <- fromJSON(api_spots) %>% mutate(across(c(de_longitude, de_latitude, dx_longitude, dx_latitude), as.numeric)) # Convert to spatial spots <- spots_raw %>% st_as_sf(coords = c("dx_longitude", "dx_latitude"), crs = "EPSG:4326") %>% mutate(color = band_color) %>% select(c(-dx_flag, -de_flag)) spotters <- spots_raw %>% st_as_sf(coords = c("de_longitude", "de_latitude"), crs = "EPSG:4326") # Make lines # https://stackoverflow.com/a/76197010 lines <- bind_rows(spots, spotters) %>% group_by(id) %>% dplyr::summarize(do_union=FALSE) %>% # do_union=FALSE doesn't work as well st_cast("LINESTRING") # Make geodesic lines great_circles_list <- list() for(i in 1:nrow(spots_raw)){ great_circles_list[[i]] <- as.data.frame(gcIntermediate(c(spots_raw[i,"dx_longitude"], spots_raw[i,"dx_latitude"]), c(spots_raw[i,"de_longitude"], spots_raw[i,"de_latitude"]))) names(great_circles_list)[[i]] <- spots_raw[i,"id"] } great_circles <- bind_rows(great_circles_list, .id = "id") %>% st_as_sf(coords = c("lon", "lat"), crs = "EPSG:4326") %>% group_by(id) %>% dplyr::summarize(do_union=FALSE) %>% # do_union=FALSE doesn't work as well st_cast("LINESTRING") %>% left_join(spots_raw, by = "id") %>% mutate(color = band_color) station_bbox <- matrix(c(st_bbox(spots), st_bbox(spotters)), nrow = 4, ncol = 2) %>% t() %>% as.data.frame() %>% summarize(xmin = min(V1), ymin = min(V2), xmax = max(V3), ymax = max(V4)) # Pull in GIS basemaps etc. countries <- ne_download( scale = 50, type = "admin_0_countries", category = "cultural", returnclass = "sf" ) borders <- ne_download( scale = 50, type = "admin_1_states_provinces", category = "cultural", returnclass = "sf" ) # Make simple map ggplot() + geom_sf(data = countries) + geom_sf(data = borders) + geom_sf(data = great_circles, aes(color = band)) + geom_sf(data = spots) + geom_sf(data = spotters, color = "green") + geom_sf_text(data = spotters, aes(label = de_call)) + coord_sf(crs = "EPSG:4269", xlim = c(station_bbox$xmin, station_bbox$xmax), ylim = c(station_bbox$ymin, station_bbox$ymax)) + theme_bw() + theme(#axis.title.x=element_blank(), axis.title.y=element_blank()) + labs(x = time) ggsave("out/farpn_map_simple.png", scale = 0.75) # Export spatial data st_write(spots, "out/spots.geojson", delete_dsn = T) st_write(spotters, "out/spotters.geojson", delete_dsn = T) st_write(great_circles, "out/great_circles.geojson", delete_dsn = T) # Try to combine in one file st_write(spots %>% bind_rows(spotters) %>% bind_rows(great_circles), "out/all.geojson", delete_dsn = T)