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

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 3)
has_ggplot <- requireNamespace("ggplot2", quietly = TRUE)
```

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

How ordered is a city's street grid? Following Boeing (2019, 2025), `osmnxr`
measures this with the **compass bearing** of every street and the **Shannon
entropy** of their distribution: low entropy for a rigid gridiron, high entropy
for an organic, winding network.

## A real first network

`ox_example("olinda")` loads a small real network (the historic centre of
Olinda, Brazil) bundled with the package, so this runs without network access:

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

```{r, eval = has_ggplot}
ox_plot_orientation(g, title = "Olinda")
```

Olinda's colonial street pattern is irregular, so its rose plot points in many
directions and its entropy is high.

## Comparing cities

The package bundles the bearings of three cities that span the spectrum —
the same comparison as Figure 2 of Boeing (2025). These are real bearings,
sampled from each city's drivable network:

```{r}
cities <- readRDS(system.file("extdata", "city_orientations.rds", package = "osmnxr"))
ent <- tapply(cities$bearing, cities$city, ox_orientation_entropy)
round(ent, 3)
```

Chicago's relentless grid gives the lowest entropy; New Orleans, bending along
the Mississippi, sits in the middle; Rome's ancient organic core is highest —
near the theoretical maximum of `log(36) =` `r round(log(36), 2)`.

```{r orientation-roses, eval = has_ggplot, fig.height = 3}
library(ggplot2)

bins <- 36; bw <- 360 / bins
cities$sector <- (floor((cities$bearing %% 360) / bw) + 0.5) * bw
counts <- as.data.frame(table(city = cities$city, sector = cities$sector))
counts$sector <- as.numeric(as.character(counts$sector))

ggplot(counts, aes(sector, Freq)) +
  geom_col(width = bw, fill = "#0d3b66", colour = "white", linewidth = 0.1) +
  coord_polar(start = 0) +
  scale_x_continuous(limits = c(0, 360), breaks = seq(0, 315, 45),
                     labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")) +
  facet_wrap(~ city) +
  labs(x = NULL, y = NULL,
       title = "Street orientation: ordered (Chicago) to organic (Rome)") +
  theme_minimal(base_size = 9) +
  theme(axis.text.y = element_blank(), panel.grid.minor = element_blank())
```

## On your own city

With network access, compute this for any place straight from OpenStreetMap:

```{r, eval = FALSE}
g <- ox_graph_from_place("Manhattan, New York, USA", network_type = "drive") |>
  ox_simplify()
ox_orientation_entropy(g) # low: a famous grid
ox_plot_orientation(g, title = "Manhattan")
```

## References

Boeing, G. (2019). Urban spatial order: street network orientation,
configuration, and entropy. *Applied Network Science* 4(1).

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