---
title: "Urban metrics"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Urban metrics}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 6.5, fig.height = 5.5)
```

```{r setup}
library(osmnxr)
```

`osmnxr` summarises a street network with the geometric and topological
measures used in urban morphology (Boeing 2025). We use a bundled real network —
the centre of Olinda, Brazil — so everything here runs offline.

```{r}
g <- ox_example("olinda")
g
```

## Basic statistics

```{r}
ox_basic_stats(g)
```

The pieces of this summary are standard urban indicators:

- **`n_nodes` / `n_edges`** — intersections and street segments. Intersection
  density (nodes per km²) is the most common measure of network "grain".
- **`mean_length`** — average street segment length, a proxy for block size.
- **`total_length`** — total street length; divide by area for street density.
- **`circuity`** — how much streets deviate from straight lines.

```{r}
area_km2 <- as.numeric(sf::st_area(sf::st_convex_hull(sf::st_union(g$nodes)))) / 1e6
n_intersections <- sum(g$nodes$osmid %in% c(g$edges$u, g$edges$v))
n_intersections / area_km2 # intersections per km^2
```

## Circuity

Circuity is total street length over straight-line distance between segment
endpoints. A value near `1` means straight streets; higher means more winding:

```{r}
ox_circuity(g)
```

## Centrality: finding chokepoints

Betweenness centrality counts the share of shortest paths passing through each
node. Its maximum highlights structural chokepoints — "a bridge connecting a
city's halves" (Boeing & Ha 2024) — that are single points of failure for
mobility and resilience.

```{r}
ct <- ox_centrality(g, type = "betweenness", normalized = TRUE)
ct[order(-ct$betweenness), ][1:5, ]
```

Map it: the darkest, largest nodes carry the most through-traffic.

```{r}
nodes <- g$nodes
nodes$betweenness <- ct$betweenness[match(nodes$osmid, ct$osmid)]
plot(g, col = "grey80", lwd = 0.6)
plot(nodes["betweenness"], pch = 19,
     cex = 0.4 + 4 * nodes$betweenness / max(nodes$betweenness),
     pal = function(n) hcl.colors(n, "YlOrRd", rev = TRUE), add = TRUE)
```

The high-betweenness nodes trace the through-routes that hold the network
together — exactly the junctions a planner would protect or reinforce.

## References

Boeing, G. (2025). Modeling and analyzing urban networks and amenities with
OSMnx. *Geographical Analysis*.

Boeing, G., & Ha, J. (2024). Resilient by design: simulating street network
disruptions across every urban area in the world. *Transportation Research
Part A*.
