Skip to content

Instantly share code, notes, and snippets.

@marcosci
Created May 22, 2023 16:39
Show Gist options
  • Save marcosci/57430ec059f9cc91bb5da6c5d13539bd to your computer and use it in GitHub Desktop.
Save marcosci/57430ec059f9cc91bb5da6c5d13539bd to your computer and use it in GitHub Desktop.
# load libraries
library(units)
library(tidyverse)
library(osmdata)
library(sf)
library(ggtext)
library(exactextractr)
library(fasterize)
library(ggtext)
library(tidygeocoder)
library(glue)
library(purrr)
library(geosphere)
library(classInt)
library(patchwork)
library(glue)
sf::sf_use_s2(TRUE)
#epsg <- 32632
epsg <- 4326
country <- 'germany'
aoi_citys <- c('Berlin, Germany',
'Hamburg⁠, Germany',
'München, Germany',
'Köln, Germany',
'Frankfurt, Germany',
'Stuttgart, Germany',
'Kiel, Germany',
'Leipzig, Germany',
'Dortmund, Germany')
figureground <- map_dfr(aoi_citys, function(aoi_city){
city <- tidygeocoder::geo(aoi_city) %>%
st_as_sf(coords = c("long", "lat"), crs = 4326) %>%
st_transform(epsg)
buildings <- getbb(aoi_city)%>%
opq(timeout = 100)%>%
add_osm_feature(key = "building",
value = c("apartments",
"detached",
"dormitory",
"farm",
"hotel",
"house",
"residential",
"semidetached_house"
)) %>%
osmdata_sf()
buildings_sf <- buildings$osm_polygons %>%
st_transform(epsg)
crop_buffer <- st_buffer(city, 7500)
buildings_sf <- st_crop(buildings_sf, crop_buffer)
buildings_sf <- st_intersection(buildings_sf, crop_buffer)
buildings_area <- as.numeric(sum(st_area(buildings_sf)))
buffer_area <- as.numeric(sum(st_area(crop_buffer))) - buildings_area
total_area <- as.numeric(sum(st_area(crop_buffer)))
df <- tibble(x = c(1, 2),
type = c("Void", "Solid"),
city = rep(factor(aoi_city), 2),
count = c(buffer_area, buildings_area)) |>
mutate(count = as.numeric(count))
circleFun <- function(center=c(0,0), diameter=1, npoints=500, start=0, end=2, type, aoi, coverage_figure = NA, coverage_ground = NA)
{
tt <- seq(start*pi, end*pi, length.out=npoints)
data.frame(x = center[1] + diameter / 2 * cos(tt),
y = center[2] + diameter / 2 * sin(tt),
type = type,
aoi = aoi,
coverage_figure = coverage_figure,
coverage_ground = coverage_ground)
}
half_circles_solid <- circleFun(c(0,7.625),
sqrt(buildings_area),
start=0.5,
end=1.5,
type = "Solid",
aoi = aoi_city,
coverage_figure = round(buildings_area / total_area * 100, 2))
half_circles_void <- circleFun(c(0,7.625),
sqrt(buffer_area),
start=1.5,
end=2.5,
type = "Void",
aoi = aoi_city,
coverage_ground = round(buffer_area / total_area * 100, 2))
rbind(half_circles_solid,
half_circles_void)
})
figureground |>
arrange(aoi) |>
ggplot() +
geom_polygon(aes(x,y, fill = type)) +
scale_fill_manual(values = c("#ad9a8c", "#f1eeeb")) +
facet_wrap(vars(aoi)) +
scale_x_continuous(expand = expansion(mult = c(0.1, .1))) +
# annotate("richtext",
# x = -4000,
# y = 250,
# label.color = NA,
# fill = NA,
# hjust = 0.5,
# label = glue("<span style='text-align: center;'><b style = 'font-size:16pt; font-weight: 100;'>{coverage_ground} %</b> <br> Solid</span>")) +
# annotate("richtext",
# x = 8000,
# y = 250,
# label.color = NA,
# fill = NA,
# hjust = 0.5,
# label = glue("<span style='text-align: center;'><b style = 'font-size:16pt; font-weight: 100;'>{coverage_figure} %</b> <br> Void</span>")) +
coord_equal() +
theme_void() +
theme(legend.position = "none",
panel.spacing.y = unit(1, "lines"),
#plot.margin = margin(2, 2, 2, 2, "cm"),
strip.text.x = element_text(size = 9, face = "bold"),
text = element_text(family="West"))
wrapper <- function(label, dev_width = dev.size("in")[1], dev_scaler = 18) {
paste(strwrap(label, dev_width * dev_scaler), collapse = "\n")
}
figureground |>
arrange(aoi) |>
ggplot() +
geom_polygon(aes(x,y, fill = type)) +
scale_fill_manual(values = c("#ad9a8c", "#f1eeeb")) +
facet_wrap(vars(aoi)) +
scale_x_continuous(expand = expansion(mult = c(0.1, .1))) +
guides(fill = guide_legend(keyheight = unit(1, units = "mm"),
keywidth = unit(5, units = "mm"),
direction = "horizontal",
nrow = 1,
ticks.colour = "white",
label.position = "bottom",
title.position = "bottom",
title.hjust = 0.5)) +
coord_equal() +
theme_void() +
labs(title = "Figure Ground",
subtitle = "The figure-ground diagram serves as a mapping technique that showcases the \n correlation between developed and undeveloped areas within urban environments. \n This method visually represents the land occupied by buildings as a solid mass or 'figure', \n while the open spaces, including streets, parks, and plazas, are depicted as voids or ground. \n Here, we look at the 9 biggest German cities.",
caption = "Data: OSM | Visualisation: Marco Sciaini",
fill='') +
theme(legend.direction="horizontal",
legend.position="bottom",
legend.box = "vertical",
panel.spacing.y = unit(1, "lines"),
plot.title = element_text(size = 18,
colour = '#171717',
hjust = 0.5,
margin = margin(.3,0,.5,-2, "cm")),
plot.subtitle = element_text(size = 9,
colour = '#171717',
hjust = 0.5,
margin = margin(.3,0,.5,-2, "cm"),
lineheight = 1.3),
plot.caption = element_text(size = 6,
colour = '#171717',
margin = margin(.3,-2,.3,0, "cm")),
strip.text.x = element_text(size = 7, face = "bold"),
text = element_text(family="West"))
ggsave("single.png", width = 9, height = 16, dpi = 600)
figureground_sf <- map(aoi_citys, function(aoi_city){
city <- tidygeocoder::geo(aoi_city) %>%
st_as_sf(coords = c("long", "lat"), crs = 4326) %>%
st_transform(epsg)
buildings <- getbb(aoi_city)%>%
opq(timeout = 100)%>%
add_osm_feature(key = "building",
value = c("apartments",
"detached",
"dormitory",
"farm",
"hotel",
"house",
"residential",
"semidetached_house"
)) %>%
osmdata_sf()
buildings_sf <- buildings$osm_polygons %>%
st_transform(epsg)
crop_buffer <- st_buffer(city, 7500)
buildings_sf <- st_crop(buildings_sf, crop_buffer)
buildings_sf <- st_intersection(buildings_sf, crop_buffer)
list(buildings_sf, crop_buffer)
})
street_plot <- ggplot() +
geom_sf(data = figureground_sf[[1]][[2]], color = "#f1eeeb", fill = "#f1eeeb", lwd = .25, alpha = 0.8) +
geom_sf(data = figureground_sf[[1]][[1]], color = "#ad9a8c", lwd = .15, alpha = 0.6) +
theme_void()
street_plot
n_buildings <- nrow(figureground_sf[[1]][[1]])
coverage_figure <- figureground |>
filter(aoi == "Berlin, Germany") |>
pull(coverage_figure) |>
unique() |>
na.omit()
coverage_ground <- figureground |>
filter(aoi == "Berlin, Germany") |>
pull(coverage_ground) |>
unique() |>
na.omit()
circle_plot <- figureground |>
filter(aoi == "Berlin, Germany") |>
ggplot() +
geom_polygon(aes(x,y, fill = type)) +
scale_fill_manual(values = c("#ad9a8c", "#f1eeeb")) +
scale_x_continuous(expand = expansion(mult = c(0.14, .14))) +
guides(fill = guide_legend(keyheight = unit(1, units = "mm"),
keywidth = unit(5, units = "mm"),
direction = "horizontal",
nrow = 1,
ticks.colour = "white",
label.position = "bottom",
title.position = "bottom",
title.hjust = 0.5)) +
coord_equal() +
theme_void() +
labs(#title = glue("{aoi_citys[1]} | {n_buildings} Buildings"),
caption = "Data: OSM | Visualisation: Marco Sciaini",
fill='') +
annotate("richtext",
x = -3000,
y = 250,
label.color = NA,
fill = NA,
hjust = 0.5,
label = glue("<span style='text-align: center;'><b style = 'font-size:16pt; font-weight: 100;'>{coverage_figure} %</b> <br> Solid</span>")) +
annotate("richtext",
x = 7200,
y = 250,
label.color = NA,
fill = NA,
hjust = 0.5,
label = glue("<span style='text-align: center;'><b style = 'font-size:16pt; font-weight: 100;'>{coverage_ground} %</b> <br> Void</span>")) +
theme(legend.direction="horizontal",
legend.position="bottom",
legend.box = "vertical",
panel.spacing.y = unit(1, "lines"),
plot.title = element_text(size = 18,
colour = '#171717',
hjust = 0.5,
margin = margin(.3,0,.5,-2, "cm")),
plot.subtitle = element_text(size = 9,
colour = '#171717',
hjust = 0.5,
margin = margin(.3,0,.5,-2, "cm"),
lineheight = 1.3),
plot.caption = element_text(size = 12,
colour = '#171717',
margin = margin(.3,-2,.3,0, "cm")),
strip.text.x = element_text(size = 7, face = "bold"),
text = element_text(family="West"))
street_plot + circle_plot + plot_annotation(
title = glue("{aoi_citys[1]} | {n_buildings} Buildings"),
theme = theme( plot.title = element_text(size = 18,
face = "bold",
colour = '#171717',
hjust = 0.5,
margin = margin(.3,0,.5,-2, "cm")))
)
ggsave("both.png", width = 16, height = 9, dpi = 600)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment