ggplot与sf包正射投影部分参数报错问题求助
正射投影参数触发sf包报错的问题分析
问题背景
使用ggplot2绘制空间数据时,部分正射投影参数会触发报错,且在R基础绘图的plot()函数中也存在类似问题,推测根源在sf包。
可正常运行的代码示例
以下代码能正常执行:
library(tmap) library(sf) library(tidyverse) data("World") ## 获取tmap包内置数据 world.sf <- World projection <- "+proj=ortho +lat_0=40" # 修正多边形避免在正射投影中被切割 ortho_world.sf <- st_cast(world.sf, 'MULTILINESTRING') %>% st_cast('LINESTRING', do_split=TRUE) %>% mutate(npts = npts(geometry, by_feature = TRUE)) %>% st_cast('POLYGON') %>% st_transform(crs=projection) ggplot() + geom_sf(data=ortho_world.sf)
另外,该投影参数也能正常工作:
projection <- "+proj=ortho +lat_0=70 +lon_0=-181" ## 运行正常
触发报错的投影参数
以下所有投影参数都会导致报错:
projection <- "+proj=ortho +lat_0=40 +lon_0=-180" ## 触发报错 projection <- "+proj=ortho +lat_0=40 +lon_0=-149" ## 触发报错 projection <- "+proj=ortho +lat_0=20 +lon_0=-149" ## 触发报错
原因分析
这个问题的核心是正射投影的视口边界恰好穿过部分多边形的顶点或边,导致sf在执行st_transform时无法正确处理跨越投影边界的几何对象,进而抛出错误。
具体来说:
- 正射投影(ortho)是半球投影,以指定的
lat_0和lon_0为中心展示半个地球。当lon_0设置为某些值时,投影的分割线会刚好经过世界地图数据中的部分多边形(比如太平洋岛屿、美洲大陆边缘)。 - 你用来修复多边形的
st_cast操作能处理大部分切割问题,但当投影边界与几何要素的顶点/边完全重合时,会生成无效几何对象(如零面积多边形、自相交图形),sf在转换或绘图时会检测到这些无效对象并报错。
解决建议
- 微调投影参数:把触发报错的
lon_0值稍微偏移一点,比如将-180改为-180.1,-149改为-149.1,避开刚好穿过几何要素的边界线。 - 添加几何有效性修复:在
st_transform之后调用st_make_valid()函数,自动修复转换过程中产生的无效几何对象:
ortho_world.sf <- st_cast(world.sf, 'MULTILINESTRING') %>% st_cast('LINESTRING', do_split=TRUE) %>% mutate(npts = npts(geometry, by_feature = TRUE)) %>% st_cast('POLYGON') %>% st_transform(crs=projection) %>% st_make_valid() # 修复无效几何
- 简化原始几何数据:对原始世界地图数据执行
st_simplify()操作,减少顶点数量,降低投影边界刚好穿过顶点的概率:
world.sf <- World %>% st_simplify(dTolerance = 0.1) # 先简化再处理后续步骤
内容的提问来源于stack exchange,提问作者Mark R
相关产品推荐
相关产品推荐

