Lessons learned making bad map projections

David O’Sullivan

Geospatial Stuff

University of Auckland

More specifically…

XKCD bad map projections

xkcd.com is “a webcomic of romance, sarcasm, math, and language.”

All cartoons are Creative Commons licensed

The artist is Randall Munroe, previously a NASA engineer, but working full time on the comic since 2006

A significant visualization thread

XKCD 256 Online Communities

XKCD 802 Online Communities 2

XKCD 657 Movie Narrative Charts

A significant geographical thread

XKCD 503 Terminology

XKCD 1472 Geography

So inevitably…

XKCD 977 Map Projections

And so to XKCD bad map projections

XKCD 1500 Upside Down Map

Ten more bad map projections since

Lesson 1: Sometimes, you need a drawing package

XKCD 1784 Bad Map Projection: Liquid Resize

XKCD 1799 Bad Map Projection: Time Zones

XKCD 2256 Bad Map Projection: South America

XKCD 2999 Bad Map Projection: The United Stralia

Lesson 2: Sometimes geometry is enough, until it’s not

XKCD 2807 Bad Map Projection Abs(Longitude)

get_hemisphere <- function(central_meridian = 0, density = 1) {
  lons <- c( 1,  1, -1, -1,  1) * 90 + central_meridian
  lats <- c(-1,  1,  1, -1, -1) * 90
  st_polygon(list(matrix(c(lons, lats), ncol = 2))) |>
    st_sfc() |>
    as.data.frame() |>
    st_as_sf(crs = 4326) |>
    smoothr::densify(density)
}
hemi_w <- get_hemisphere(-90)
hemi_e <- get_hemisphere(90)

world_w <- World |>
  st_intersection(hemi_w) |>
  mutate(geometry = geometry * matrix(c(-1, 0, 0, 1), 2, 2)) |>
  st_set_crs(4326)

world_e <- World |>
  st_intersection(hemi_e)

world_abs <- world_w |>
  bind_rows(world_e) |>
  mutate(id = 1) |>
  group_by(id) |>
  summarise() |>
  mutate(geometry = geometry - c(90, 0)) |>
  st_set_crs(4326) |>
  st_transform("+proj=eqearth")

XKCD 1500 Upside-Down Map

world_upside_down <- World |>
  mutate(
    geometry = geometry * diag(c(-1, 2, 2))) |>
  st_set_crs(4326) |>
  st_transform("+proj=eqearth")

ggplot(world_upside_down) +
  geom_sf() +
  theme_minimal()

Supplementary lesson

Sometimes, you have to lie about your data’s projection

Lesson 3: Mercator is more useful than you think, and never not funny

XKCD 2489 Bad Map Projection: The Greenland Special

greenland <- World |>
  filter(name == "Greenland") |>
  st_transform("+proj=merc") |>
  mutate(geometry = 
    (geometry + c(2e6, -3.1e6)) * diag(1, 2, 2) * 0.85) |>
  st_set_crs("+proj=merc")

greenland_buffer <- greenland |>
  st_buffer(1e5)

w <- World |>
  st_transform("+proj=moll") |>
  st_make_valid() |>
  st_set_crs("+proj=merc") |>
  st_difference(greenland_buffer) |>
  bind_rows(greenland)

XKCD 2613 Bad Map Projection: Madagascator

ll <- c(-4.595750619515433, 55.43837198904654)
madagascator <- World |>
  st_transform(str_glue("+proj=laea +lon_0={ll[2]} +lat_0={ll[1]}")) |>
  st_set_crs("+proj=laea +lon_0=150 +lat_0=90") |>
  st_transform("+proj=merc")

Supplementary lessons

Azimuthal projections are your friend

Antarctica is a menace: sometimes you just have to ditch it

Lesson 4: If a job’s worth doing, it’s worth doing well, unless it’s not

XKCD 2951 Bad Map Projection: Exterior Kansas

XKCD 3122 Bad Map Projection: Interrupted Spheres

XKCD 3207 Bad Map Projection: Zero Declination

Lessons learned

Sometimes, you need a drawing package

Sometimes geometry is enough, until it’s not

Mercator is more useful than you think, and never not funny

If a job’s worth doing, it’s worth doing well, unless it’s not

Sometimes, you have to lie about your data’s projection

Azimuthal projections are your friend

Antarctica is a menace: sometimes you just have to ditch it

Finally

All projections are wrong…

…some are amusing

geospatialstuff.com/blog.html#category=xkcd