R语言 使用sf和ggplot显示地球仪的边缘或海洋背景

shstlldc  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(123)

我试图用ggplot和sf得到一条表示地球仪边缘的线(或者一个表示海洋的多边形)。我的代码适用于一个基本的莫尔韦德投影...

library(tmap)
library(sf)
library(s2)
sf_use_s2(TRUE) 
data("World") ## get built-in data from the tmap package
world.sf <- World

lat <- c(seq(from=-90,to=90,by=0.25)) ## creates a sequence -90 to 90 by 0.25
lon <- c(rep(180,length(lat)),rep(-180,length(lat))) # creates a sequence of 180 and -180 longitudes
oceans.df <- data.frame("lon"=lon, "lat"=c(lat,lat)) ## combines the point in a data frame
oceans.sf <- st_as_sf(oceans.df,coords = c("lon","lat"), crs=4326) %>% 
  st_union() %>% # combines the points into a MULTIPOINT
  st_convex_hull() # gets the outline of the points

ggplot() + 
  geom_sf(data=oceans.sf, fill="blue") ## fine for Mercator

oceans_moll.sf <- st_as_sf(oceans.df,coords = c("lon","lat"), crs=4326) %>% 
  st_transform(crs="+proj=moll") %>% ## 
  st_union() %>% # combines the points into a MULTIPOINT
  st_convex_hull() # gets the outline of the points

world_moll.sf <- st_transform(world.sf, crs="+proj=moll")
ggplot() + 
  geom_sf(data=oceans_moll.sf, fill="blue") + 
  geom_sf(data=world_moll.sf, fill="white")

但对于以太平洋为中心的莫尔韦德来说,

oceans_moll_pacific.sf <- st_as_sf(oceans.df,coords = c("lon","lat"), crs=4326) %>% 
  st_transform(crs="+proj=moll +lon_0=-150 +x_0=0 +y_0=0") %>% ## 
  st_union() %>% # combines the points into a MULTIPOINT
  st_convex_hull() # gets the outline of the points

ggplot() + 
  geom_sf(data=oceans_moll_pacific.sf, fill="blue")

不太确定出了什么问题。我试着用下面的sf::st_transform()中的代码定义地球仪,返回空的几何体,但这也不适用于重投影。

ocean <- st_point(x = c(0,0)) %>%
  st_buffer(dist = 6371000) %>%
  st_sfc(crs = "+proj=ortho +lat_0=20 +lon_0=0 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs")

不知道这里出了什么问题...

x4shl7ld

x4shl7ld1#

基于一个伟大的答案张贴在https://gis.stackexchange.com/questions/468260/oceans-as-global-background-wont-reproject-properly/468292#468292,这个通用的黑客修复多边形,并创建一个海洋/轮廓的任何本初子午线。

rm(list=ls())
library(rnaturalearthdata)
library(rnaturalearth)
library(sf)
library(tidyverse)

ante_meridian <- -20 ## change as needed
offset <- ante_meridian+180

jitter = 0.01
lat <- c(seq(from=-90,to=90,by=0.25))
lon <- c(rep(offset-jitter,length(lat)),rep(offset+jitter,length(lat)))

oceans.sf <- cbind(lon, c(lat, rev(lat))) %>% st_linestring() %>% st_cast("POLYGON") %>% 
  st_sfc(crs=4326) %>% st_transform(crs=paste0("+proj=moll +lon_0=",ante_meridian," +x_0=0 +y_0=0"))

world_ne.sf <- st_as_sf(ne_countries(scale="medium"))

world_Mollweide_rotated.sf <- world_ne.sf %>%
  st_break_antimeridian(lon_0 = ante_meridian) %>% # insert this before transformation
  # (& ignore the warning)
  st_transform(crs=paste0("+proj=moll +lon_0=",ante_meridian," +x_0=0 +y_0=0"))

ggplot() + geom_sf(data=oceans.sf, fill="blue") + geom_sf(data=world_Mollweide_rotated.sf, 
                                                          fill="grey80")

相关问题