Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
^zonebuilder-paper_files$
^vignettes/josis*$
^\.ccache$
^CRAN-SUBMISSION$
7 changes: 4 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: zonebuilder
Title: Create and Explore Geographic Zoning Systems
Version: 0.0.2.9001
Version: 0.1.0
Authors@R:
c(person(given = "Robin",
family = "Lovelace",
Expand All @@ -13,6 +13,8 @@ Authors@R:
email = "mtennekes@gmail.com"))
Description: Functions, documentation and example data to help divide
geographic space into discrete polygons (zones).
The package supports new zoning systems that are documented in the
accompanying paper <doi:10.5311/JOSIS.2022.24.172>.
The functions are motivated by research into the merits of different zoning systems
<doi:10.1068/a090169>. A flexible 'ClockBoard' zoning system is
provided, which breaks-up space by concentric rings
Expand All @@ -39,7 +41,6 @@ Suggests:
rmarkdown,
tmap,
tmaptools,
pct,
dplyr,
lwgeom,
leaflet,
Expand All @@ -50,4 +51,4 @@ VignetteBuilder:
URL: https://github.com/zonebuilders/zonebuilder, https://zonebuilders.github.io/zonebuilder/
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.1.1
RoxygenNote: 7.3.2
3 changes: 2 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Generated by roxygen2: do not edit by hand

S3method(geo_select_aeq,sf)
S3method(geo_select_aeq,sfc)
export(london_a)
export(london_c)
export(zb_color)
Expand All @@ -8,7 +10,6 @@ export(zb_lines)
export(zb_plot)
export(zb_quadrat)
export(zb_segment)
export(zb_view)
export(zb_zone)
import(sf)
importFrom(RColorBrewer,brewer.pal)
Expand Down
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# zonebuilder (development version)
# zonebuilder 0.1.0 (2025-02)

* Various issues fixed for CRAN (#36)
* Removal of `zb_view()` function
* Addition of citation to documentation

# zonebuilder 0.0.2

Expand Down
15 changes: 13 additions & 2 deletions R/from_stplanr.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
#' Azimuthal Equidistant Projection
#'
#' @title Azimuthal Equidistant Projection
#' @name geo_select_aeq
#' @description Returns a CRS string for an Azimuthal Equidistant projection centered on the midpoint of an sf object's coordinates.
#'
#' @param shp An sf object.
#' @return A CRS string for an Azimuthal Equidistant projection.
#' @export
geo_select_aeq.sf = function (shp) {
#cent <- sf::st_geometry(shp)
coords <- sf::st_coordinates(shp)
Expand All @@ -8,7 +17,8 @@ geo_select_aeq.sf = function (shp) {
sf::st_crs(aeqd)
}


#' @rdname geo_select_aeq
#' @export
geo_select_aeq.sfc = function (shp) {
#cent <- sf::st_geometry(shp)
coords <- sf::st_coordinates(shp)
Expand All @@ -19,12 +29,13 @@ geo_select_aeq.sfc = function (shp) {
sf::st_crs(aeqd)
}

#' @rdname geo_select_aeq
geo_select_aeq = function (shp) {
UseMethod("geo_select_aeq")
}


geo_project = function(shp) {
crs = geo_select_aeq(shp)
st_transform(shp, crs = crs)
sf::st_transform(shp, crs = crs)
}
51 changes: 1 addition & 50 deletions R/plot.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,55 +35,6 @@ zb_color = function(z, palette = c("rings", "hcl", "dartboard")) {
}
}



#' View zones
#'
#' This function opens an interactive map of the zones
#'
#' @param z An `sf` object containing zones covering the region
#' @param alpha Alpha transparency, number between 0 (fully transparent) and 1 (not transparent)
#' @param palette Palette type, one of \code{"hcl"} (a palette based on the HCL color space), \code{"rings"} (a palette which colors the rings using the YlOrBr color brewer palette), \code{"dartboard"} (a palette which resembles a dartboard)
#' @param title The title of the plot
#' @return An interactive map created with `tmap`
#' @export
#' @examples
#' \donttest{
#' z = zb_zone(london_c(), london_a())
#' zb_view(z, palette = "rings")
#' }
zb_view = function(z, alpha = 0.4, palette = c("rings", "hcl", "dartboard"), title = NULL) {
palette = match.arg(palette)
if (requireNamespace("tmap")) {
suppressMessages(tmap::tmap_mode("view"))
tmap::tmap_options(show.messages = FALSE)

cent = sf::st_set_crs(sf::st_set_geometry(z, "centroid"), sf::st_crs(z))
check_and_fix = tmap::tmap_options()$check.and.fix
if(!check_and_fix) {
message("Updating tmap settings with:\ntmap::tmap_options(check.and.fix = TRUE)")
tmap::tmap_options(check.and.fix = TRUE)
}

z$color = zb_color(z, palette)
tm = tmap::tm_basemap("OpenStreetMap") +
tmap::tm_shape(z) +
tmap::tm_fill("color", alpha = alpha, id = "label", group = "colors", popup.vars = c("circle_id", "segment_id", "label")) +
tmap::tm_borders(group = "Borders", col = "black", lwd = 1.5) +
tmap::tm_shape(cent) +
tmap::tm_text("label", col = "black", size = "circle_id", group = "Labels") +
tmap::tm_scale_bar()

if (!is.null(title)) {
tm + tmap::tm_layout(title = title)
} else {
tm
}
} else {
stop("Please install tmap")
}
}

#' Plot zones
#'
#' This function opens a static map of the zones
Expand Down Expand Up @@ -113,7 +64,7 @@ zb_plot = function(z, palette = c("rings", "hcl", "dartboard"), title = NULL, te
on.exit(par(oldpar)) # code line i + 1
p = graphics::par(mar=c(.2,.2,.2,.2))
plot(sf::st_geometry(z), col = z$color, border = "grey40")
co = st_coordinates(cent[sel,])
co = sf::st_coordinates(cent[sel,])
mx = max(z$circle_id[sel])
cex = seq(text_size[1], text_size[2], length.out = 9)[pmin(9, z$circle_id[sel] + (9-mx))]
text(co[, 1], co[, 2], cex = cex, labels = z$label[sel])
Expand Down
11 changes: 0 additions & 11 deletions R/zone.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,9 @@
#' @examples
#' # default settings
#' z = zb_zone(london_c(), london_a())
#' \donttest{
#' zb_plot(z)
#' if (require(tmap)) {
#' zb_view(z)
#'
#' z = zb_zone("Berlin")
#' zb_view(z)
#'}
#'
#' # variations
#' zb_plot(zb_zone(london_c(), london_a(), n_circles = 2))
#' zb_plot(zb_zone(london_c(), london_a(), n_circles = 4, distance = 2, distance_growth = 0))
#' zb_plot(zb_zone(london_c(), london_a(), n_circles = 3, n_segments = c(1,4,8)))
#' }
zb_zone = function(x = NULL,
area = NULL,
n_circles = NA,
Expand Down
38 changes: 28 additions & 10 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ knitr::opts_chunk$set(
[![CRAN status](https://www.r-pkg.org/badges/version/zonebuilder)](https://CRAN.R-project.org/package=zonebuilder)
[![CRAN RStudio mirror
downloads](https://cranlogs.r-pkg.org/badges/grand-total/zonebuilder)](https://www.r-pkg.org/pkg/zonebuilder)
[DOI](https://doi.org/10.31219/osf.io/vncgw)
[DOI](https://doi.org/10.5311/JOSIS.2022.24.172)
<!-- badges: end -->

The goal of zonebuilder is to break up large geographic regions such as cities into manageable zones.
Zoning systems are important in many fields, including demographics, economy, health, and transport. The zones have standard configuration, which enabled comparability across cities. See its website at [zonebuilders.github.io/zonebuilder](https://zonebuilders.github.io/zonebuilder/).
Zoning systems are important in many fields, including demographics, economy, health, and transport. The zones have standard configuration, which enabled comparability across cities. See its website at [zonebuilders.github.io/zonebuilder](https://zonebuilders.github.io/zonebuilder/) and the academic paper that describes the package in detail [here (Lovelace et al. 2022)](https://doi.org/10.5311/JOSIS.2022.24.172).

## Installation

Expand All @@ -53,7 +53,11 @@ Attaching the package provides the example datasets `london_a()` and `london_c()
```{r}
library(zonebuilder)
library(tmap)
tm_shape(london_a()) + tm_borders() + tm_shape(london_c()) + tm_dots("red")
tmap_mode("plot")
tm_shape(london_a()) +
tm_borders() +
tm_shape(london_c()) +
tm_dots("red")
```

The main function `zb_zone` breaks this geographical scale into zones. The default settings follow the **ClockBoard** configuration:
Expand Down Expand Up @@ -99,11 +103,25 @@ It may be worth checking-in in a [discussion post](https://github.com/zonebuilde

## Citation

Watch this space.


<!-- tmap_arrange( -->
<!-- zb_view(zb_doughnut(london_c(), london_a(), n_circles = 5), title = "Doughnuts"), -->
<!-- zb_view(zb_segment(london_c(), n_segments = 20), title = "Segments") -->
<!-- ) -->
Please cite the package as follows (Lovelace et al. 2022):

```
@article{lovelace_clockboard_2022,
title = {{{ClockBoard}}: {{A}} Zoning System for Urban Analysis},
shorttitle = {{{ClockBoard}}},
author = {Lovelace, Robin and Tennekes, Martijn and Carlino, Dustin},
date = {2022-06-20},
journaltitle = {Journal of Spatial Information Science},
number = {24},
pages = {63--85},
issn = {1948-660X},
doi = {10.5311/JOSIS.2022.24.172},
url = {https://josis.org/index.php/josis/article/view/172},
urldate = {2022-07-02},
abstract = {Zones are the building blocks of urban analysis. Fields ranging from demographics to transport planning routinely use zones - spatially contiguous areal units that break-up continuous space into discrete chunks - as the foundation for diverse analysis techniques. Key methods such as origin-destination analysis and choropleth mapping rely on zones with appropriate sizes, shapes and coverage. However, existing zoning systems are sub-optimal in many urban analysis contexts, for three main reasons: 1) administrative zoning systems are often based on somewhat arbitrary factors; 2) zoning systems that are evidence-based (e.g., based on equal population size) are often highly variable in size and shape, reducing their utility for inter-city comparison; and 3) official zoning systems in many places simply do not exist or are unavailable. We set out to develop a flexible, open and scalable solution to these problems. The result is the zonebuilder project (with R, Rust and Python implementations), which was used to create the ClockBoard zoning system. ClockBoard consists of 12 segments emanating from a central place and divided by concentric rings with radii that increase in line with the triangular number sequence (1, 3, 6 km etc). 'ClockBoards' thus create a consistent visual frame of reference for monocentric cities that is reminiscent of clocks and a dartboard. This paper outlines the design and potential uses of the ClockBoard zoning system in the historical context, and discusses future avenues for research into the design and assessment of zoning systems.},
issue = {24},
langid = {english},
keywords = {modifiable area unit problem},
file = {C:\Users\georl_admin\Zotero\storage\QRQDMJSH\Lovelace et al. - 2022 - ClockBoard A zoning system for urban analysis.pdf}
}
```
71 changes: 45 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@
# zonebuilder

<!-- badges: start -->

<!-- [![Codecov test coverage](https://codecov.io/gh/zonebuilders/zonebuilder/branch/master/graph/badge.svg)](https://codecov.io/gh/zonebuilders/zonebuilder?branch=master) -->

[![R-CMD-check](https://github.com/zonebuilders/zonebuilder/workflows/R-CMD-check/badge.svg)](https://github.com/zonebuilders/zonebuilder/actions)
[![CRAN
status](https://www.r-pkg.org/badges/version/zonebuilder)](https://CRAN.R-project.org/package=zonebuilder)
[![CRAN RStudio mirror
downloads](https://cranlogs.r-pkg.org/badges/grand-total/zonebuilder)](https://www.r-pkg.org/pkg/zonebuilder)
[DOI](https://doi.org/10.31219/osf.io/vncgw) <!-- badges: end -->
[DOI](https://doi.org/10.5311/JOSIS.2022.24.172) <!-- badges: end -->

The goal of zonebuilder is to break up large geographic regions such as
cities into manageable zones. Zoning systems are important in many
fields, including demographics, economy, health, and transport. The
zones have standard configuration, which enabled comparability across
cities. See its website at
[zonebuilders.github.io/zonebuilder](https://zonebuilders.github.io/zonebuilder/).
[zonebuilders.github.io/zonebuilder](https://zonebuilders.github.io/zonebuilder/)
and the academic paper that describes the package in detail [here
(Lovelace et al. 2022)](https://doi.org/10.5311/JOSIS.2022.24.172).

## Installation

Expand Down Expand Up @@ -47,7 +50,11 @@ geographic boundary and the centre of London:
``` r
library(zonebuilder)
library(tmap)
tm_shape(london_a()) + tm_borders() + tm_shape(london_c()) + tm_dots("red")
tmap_mode("plot")
tm_shape(london_a()) +
tm_borders() +
tm_shape(london_c()) +
tm_dots("red")
```

<img src="man/figures/README-unnamed-chunk-3-1.png" width="100%" />
Expand All @@ -64,22 +71,21 @@ zb_plot(london_zones)

The idea behind this zoning system is based on the following principles:

- Most cities have a centre, the ‘heart’ of the city. Therefore, the
zones are distributed around the centre.
- Typically, the population is much denser in and around the centre
and also the traffic intensity is higher. Therefore, the zones are
smaller in and around the centre.
- The rings (so A, B, C, D, etc) reflect the proximity to the centre
point. The distances from the outer borders of the rings A, B, C, D,
etc. follow the triangular number sequence 1, 3, 6, 10, etc. This
means that in everyday life use, within zone A everything is in
walking distance, from ring B to the centre requires a bike, from
zone C and further to the centre typically requires public
transport.
- Regarding direction relative to the centre, we use the clock
analogy, since most people are familiar with that. So each ring
(annuli) is divided into 12 segments, where segment 12 is directed
at 12:00, segment 1 at 1:00 etc.
- Most cities have a centre, the ‘heart’ of the city. Therefore, the
zones are distributed around the centre.
- Typically, the population is much denser in and around the centre and
also the traffic intensity is higher. Therefore, the zones are smaller
in and around the centre.
- The rings (so A, B, C, D, etc) reflect the proximity to the centre
point. The distances from the outer borders of the rings A, B, C, D,
etc. follow the triangular number sequence 1, 3, 6, 10, etc. This
means that in everyday life use, within zone A everything is in
walking distance, from ring B to the centre requires a bike, from zone
C and further to the centre typically requires public transport.
- Regarding direction relative to the centre, we use the clock analogy,
since most people are familiar with that. So each ring (annuli) is
divided into 12 segments, where segment 12 is directed at 12:00,
segment 1 at 1:00 etc.

The package `zonebuilder` does not only create zoning systems based on
the CloadBoard layout as illustrated below.
Expand Down Expand Up @@ -126,10 +132,23 @@ opening an issue.

## Citation

Watch this space.

<!-- tmap_arrange( -->
<!-- zb_view(zb_doughnut(london_c(), london_a(), n_circles = 5), title = "Doughnuts"), -->
<!-- zb_view(zb_segment(london_c(), n_segments = 20), title = "Segments") -->
<!-- ) -->

Please cite the package as follows (Lovelace et al. 2022):

@article{lovelace_clockboard_2022,
title = {{{ClockBoard}}: {{A}} Zoning System for Urban Analysis},
shorttitle = {{{ClockBoard}}},
author = {Lovelace, Robin and Tennekes, Martijn and Carlino, Dustin},
date = {2022-06-20},
journaltitle = {Journal of Spatial Information Science},
number = {24},
pages = {63--85},
issn = {1948-660X},
doi = {10.5311/JOSIS.2022.24.172},
url = {https://josis.org/index.php/josis/article/view/172},
urldate = {2022-07-02},
abstract = {Zones are the building blocks of urban analysis. Fields ranging from demographics to transport planning routinely use zones - spatially contiguous areal units that break-up continuous space into discrete chunks - as the foundation for diverse analysis techniques. Key methods such as origin-destination analysis and choropleth mapping rely on zones with appropriate sizes, shapes and coverage. However, existing zoning systems are sub-optimal in many urban analysis contexts, for three main reasons: 1) administrative zoning systems are often based on somewhat arbitrary factors; 2) zoning systems that are evidence-based (e.g., based on equal population size) are often highly variable in size and shape, reducing their utility for inter-city comparison; and 3) official zoning systems in many places simply do not exist or are unavailable. We set out to develop a flexible, open and scalable solution to these problems. The result is the zonebuilder project (with R, Rust and Python implementations), which was used to create the ClockBoard zoning system. ClockBoard consists of 12 segments emanating from a central place and divided by concentric rings with radii that increase in line with the triangular number sequence (1, 3, 6 km etc). 'ClockBoards' thus create a consistent visual frame of reference for monocentric cities that is reminiscent of clocks and a dartboard. This paper outlines the design and potential uses of the ClockBoard zoning system in the historical context, and discusses future avenues for research into the design and assessment of zoning systems.},
issue = {24},
langid = {english},
keywords = {modifiable area unit problem},
file = {C:\Users\georl_admin\Zotero\storage\QRQDMJSH\Lovelace et al. - 2022 - ClockBoard A zoning system for urban analysis.pdf}
}
4 changes: 3 additions & 1 deletion cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Resubmitting after fixes to enable the package to work with sf 1.0-1 and beyond.
Many updates enabling tests to pass on CRAN, after the package was removed due to failing tests.

I have fixed broken URLs since last submission.

## Test environments
* local R installation, R 4.1.0
Expand Down
3 changes: 0 additions & 3 deletions data-raw/fix-polygons.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ qtm(sf::st_make_valid(z))
tmap_options(check.and.fix = TRUE)
qtm(z)

zb_view(z)


lnd_a = zonebuilder::london_a()
sf::st_is_valid(lnd_a)
sf::st_is_valid(london_c())
Expand Down
Binary file modified man/figures/README-unnamed-chunk-3-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-4-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-5-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-5-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-5-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-6-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading