Visualization "Building taxonomy"

Simplified building taxonomy of selected cities

Table of contents

What is this about?

A small-multiple grid of simplified building outlines for selected cities, built with PyData, QuackOSM, and Metaflow from OpenStreetMap geometries.

#30DayMapChallenge | Day 3: Polygons | 2024 (see: ⁠"30DayMapChallenge" official Github repo)

Recently I saw a post by Daniel Gorokhov who illustrated building taxonomy of "interesting buildings" in Milano, Italy, Stockholm, Sweden and Amsterdam, Netherlands. Here is my extension for that post, with some more cities, mostly in USA, but also in Europe.

Chart type is "small multiple" (a.k.a. "grid chart"). How was it made? I run a script that loaded all mapped buildings within city area and counted exterior vertices (nodes) for all of them. Still, I did not explicitly count inner polygons, like courtyards or patios. Then, I took one hundred of buildings with the most nodes to plot them.

  1. Yet, it happened that under current methodology, quite often, "interesting" buildings are repetitive because of construction nature (for example - neighborhoods of apartment buildings or high-rise housing projects; industrial structures, like water treatment ponds, fuel storages, dockside cranes)
  2. Yet, it happened that under current methodology, quite often, "interesting" buildings are repetitive because of construction nature (for example - neighborhoods of apartment buildings or high-rise housing projects; industrial structures, like water treatment ponds, fuel storages, dockside cranes)

Made with #Python
Data: #OSM, #OpenStreetMap retrieved with QuackOSM
#dataviz #datavisualization

How to read this?

The chart is a small multiple (grid chart). Each city is one panel. Inside each panel, the 100 buildings with the most exterior vertices are drawn as simplified outlines.

Complexity here means vertex count on the exterior ring, not architectural fame. Courtyards and other inner rings are not counted explicitly. Under this rule, "interesting" shapes often repeat: housing projects, industrial ponds, fuel storages, dockside structures, and similar construction patterns. Some truly complex buildings are also poorly mapped in OSM and need case-by-case handling (multi-buildings, connections, and similar edge cases).

Why did I make it?

I wanted to extend Daniel Gorokhov's Milano / Stockholm / Amsterdam taxonomy idea to a wider city set for #30DayMapChallenge Day 3 (Polygons), and to keep the pipeline reproducible in Python rather than as a one-off illustration.

What's under the hood?

Pipeline sketch: load OSM buildings for each city with QuackOSM, count exterior vertices, keep the top 100 per city, plot the small multiples with Matplotlib, orchestrated in Metaflow.

How-to: make this chart
Click or tap to open section
★ Click to see code snippets
python
import metaflow
  from metaflow import FlowSpec, Parameter, JSONType, step, NBRunner, pypi

  import quackosm as qosm

  import time
  import datetime

  import numpy as np
  import geopandas as gpd
  import matplotlib
  import matplotlib.pyplot as plt
Pipeline sketch (Metaflow)
python
def _func_count_vertices(row_index, row_values_series):
    """
        * https://gis.stackexchange.com/questions/328884/counting-number-of-vertices-in-geopandas
        * https://gis.stackexchange.com/questions/388606/counting-vertices-and-adding-it-as-number-to-column-using-shapely
    """
    geometry = row_values_series.geometry
    geom_type = geometry.geom_type

    n_vertices = 0
    #try:
    if geom_type == "Polygon":
        n_vertices = len(geometry.exterior.coords)
    elif geom_type == "MultiPolygon":
        for inner_geometry in list(geometry.geoms):
            n_vertices += len(inner_geometry.exterior.coords)
    else:
        None
        #print("- Other type of geometry: ", geom_type, row_index)
    #except:
        #print("- There was unexpected error with row: ", row_index)

    return n_vertices
Pipeline sketch (Metaflow)
python
def _func_count_vertices(row_index, row_values_series):
    """
        * https://gis.stackexchange.com/questions/328884/counting-number-of-vertices-in-geopandas
        * https://gis.stackexchange.com/questions/388606/counting-vertices-and-adding-it-as-number-to-column-using-shapely
    """
    geometry = row_values_series.geometry
    geom_type = geometry.geom_type

    n_vertices = 0
    #try:
    if geom_type == "Polygon":
        n_vertices = len(geometry.exterior.coords)
    elif geom_type == "MultiPolygon":
        for inner_geometry in list(geometry.geoms):
            n_vertices += len(inner_geometry.exterior.coords)
    else:
        None
        #print("- Other type of geometry: ", geom_type, row_index)
    #except:
        #print("- There was unexpected error with row: ", row_index)

    return n_vertices
Pipeline sketch (Metaflow)
python
def _func_count_vertices(row_index, row_values_series):
    """
        * https://gis.stackexchange.com/questions/328884/counting-number-of-vertices-in-geopandas
        * https://gis.stackexchange.com/questions/388606/counting-vertices-and-adding-it-as-number-to-column-using-shapely
    """
    geometry = row_values_series.geometry
    geom_type = geometry.geom_type

    n_vertices = 0
    #try:
    if geom_type == "Polygon":
        n_vertices = len(geometry.exterior.coords)
    elif geom_type == "MultiPolygon":
        for inner_geometry in list(geometry.geoms):
            n_vertices += len(inner_geometry.exterior.coords)
    else:
        None
        #print("- Other type of geometry: ", geom_type, row_index)
    #except:
        #print("- There was unexpected error with row: ", row_index)

    return n_vertices

How to cite

For human-readable attribution, please cite this work as:

Visualization "Building taxonomy" (2024), Vitaliy Yevtushenko (Witold's Data Consulting). https://witold1.github.io/portfolio/blog/viz-building-taxonomy/.

BibTeX

@misc{witold_blog_viz-building-taxonomy,
  author = {Vitaliy Yevtushenko},
  title = {{Visualization "Building taxonomy"}},
  year = {2024},
  url = {https://witold1.github.io/portfolio/blog/viz-building-taxonomy/},
}
Discuss with AI
PerplexityChatGPTClaudeGemini
Share