Skip to content

Instantly share code, notes, and snippets.

@andrewheiss
Created September 17, 2025 04:14
Show Gist options
  • Save andrewheiss/f01ed91e160f15c0b513d04897cff2dd to your computer and use it in GitHub Desktop.
Save andrewheiss/f01ed91e160f15c0b513d04897cff2dd to your computer and use it in GitHub Desktop.
library(tidyverse)
library(sf)
library(rnaturalearth)
# World map
world <- ne_countries(scale = "medium") |>
filter(adm0_a3 != "ATA") |>
st_transform(crs = "+proj=merc")
# The center of the map is off the coast of Sardegna
center <- c(10, 40)
# Transform center to Mercator coordinates
center_merc <- st_point(center) |>
st_sfc(crs = 4326) |>
st_transform(crs = "+proj=merc") |>
st_coordinates() |>
as.numeric()
# Make straight lines in Mercator projection
make_line_mercator <- function(angle, npts = 200, length = 50000000) { # length in meters
x_coords <- seq(
center_merc[1],
center_merc[1] + length * cos(angle * pi / 180),
length.out = npts
)
y_coords <- seq(
center_merc[2],
center_merc[2] + length * sin(angle * pi / 180),
length.out = npts
)
st_linestring(cbind(x_coords, y_coords))
}
# The C angle in the original is ≈34° and B is ≈56°, so we build the angles
# counterclockwise from C
first_slice <- 34
angles <- c(
0,
first_slice,
90,
180 - first_slice,
180,
180 + first_slice,
270,
360 - first_slice
)
# Make the actual lines
lines <- angles |>
map(make_line_mercator) |>
st_sfc(crs = "+proj=merc") |>
st_as_sf()
# Crop lines to world boundaries
lines_cropped <- st_crop(lines, st_bbox(world))
# Find the angles in between each of the main angles
mid_angles <- map2_dbl(
angles,
lead(angles, default = angles[1] + 360),
\(x, y) (x + y) / 2
)
# Get the midpoint coordinates in Mercator projection
# Distance is in meters
midpoint_coord_mercator <- function(angle, distance = 5000000) {
x <- center_merc[1] + distance * cos(angle * pi / 180)
y <- center_merc[2] + distance * sin(angle * pi / 180)
tibble(x = x, y = y, angle = angle)
}
# Make a dataframe of all the midpoints
midpoints <- map(mid_angles, midpoint_coord_mercator) |>
list_rbind() |>
mutate(label = c("C", "B", "A", "H", "G", "F", "E", "D")) |>
st_as_sf(coords = c("x", "y"), crs = "+proj=merc")
# Finaly plot these things!
map_thing <- ggplot() +
geom_sf(data = world, fill = "grey60", color = "white") +
geom_sf(data = lines_cropped, color = "red", linewidth = 0.5) +
geom_sf_text(
data = midpoints,
aes(label = label),
size = 6,
color = "blue",
fontface = "bold"
) +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
map_thing +
labs(title = "Original Mercator slices") +
coord_sf(crs = "+proj=merc")
map_thing +
labs(title = "Slices in the Robinson projection") +
coord_sf(crs = "+proj=robin")
map_thing +
labs(title = "Slices in the Equal Earth projection") +
coord_sf(crs = "+proj=eqearth")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment