Skip to contents

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

The creation of streetblocks requires two input datasets: - a polygon representing the extents of the study area, - linestrings representing highways/ streets in the study area.

Typically, the study area extents are pre-defined and known to us (such as the administrative or municipal boundary within a particular city or region). For this vignette, we’ll define a location in the center of Bangalore and then draw a 500m buffer around it.

# Define the study area extents.

bangalore_boundary <- data.frame(lat = c(12.964045),
                         long = c(77.585611)) |> 
  sf::st_as_sf(coords = c("long", "lat"),
               crs = 4326) |> 
  sf::st_transform(3857) |> 
  sf::st_buffer(500,
                endCapStyle = "SQUARE") |> 
  sf::st_transform(4326) |> 
  sf::st_make_valid()

bangalore_boundary

We can then use this buffer as the bounding box to download highways/ streets from OpenStreetMap.

# Download highways from OpenStreetMap

bangalore_highways <- osmdata::opq(bbox = sf::st_bbox(bangalore_boundary)) |> 
  osmdata::add_osm_feature("highway") |> 
  osmdata::osmdata_sf() |> 
  purrr::pluck("osm_lines")  |> 
  dplyr::select(osm_id, highway, geometry)  |> 
  sf::st_make_valid()

bangalore_highways

Note: Both datasets are included in multi and can be accessed using the data() function.

# Load data as included in the package.

data("bangalore_buildings") # Load for the map.
data("bangalore_highways")

The code chunk below uses these datasets to draw street blocks. Aside from setting merge_threshold = NULL, we use function defaults.

# Draw street blocks.

bangalore_streetblocks <- multi::st_create_streetblocks(x = bangalore_highways,
                                                        boundary = bangalore_boundary,
                                                        merge_threshold = NULL,
                                                        verbose = TRUE)

bangalore_streetblocks

tmap::tm_shape(bangalore_buildings) +
  tmap::tm_fill(col = "#d9d9d9") +
  tmap::tm_shape(bangalore_streetblocks) +
  tmap::tm_borders() +
  tmap::tm_layout(frame = FALSE)

Notice that the function warns us about the presence of small geometries (< m^2). Such small geometries are often created when the input data contains multiple linestrings in close proximity. Awkward street intersections and small traffic islands also result in these small geometries. To address this, we can either define a non-null merge_threshold value (in m^2) while creating the street blocks or use the st_merge_spatialunits function subsequently. We can also use the st_survey_spatialunits() function to get an overview of the current sizes.

multi::st_survey_spatialunits(bangalore_streetblocks,
                              trim = 0.3)

The st_merge_spatialunits() function uses an iterative merging process. Please refer to the Iterative Merging Vignette for more details. Below, we use 4050 m^2 as the merge threshold and max_shared_boundary as the merge type.

# Merge spatial units.

bangalore_streetblocks_merged <- multi::st_merge_spatialunits(x = bangalore_streetblocks,
                                                              merge_threshold = 4050,
                                                              merge_type = "max_shared_boundary",
                                                              verbose = FALSE)

bangalore_streetblocks_merged

tmap::tm_shape(bangalore_buildings) +
  tmap::tm_fill(col = "#d9d9d9") +
  tmap::tm_shape(bangalore_streetblocks_merged) +
  tmap::tm_borders() +
  tmap::tm_layout(frame = FALSE)

Morphological Tessellation Units

The process of creating morphological tessellation units (MTs) is very similar to the process of drawing streetblocks. The only major difference is that we require data on building polygons rather than highway/ street linestrings.

This data can also be obtained from OpenStreetMap.

# Download buildings from OpenStreetMap.

bangalore_buildings <- osmdata::opq(bbox = sf::st_bbox(bangalore_boundary)) |> 
  osmdata::add_osm_feature("building") |> 
  osmdata::osmdata_sf() |> 
  purrr::pluck("osm_polygons") |> 
  dplyr::select(osm_id, geometry) |> 
  sf::st_make_valid()

As before, this example data is included with the package. The code chunk below uses these datasets to draw MTs. We use default values for segment_length, shrink_extent, and contiguity. We skip the merging process for now.

(Please refer to Fleischmann et al., 2020 for details on segment_length and shrink_extent.)

# Draw MTUs.

bangalore_mtus <- multi::st_create_tessellations(x = bangalore_buildings,
                                                 boundary = bangalore_boundary,
                                                 merge_threshold = NULL,
                                                 verbose = FALSE)

bangalore_mtus

tmap::tm_shape(bangalore_buildings) +
  tmap::tm_fill(col = "#d9d9d9") +
  tmap::tm_shape(bangalore_mtus) +
  tmap::tm_borders() +
  tmap::tm_layout(frame = FALSE)

A similar but alternative implementation of a function to create MTs is available in the moter package.

References

Fleischmann, M., Feliciotti, A., Romice, O., & Porta, S. (2020). Morphological tessellation as a way of partitioning space: Improving consistency in urban morphology at the plot scale. Computers, Environment and Urban Systems, 80, 101441.

Padgham, M., Rudis, B., Lovelace, R., Salmon, M., Smith, A., Smith, J., Gilardi, A., Spinielli, E., North, A., Machyna, M., & code), M. K. (Author of included R. (2022). osmdata: Import “OpenStreetMap” Data as Simple Features or Spatial Objects (0.1.10) [Computer software]. https://CRAN.R-project.org/package=osmdata