Skip to content

Commit

Permalink
add: new merge type in st_merge_spatialunits
Browse files Browse the repository at this point in the history
add: plots in st_surveyspatialunits
fix: logic issues in st_create_tessellations
  • Loading branch information
Anirudh Govind committed Feb 11, 2024
1 parent 8f111da commit 8baa6f8
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 28 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ URL: https://github.com/anirudhgovind/multi,
BugReports: https://github.com/anirudhgovind/multi/issues
Imports:
dplyr (>= 1.0.9),
graphics,
lwgeom (>= 0.2.8),
sf (>= 1.0.8),
sfdep,
Expand Down
14 changes: 9 additions & 5 deletions R/st_create_tessellations.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#' size for a spatial unit. Contiguous units will be iteratively merged until
#' this value is reached. To skip this process, set `merge_threshold = NULL`.
#' See st_merge_spatialunits() for more details.
#' @param merge_type string; Passed on to st_merge_spatialunits.
#' @param merge_type string; Passed on to st_merge_spatialunits().
#' Criteria with which polygons are merged. Must be one of
#' "min_centroid_distance", "min_shared_boundary", or "max_shared_boundary".
#' Default = "min_centroid_distance".
Expand All @@ -38,7 +38,7 @@
st_create_tessellations <-
function(x,
boundary,
type = c("morphological"),
type = "morphological",
segment_length = 0.5,
shrink_extent = 0.4,
merge_threshold = NULL,
Expand Down Expand Up @@ -164,10 +164,14 @@ st_create_tessellations <-
)
}

# Convert CRS back to original
# If geometry is long lat, convert CRS back to the original.

tessellations <- sf::st_transform(tessellations,
x_crs)
if (sf::st_is_longlat(x) == TRUE |
sf::st_is_longlat(boundary) == TRUE) {

tessellations <- sf::st_transform(tessellations,
x_crs)
}

return(tessellations)
} else {
Expand Down
51 changes: 46 additions & 5 deletions R/st_merge_spatialunits.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#' iteratively merged until this value is reached. To skip this process,
#' set `merge_threshold = NULL`.
#' @param merge_type string; criteria with which polygons are merged. Must be one of
#' "min_centroid_distance", "min_shared_boundary", or "max_shared_boundary".
#' "min_centroid_distance", "min_adjacent_area", "max_adjacent_area", "min_shared_boundary", or "max_shared_boundary".
#' Default = "min_centroid_distance".
#' @param contiguity string; one of "queen" or "rook". Default = "rook".
#' @param verbose logical; if `FALSE` no status messages will be output.
Expand Down Expand Up @@ -43,11 +43,15 @@ st_merge_spatialunits <- function(x,

# Check type is one of defined defaults

if (!merge_type %in% c("min_centroid_distance",
"min_shared_boundary",
"max_shared_boundary")) {
if (!merge_type %in% c(
"min_centroid_distance",
"min_adjacent_area",
"max_adjacent_area",
"min_shared_boundary",
"max_shared_boundary"
)) {
stop(
"merge_type must be one of 'min_centroid_distance', 'min_shared_boundary', or 'max_shared_boundary'."
"merge_type must be one of 'min_centroid_distance', 'min_adjacent_area', 'max_adjacent_area', 'min_shared_boundary', or 'max_shared_boundary'."
)
}

Expand Down Expand Up @@ -112,6 +116,13 @@ st_merge_spatialunits <- function(x,
if (merge_type == "min_centroid_distance") {
selected_unit <- min_centroid_distance(ref_unit = ref_unit,
ref_unit_neighbours_geo = ref_unit_neighbours_geo)
} else if (merge_type == "min_adjacent_area" |
merge_type == "max_adjacent_area") {
selected_unit <- area_adjacency(
ref_unit = ref_unit,
ref_unit_neighbours_geo = ref_unit_neighbours_geo,
merge_type = merge_type
)
} else if (merge_type == "min_shared_boundary" |
merge_type == "max_shared_boundary") {
selected_unit <- shared_boundary_length(
Expand Down Expand Up @@ -166,6 +177,36 @@ st_merge_spatialunits <- function(x,
return(x)
}

# Function to merge polygon with an adjacent polygon with the smallest/ largest area

area_adjacency <- function(ref_unit,
ref_unit_neighbours_geo,
merge_type = merge_type) {
# Init Var

areas <- NULL

# Find areas of the polygons
areas <- sf::st_area(ref_unit_neighbours_geo)

# If min area
if (merge_type == "min_adjacent_area") {
smallest_area <-
as.integer(ref_unit_neighbours_geo$index[which.min(areas)])

return(smallest_area)
}

# If max area
if (merge_type == "max_adjacent_area") {
largest_area <-
as.integer(ref_unit_neighbours_geo$index[which.max(areas)])

return(largest_area)
}

}

# Function to select polygon based on minimum centroid distance

min_centroid_distance <- function(ref_unit,
Expand Down
69 changes: 57 additions & 12 deletions R/st_survey_spatialunits.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#' @param x an `sf` object with `POLYGON` geometries representing the
#' spatial units to be surveyed.
#' @param trim numeric; fraction (0 to 0.5) of values to be trimmed from the lower
#' end to compute a trimmed mean
#' end to compute a trimmed mean.
#' @param viz binary; Displays a scatterplot of area distributions.
#'
#' @return A `data.frame` object with numeric values of min, max, mean, and
#' median.
Expand All @@ -15,7 +16,13 @@
#' survey_report <- st_survey_spatialunits(x = street_blocks)
#' survey_report
st_survey_spatialunits <- function(x,
trim = NULL) {
trim = NULL,
viz = TRUE) {

# Init var for later

areas <- NULL

# Check x is of type sf

if (!inherits(x, "sf")) {
Expand All @@ -25,7 +32,8 @@ st_survey_spatialunits <- function(x,
# Check geometry types

if (all(sf::st_is(x,
"POLYGON") != TRUE)) {
c("POLYGON",
"MULTIPOLYGON")) != TRUE)) {
stop("x must contain `POLYGON` geometries.")
}

Expand All @@ -42,10 +50,11 @@ st_survey_spatialunits <- function(x,

# Survey Result

output <- data.frame(category = c("Area",
"Area",
"Area",
"Area"),
output <- data.frame(
category = c("Area",
"Area",
"Area",
"Area"),
description = c("Min",
"Max",
"Mean",
Expand All @@ -67,16 +76,52 @@ st_survey_spatialunits <- function(x,
dplyr::slice_tail(prop = 1 - trim) |>
dplyr::summarise(value = mean(areas))

suffix <- data.frame(category = c("Area"),
description = c(paste0("Trimmed Mean (",
trim,
")")),
value = c(x_trim))
suffix <- data.frame(
category = c("Area"),
description = c(paste0("Trimmed Mean (",
trim,
")")),
value = c(x_trim)
)

output <- rbind(output,
suffix)
}
}

if (viz == TRUE) {
plot(x$areas,
col = "gray",
xlab = "Spatial Unit Index",
ylab = "Areas")
graphics::abline(h = c(x_min,
x_max,
x_mean,
x_median),
lty = 2)
graphics::text(
x = c(0,
nrow(x),
0,
nrow(x)),
y = c(x_min,
x_max,
x_mean,
x_median),
labels = c("min",
"max",
"mean",
"median")
)
if (!is.null(trim)) {
graphics::abline(h = x_trim,
col = "black")
graphics::text(x = nrow(x) / 2,
y = x_trim,
labels = "trimmed mean")
}
}

print(output,
right = FALSE)
}
4 changes: 2 additions & 2 deletions man/st_create_tessellations.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/st_merge_spatialunits.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions man/st_survey_spatialunits.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vignettes/articles/1-Spatial-Units.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ tmap::tmap_options(check.and.fix = TRUE,
show.warnings = FALSE)
```

`multi` simplifies the process of creating morphological spatial units like street blocks and morphological tessellation units (MTs; Fleischmann et al., 2020). This vignette presents one workflow for creating street blocks and MTs using data from OpenStreetMap (using the excellent `osmdata` package; Padgham et al., 2022) with Bangalore, India as a case.
`multi` simplifies the process of creating morphological spatial units like street blocks and morphological tessellation units (MTs; Fleischmann et al., 2020). This vignette presents one workflow for creating street blocks and MTs using data from OpenStreetMap (sourced using the excellent `osmdata` package; Padgham et al., 2022) with Bangalore, India as a case.

## Street Blocks

Expand Down

0 comments on commit 8baa6f8

Please sign in to comment.