Created
May 22, 2023 16:39
-
-
Save marcosci/57430ec059f9cc91bb5da6c5d13539bd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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