Reputation: 2535
(how) is it possible to plot geodata – for example a polygon layer – on a globe with d3/perspective view, similar to this graphic on wikipedia?
I'd like a solution with sf
and ggplot
most, but any solutions are welcome.
(I ask this mostly out of curiosity, but since I see graphics like this fairly often, I guess the question might be useful)
Upvotes: 2
Views: 1010
Reputation: 8749
You can use orthographic projection in sf
and ggplot2
projecting to "+proj=ortho"
coordinate reference system.
Making the oceans turn blue may take some tweaking; I have resorted to buffering the Null Island by the Earth radius (inspired by this gist).
For more information of the arguments (i.e. lat_0 & lon_0) used have a look at the PROJ documentation https://proj.org/operations/projections/ortho.html
For a more graphic example consider this piece of code:
library(sf)
library(giscoR) # for the countries dataset only
library(ggplot2)
# projection string used for the polygons & ocean background
crs_string <- "+proj=ortho +lon_0=30 +lat_0=30"
# background for the globe - center buffered by earth radius
ocean <- st_point(x = c(0,0)) %>%
st_buffer(dist = 6371000) %>%
st_sfc(crs = crs_string)
# country polygons, cut to size
world <- gisco_countries %>%
st_intersection(ocean %>% st_transform(4326)) %>% # select visible area only
st_transform(crs = crs_string) # reproject to ortho
# one of the visible ones red (don't really matter which one :)
world$fill_color <- ifelse(world$ISO3_CODE == "DEU", "interesting", "dull")
# now the action!
ggplot(data = world) +
geom_sf(data = ocean, fill = "aliceblue", color = NA) + # background first
geom_sf(aes(fill = fill_color), lwd = .1) + # now land over the oceans
scale_fill_manual(values = c("interesting" = "red",
"dull" = "lightyellow"),
guide = "none") +
theme_void()
Upvotes: 10
Reputation: 3412
That is amazing @jindra-lacko! I took the liberty of checking the code above by creating a polar view map of Antarctica (holy grial of maps ;)), and works amazingly!:
library(sf)
library(giscoR) # for the countries dataset only
library(ggplot2)
# Test of https://stackoverflow.com/a/70756593/7877917
# projection string used for the polygons & ocean background
crs_string <- "+proj=ortho +lat_0=-90 +lon_0=0"
# background for the globe - center buffered by earth diameter
ocean <- st_point(x = c(0, 0)) %>%
st_buffer(dist = 6371000) %>%
st_sfc(crs = crs_string)
# country polygons, cut to size
world <- gisco_countries %>%
st_intersection(ocean %>% st_transform(4326)) %>% # select visible area only
st_transform(crs = crs_string) # reproject to ortho
# one of the visible ones red (don't really matter which one :)
world$fill_color <- ifelse(world$ISO3_CODE == "DEU", "interesting", "dull")
# background for the globe - center buffered by earth diameter
ocean <- st_point(x = c(0, 0)) %>%
st_buffer(dist = 6371000) %>%
st_sfc(crs = crs_string)
# now the action!
ggplot(data = world) +
geom_sf(data = ocean, fill = "aliceblue", color = "black") + # background first
geom_sf(aes(fill = fill_color), lwd = .1) + # now land over the oceans
scale_fill_manual(
values = c(
"interesting" = "red",
"dull" = "lightyellow"
),
guide = "none"
) +
theme_void() +
labs(
title = "Polar View: Antarctica",
caption = "Based on Jindra Lacko:\nhttps://stackoverflow.com/a/70756593/7877917"
)
Upvotes: 2