What would happen if we peeled the Earth like an orange? The interrupted Goode homolosine projection gives us something close to that! This equal-area projection preserves relative areas while splitting the world map into lobes. Add a few shades of orange and our world is ready to peel.
Let’s make it with sf , giscoR and ggplot2. First, we get the coastlines and draw the outline, following the cuts between the lobes.
library(sf)
library(ggplot2)
library(giscoR)
library(showtext)
world <- gisco_get_coastal_lines(resolution = 10)
goode_crs <- "+proj=igh"
lat <- c(90:-90, rep(c(-90:0, 0:-90), 3), -90:90, 90:0, 0:90, 90)
lon <- c(
rep(180, 181),
rep(c(80.01, 79.99, -19.99, -20.01, -99.99, -100.01), each = 91),
rep(-180, 181),
rep(c(-40.01, -39.99), each = 91),
180
)
outline <- st_sfc(st_polygon(list(cbind(lon, lat))), crs = 4326) |>
st_transform(goode_crs)
rectangle <- st_as_sfc(st_bbox(outline) * 1.1)
mask <- st_difference(rectangle, outline)
Next, we draw the meridians and parallels within each lobe so that they do not connect across the cuts.
lobes <- list(
c(-180, -40, 0, 90), c(-40, 180, 0, 90),
c(-180, -100, -90, 0), c(-100, -20, -90, 0),
c(-20, 80, -90, 0), c(80, 180, -90, 0)
)
lines <- lapply(lobes, function(b) {
west <- b[1] + 0.01
east <- b[2] - 0.01
south <- max(b[3], -89.99)
north <- min(b[4], 89.99)
meridians <- seq(-180, 180, 30)
meridians <- meridians[meridians > west & meridians < east]
parallels <- seq(-60, 60, 30)
parallels <- parallels[parallels >= south & parallels <= north]
c(
lapply(meridians, function(x) {
st_linestring(cbind(x, seq(south, north, length.out = 181)))
}),
lapply(parallels, function(y) {
st_linestring(cbind(seq(west, east, length.out = 361), y))
})
)
})
grat <- st_sfc(do.call(c, lines), crs = 4326) |>
st_transform(goode_crs)
Finally, we add the orange palette. The mask hides anything outside the outline and keeps the edges of our peel tidy.
font_add_google("Coiny", family = "coiny")
showtext_auto()
ggplot() +
geom_sf(data = outline, fill = "#FFF0D9", colour = NA) +
geom_sf(data = world, fill = "#F9B566", colour = "#B34D08", linewidth = 0.25) +
geom_sf(data = grat, fill = NA, colour = "#E8A45B", linewidth = 0.25) +
geom_sf(data = mask, fill = "#fcf1e7", colour = NA) +
geom_sf(data = outline, fill = NA, colour = "#E87516", linewidth = 0.4) +
coord_sf(
crs = goode_crs,
xlim = st_bbox(outline)[c("xmin", "xmax")],
ylim = st_bbox(outline)[c("ymin", "ymax")],
expand = FALSE,
datum = NA
) +
theme_void() +
theme(
text = element_text(family = "coiny"),
plot.background = element_rect(fill = "#fcf1e7", colour = NA),
plot.title = element_text(
color = "#E87516", face = "bold", size = rel(3),
margin = margin(b = 10)
),
plot.margin = margin(10, 10, 10, 10),
plot.caption = element_text(
color = "#E87516", size = rel(1.5),
margin = margin(t = 10)
)
) +
labs(
title = "Let's peel the world",
caption = "Interrupted Goode homolosine projection"
)
References
- Panaïotis, T. (2026, September 29). Projections cartographiques : Le guide pour ne pas y laisser sa santé mentale. Pyranhia. Article
- Wilke, C. O. (n.d.). Interrupted Goode homolosine. practicalgg. https://wilkelab.org/practicalgg/articles/goode.html (Source for the outline and masking approach.)

Top comments (0)