inat-ranges / utils.R
cboettig's picture
:bird:
a9b986b
library(dplyr)
library(duckdbfs)
library(sf)
as_dataset.sf <- function(sf, ...) {
# cludgy way to get polygon into duckdb as spatial data
tmp <- tempfile(fileext = ".fgb")
sf |> sf::st_transform(4326) |> sf::write_sf(tmp, append = FALSE, quiet = TRUE)
aoi <- duckdbfs::open_dataset(tmp, ...)
aoi
}
# promote bbox to polygon
as_poly <- function(aoi) {
crs <- st_crs(aoi)
if (crs$input != "EPSG:4326" ) {
aoi <- aoi |> st_transform(4326)
}
if (inherits(aoi, "bbox")) {
aoi <- aoi |>
st_as_sfc() |>
st_as_sf() |>
rename(geom = x)
}
aoi
}
get_h3_aoi <- function(aoi, zoom = 0L, precision = 6L, upper = FALSE) {
duckdbfs::load_h3()
zoom <- as.integer(zoom)
# consider auto-retry at higher precision if subset is empty.
precision <- as.integer(precision)
res <- paste0("h", precision)
if(inherits(aoi, "sf") || inherits(aoi, "bbox")) {
aoi <- as_poly(aoi)
aoi <- as_dataset.sf(aoi)
}
# multipolygon dump may not be needed for draw tools.
h3_aoi <- aoi |>
dplyr::mutate(poly = array_extract(unnest(st_dump(geom)),"geom"),
h3id = h3_polygon_wkt_to_cells(poly,{precision}),
h3id = unnest(h3id)
) |>
dplyr::mutate(h0 = h3_h3_to_string( h3_cell_to_parent(h3id, {zoom})),
h3id = h3_h3_to_string (h3id) )
if(upper) {
h3_aoi <- h3_aoi |>
dplyr::mutate(h0 = toupper(h0), h3id = toupper(h3id))
}
h3_aoi |>
dplyr::select(h0, h3id) |>
duckdbfs::as_view("h3_aoi")
}
hex_res <- function(x) {
x |>
utils::head(1) |>
dplyr::mutate(res = h3_get_resolution(h3id)) |>
dplyr::pull(res)
}
hex_join <- function(x,y) {
res_x <- hex_res(x)
res_y <- hex_res(y)
if (res_x > res_y) {
y <- y |>
dplyr::mutate(h3id = unnest(h3_cell_to_children(h3id, {res_x})),
h3id = toupper(h3id))
}
if (res_x < res_y) {
y <- y |>
dplyr::mutate(h3id = h3_cell_to_parent(h3id, {res_x}))
}
dplyr::inner_join(x, y)
}
antimeridian_hexes <- function(zoom = 4, con = duckdbfs::cached_connection()) {
duckdbfs::load_h3(con)
duckdbfs::load_spatial(con)
DBI::dbExecute(con,
"
CREATE OR REPLACE TABLE antimeridian AS (
SELECT ST_GeomFromText(
'POLYGON ((170 85, 190 85, 190 -85, 170 -85, 170 85))'
) AS geometry
)
")
zoom <- as.integer(zoom)
am <-
dplyr::tbl(con, "antimeridian") |>
dplyr::mutate(h3id = unnest(
h3_polygon_wkt_to_cells_string(geometry, {zoom})
)) |>
dplyr::select(h3id)
am
}
viridis_pal <-
function(column = "height",
n = 61,
min_v = 0,
max_v = 1) {
pal <- viridisLite::viridis(n)
fill_color = mapgl::step_expr(
column = column,
base = pal[1],
stops = pal[2:n],
values = seq(min_v, max_v, length.out = n-1),
na_color = "white"
)
fill_color
}