rr-sfcoordinate-systemsmap-projections

sf::st_transform() returns empty geometry


I have transformed the rnaturalearth countries dataset for orthographic plotting using the procedure outlined here.

enter image description here

However, transforming with st_transform() results in at least one of the geometries (mainland Russia) being empty.

This reads and attempts to transform the problematic polygon:

polygon <- st_as_sf(data.frame(st_as_sfc(readLines("https://pastebin.com/raw/APH15G6X"), crs = 4326)))
st_transform(polygon, "+proj=ortho +lat_0=20 +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs")
Simple feature collection with 1 feature and 0 fields (with 1 geometry empty)
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
CRS:           +proj=ortho +lat_0=20 +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs
            geometry
1 MULTIPOLYGON EMPTY

The geometry seems to be valid and is expected to be fully visible after orthographic projection, so I'm not sure what else could be going on.


Solution

  • The gist you linked is inspiring, and it has helped me a lot in the past. But it is rooted in an obsolete version of {sf} - and with release 1.0 (which introduces S2 backend for geographic CRS) things got somewhat easier.

    I have updated the logic somewhat and published it a while back in this answer https://stackoverflow.com/a/70756593/7756889 - when I amend the code to your definition of Ortho projection it shows mainland Russia as expected (= the geometry is not empty, but cut somewhat to hide the invisible parts in Asia). In addition the answer uses the world dataset from Gisco instead of Natural Earth; it should have negligible impact.

    library(sf)
    library(giscoR) # for the countries dataset only
    library(ggplot2)
    
    # projection string used for the polygons & ocean background
    crs_string <- "+proj=ortho +lat_0=20 +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs"
    
    # 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
    
    # now the action!
    ggplot(data = world) +
      geom_sf(data = ocean, fill = "aliceblue", color = NA) + # background first
      geom_sf(fill = "lightyellow", lwd = .1) + # now land over the oceans
      theme_void()
    

    ortho map with russia behaving itself - I wish it were so in real life as well...