Closed boundaries on a map when using geom_sf to cross dateline
Asked Answered
S

1

7

I am trying to make a Robinson-projection map that is not centered at longitude 0, and crosses both sides of the 180° line.

My code is below:

library("rnaturalearthdata")
world <- ne_countries(scale = "medium", returnclass = "sf")
robinson = "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"
transformed = st_transform(world, robinson)
ggplot(data=transformed) + geom_sf(fill = "gray", colour = "black")+theme_bw()

That generates this map, which is oriented correctly, except all the split boundaries are "inside out" and wrap across the whole map.

enter image description here

There is this related question from 9 years ago, but I am hoping that with recent package updates, there is a less complicated solution, which will allow us to plot our lat/lon data-points using geom_point() without additional transformations.

EDIT #2: The solution by L. Tyrone works great for me. To plot points using this method, you will have to transform them from a data frame to an sf object with the same Coord Ref System, or else the lat/lon is interpreted as meters, and ends up indistinguishable from 0,0:

# Transform with fake data...
fakedata=data.frame(lat=c(-10,-20,80),lon=c(45,-100,120),tag=c("indian","tropical","arctic"))
transpoint = st_as_sf(fakedata,coords=c("lon","lat"),crs=4326)
dtran = st_transform(transpoint,robinson)

Then you can plot them by adding the special geometry= and stat= declarations to geom_point or even geom_text_repel:

geom_point(data=dtran,aes(geometry=geometry,color=tag),stat="sf_coordinates") +
geom_text_repel(data=dtran,aes(geometry=geometry,label=tag),stat="sf_coordinates")

Final Result: successful plot of fake data onto map

Sible answered 5/2, 2024 at 19:22 Comment(2)
Have a look on this https://mcmap.net/q/1021753/-how-to-plot-coordinates-on-a-spherical-shape-file-correctlyFisk
Thanks Grzegorz. I tried the gisco library but no difference in the output.Sible
E
11

You need to 'break' any polygons that cross 180 prior to projecting them. The st_break_antimeridian() function from the sf package is the easiest way to achieve this. It will throw a warning, which you can safely ignore.

library(rnaturalearth)
library(sf)
library(dplyr)
library(ggplot2)

world <- ne_countries(scale = "medium", returnclass = "sf") %>%
  st_set_crs(4326)

robinson <- "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"

world_robinson_90w <- world %>%
  st_break_antimeridian(lon_0 = -90) %>%
  st_transform(crs = robinson)

ggplot() +
  geom_sf(data = world_robinson_90w)

result

Engender answered 5/2, 2024 at 22:7 Comment(1)
This is a miracle. Thank you so much. You don't know how long I've struggled with this. I had to update my sf to get the break antimeridian function, but it is working and I can even plot transformed points.Sible

© 2022 - 2025 — McMap. All rights reserved.