.chunk <- function(x, chunk_size) {
stopifnot(inherits(x, "sf") && "assetid" %in% names(x))
metadata <- st_drop_geometry(x)
x <- x[, "assetid"]
x[["chunked"]] <- FALSE
geom_org <- attr(x, "sf_column")
x <- .split_dateline(x)
if (!is.null(chunk_size)) {
x <- .split_multipolygons(x, chunk_size)
x <- .chunk_geoms(x, chunk_size)
}
names(x)[names(x) == attr(x, "sf_column")] <- geom_org
st_geometry(x) <- geom_org
.finalize_assets(x, metadata, geom_org)
}
.finalize_assets <- function(x, meta, geom_org) {
stopifnot("assetid" %in% names(x) && "assetid" %in% names(meta))
x <- st_sf(tibble::as_tibble(dplyr::left_join(meta, x, by = "assetid")),
sf_column_name = geom_org
)
x$chunked <- NULL
.geom_last(x)
}
.split_dateline <- function(x) {
stopifnot(inherits(x, "sf"))
crosses_dateline <- sapply(st_geometry(x), .crosses_dateline)
if (any(crosses_dateline)) {
fix_dt <- st_wrap_dateline(x[which(crosses_dateline), ], options = c("WRAPDATELINE=YES", "DATELINEOFFSET=10"))
fix_dt <- .cast_to_polygon(fix_dt)
x <- rbind(x[-which(crosses_dateline), ], fix_dt)
}
x
}
.crosses_dateline <- function(geom, offset = 10) {
stopifnot(inherits(geom, "sfg"))
bbox <- st_bbox(geom)
sum <- abs(bbox[[1]]) + abs(bbox[[3]])
diff <- bbox[[1]] < 0 && bbox[[3]] > 0
diff && (360 - offset) <= sum
}
.cast_to_polygon <- function(geom) {
stopifnot(inherits(geom, "sf") && "assetid" %in% names(geom))
is_poly <- st_geometry_type(geom) == "POLYGON"
polys <- geom[is_poly, ]
casted <- suppressWarnings(st_cast(geom[!is_poly, ], "POLYGON"))
polys <- st_sf(rbind(polys, casted))
.try_make_valid(polys)
}
.split_multipolygons <- function(x, chunk_size) {
stopifnot(inherits(x, "sf") && "assetid" %in% names(x) && "chunked" %in% names(x))
is_smaller <- .calc_bbox_areas(x) < chunk_size
x[["chunked"]][is_smaller] <- TRUE
if (all(is_smaller)) {
return(x)
}
x_split <- x[!is_smaller, ]
x_split <- .cast_to_polygon(x_split)
is_smaller2 <- .calc_bbox_areas(x_split) < chunk_size
x_split[["chunked"]][is_smaller2] <- TRUE
rbind(x[is_smaller, ], x_split)
}
.calc_bbox_areas <- function(geom) {
bboxs <- lapply(st_geometry(geom), function(y) st_as_sfc(st_bbox(y)))
bboxs <- st_sf(do.call("c", bboxs), crs = st_crs(geom))
as.numeric(st_area(bboxs) / 10000)
}
.chunk_geoms <- function(x, chunk_size) {
stopifnot(inherits(x, "sf") && "assetid" %in% names(x) && "chunked" %in% names(x))
if (all(x[["chunked"]])) {
return(x)
}
x_ok <- NULL
x_grid <- x[!x[["chunked"]], ]
if (any(x[["chunked"]])) {
x_ok <- x[x[["chunked"]], ]
}
# only chunks if more than 2x2 cells
n_cells <- ceiling(sqrt(.calc_bbox_areas(x_grid) / chunk_size))
to_grid <- n_cells > 2
if (any(!to_grid)) {
x_ok <- rbind(x_ok, x_grid[!to_grid, ])
x_grid <- x_grid[to_grid, ]
}
if (any(to_grid)) {
x_grid <- purrr::map(1:nrow(x_grid), function(i) .make_grid(x_grid[i, ], chunk_size))
x_grid <- st_sf(purrr::list_rbind(x_grid))
}
rbind(x_ok, x_grid)
}
.make_grid <- function(geom, chunk_size) {
# stopifnot(inherits(geom, "sf") && "assetid" %in% names(geom))
n <- ceiling(sqrt(.calc_bbox_areas(geom) / chunk_size))
geom_grid <- st_make_grid(geom, n = n)
geom_grid <- st_intersection(geom_grid, geom)
geom_grid <- st_sf(geom_grid, assetid = geom[["assetid"]], chunked = TRUE)
st_geometry(geom_grid) <- attr(geom, "sf_col")
.try_make_valid(geom_grid)
}
#' @importFrom stats sd var
.aggregation_fun <- function(agg) {
stopifnot(agg %in% available_stats)
switch(agg,
sum = sum,
mean = mean,
median = median,
sd = sd,
min = min,
max = max,
sum = sum,
var = var
)
}
.combine_chunks <- function(data, aggregation = "sum") {
stat <- NULL
is_null <- sapply(data, is.null)
if (all(is_null)) {
return(NULL)
}
data <- data[!is_null]
if (length(data) == 1) {
return(data[[1]])
}
if (aggregation == "stat") {
data <- data %>%
purrr::list_rbind() %>%
dplyr::mutate(
stat = purrr::map_chr(strsplit(variable, "_"), function(x) rev(x)[1])
) %>%
dplyr::group_by(datetime, variable, unit) %>%
dplyr::summarise(value = .aggregation_fun(stat[1])(value, na.rm = TRUE)) %>%
dplyr::ungroup()
} else {
agg <- .aggregation_fun(aggregation)
data <- data %>%
purrr::list_rbind() %>%
dplyr::group_by(datetime, variable, unit) %>%
dplyr::summarise(value = agg(value, na.rm = TRUE)) %>%
dplyr::ungroup()
}
data
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.