st_disaggregate: Disaggregate GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING,...

View source: R/st_disaggregate.R

st_disaggregateR Documentation

Disaggregate GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON into sub-geometries

Description

Disaggregate GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON into sub-geometries

Usage

st_disaggregate(
  x,
  only_geometrycollection = FALSE,
  keep_empty = FALSE,
  warn = TRUE
)

Arguments

x

object of class sfg, sfc or sf

only_geometrycollection

logical; if TRUE only GEOMETRYCOLLECTIONs are disaggregated into their components, which can include MULTI-part geometries. If FALSE (default) MULTI-part geometries originating from GEOMETRYCOLLECTIONs or included as such in x are further disaggregated into their sub-geometries.

keep_empty

logical; if TRUE empty geometries are kept, if FALSE (default) they are dropped.

warn

logical; if TRUE, warn if attributes are assigned to sub-geometries

Details

When GEOMETRYCOLLECTIONs, MULTIPOINTs, MULTILINESTRINGs or MULTIPOLYGONs are combined in a geometry set, possibly together with single part geometries, then disaggregating them can be a cumbersome task. In most situations, some combination of filtering by geometry type, st_collection_extract and/or st_cast, will do the job. However, st_disaggregate achieves that much more smoothly (for comparison s. examples below).

In particulate, extracting single and multi-part geometries as such when contained in the very same GEOMETRYCOLLECTION (i.e., without disaggregating the multi-part geometries into their sub-geometries) can be done with st_disaggregate, but neither with st_collection_extract nor with st_cast. Furthermore, st_disaggregate can dissolve a sfg object consisting of a multi-part geometry into all its sub-geometries, while st_cast would only return the first of the sub-geometry.

Value

an object of class sf, if the input x itself is an sf-object, else a object of class sfc, containing sub-geometries of the disaggregated input geometries. The level of disaggregation is determined by the argument only_geometrycollection.

Examples

library(sf)

pt1 <- st_point(c(-10, -10))
pt2 <- st_point(c(10, -10))
pt3 <- st_point(c(10, 10))
pt4 <- st_point(c(-10, 10))
pt5 <- st_point(c(6, -5))
mpt <- st_multipoint(c(pt1, pt2, pt5))
ls1 <- st_linestring(c(pt1, pt2, pt3)) * 0.7 + c(1, 0)
ls2 <- st_linestring(c(pt1, pt4)) * 0.9 - c(1, 0)
ls3 <- st_linestring(c(pt1, pt3, pt4)) * 0.2 + c(-5, 6)
mls <- st_multilinestring(list(ls2, ls3))
pl1 <- st_polygon(list(rbind(pt1, pt3, pt4, pt1))) * 0.2 + c(-2, 3)
pl2 <- st_polygon(list(rbind(pt1, pt2, pt3, pt4, pt1) * 0.3,
                       rbind(pt1, pt2, pt3, pt1) * 0.1)) - c(2, 3)
pl3 <- st_polygon(list(rbind(pt1, pt5, pt3, pt4, pt1))) * 0.2 + c(3, 3)
mpl <- st_multipolygon(list(pl2, pl3))
gc1 <- st_geometrycollection(list(mpt, ls1, mpl))
gc2 <- st_geometrycollection(list()) # empty geometry

# function plotting sfc with distinct color for each geometry
plot_sfc <- function(sfc) {
  sfc %>% plot(., col = seq_along(.), border = seq_along(.), lwd = 2, cex = 1.5)
}

plot(gc1)
st_disaggregate(gc1) %>% summary()
st_disaggregate(gc1) %>% plot_sfc()
st_disaggregate(gc1, only_geometrycollection = TRUE) %>% summary()
st_disaggregate(gc1, only_geometrycollection = TRUE) %>% plot_sfc()

mixed_bag <- st_sfc(pt3, pt4, mls, pl1, gc1, gc2)
mixed_bag %>% plot_sfc()
mixed_bag %>% summary()
st_disaggregate(mixed_bag) %>% summary()
st_disaggregate(mixed_bag, only_geometrycollection = TRUE) %>% summary()
st_disaggregate(mixed_bag, keep_empty = TRUE) %>% summary()
st_disaggregate(mixed_bag, keep_empty = TRUE) %>% st_is_empty() %>% summary()

mixed_bag_without_gc <- st_sfc(pt3, pt4, mpt, ls1, mls, pl1, mpl)
mixed_bag_without_gc %>% plot_sfc()
mixed_bag_without_gc %>% summary()
st_disaggregate(mixed_bag_without_gc) %>% summary()
# if no geometry collection is involved and only_geometrycollection = TRUE ...
# ... then no multi-part geometry is disaggregated:
all.equal(
  mixed_bag_without_gc,
  st_disaggregate(mixed_bag_without_gc, only_geometrycollection = TRUE)
)

# compare st_disaggregate() to st_cast() on mixed sets of single and multi-part-geometries:
mixed_ls_mls <- st_sfc(ls1, mls)
mixed_ls_mls %>% summary()
st_disaggregate(mixed_ls_mls) %>% summary()
st_cast(mixed_ls_mls, "LINESTRING") %>% summary() # only 1st sub-geometry of each multi-part kept.
st_cast(mixed_ls_mls, "MULTILINESTRING") %>% st_cast("LINESTRING") %>% summary() # this trick works!
# but st_disaggregate() is more elegant:
st_equals(
  st_disaggregate(mixed_ls_mls),
  st_cast(mixed_ls_mls, "MULTILINESTRING") %>% st_cast("LINESTRING")
)

# compare usage of st_disaggregate() and st_collection_extract() for extracting
# single geometries of the same dimension from a geometry collection containing
# single as well as multi-part geometries of that very dimension:
gc <- st_geometrycollection(list(pt1, pt2, ls1, mls))
st_disaggregate(gc) %>% summary()
st_collection_extract(gc, "LINESTRING") %>% summary()
st_disaggregate(gc) %>% .[st_dimension(.) == 1] %>% summary()
st_collection_extract(gc, "LINESTRING") %>% st_cast("LINESTRING") %>% summary()
st_equals(
  st_disaggregate(gc) %>% .[st_dimension(.) == 1],
  st_collection_extract(gc, "LINESTRING") %>% st_cast("LINESTRING")
)

# extracting single and multi-part geometries (of the same dimension) as such
# from a geometry collection only works with st_disaggregate():
st_disaggregate(gc, only_geometrycollection = TRUE) %>% .[st_dimension(.) == 1] %>% summary()

a-benini/sfhelpers documentation built on Aug. 28, 2024, 3:30 a.m.