st_covers()函数随边界框扩大出现异常行为的问题求助
解决sf包中st_covers在大边界框下返回空结果的问题
问题根源
在WGS84(EPSG:4326)地理坐标系下,st_as_sfc()把边界框转成多边形时,默认会生成面积最小的多边形。当边界框扩展到一定程度(比如跨180°经线、覆盖接近半个地球),生成的多边形会变成原始区域的「补集」——也就是覆盖了全球除了点所在区域的部分,这时候你的点自然不在这个多边形里,所以st_covers()返回空。
那个1.44-1.45的阈值,就是边界框扩展到触发多边形翻转的临界点,这个值会随原始边界框的位置变化,所以不是固定值。
可行解决方案
方案1:强制生成预期的大区域多边形(仅适用于跨日界线场景)
给st_as_sfc()加offset参数,让多边形按你预期的大区域生成,而不是默认的最小面积:
# 修改bbox3的生成代码,添加offset参数 bbox3 <- st_bbox(points_sf) %>% expand_bbox(expand_factor = 2) %>% st_as_sfc(offset = c(180, 0)) %>% # 指定offset,强制生成正确的大区域多边形 st_set_crs(st_crs(points_sf)) st_covers(bbox3, points_sf) # 现在会正常返回点的索引
注意:这个方法只适合边界框跨180°经线的情况,要是涉及南北极附近的扩展,可能需要调整offset参数。
方案2:转换为投影坐标系(通用推荐方案)
WGS84是地理坐标系,本来就不适合做空间谓词计算,尤其是大区域场景。换成对应区域的投影坐标系(比如南美洲专用的South America Albers Equal Area Conic,EPSG:102003),就能彻底解决问题:
# 定义南美洲的投影坐标系 sa_crs <- st_crs(102003) # 将点和边界框转换到投影坐标系下 points_proj <- st_transform(points_sf, sa_crs) bbox_proj <- st_bbox(points_proj) %>% st_as_sfc() # 扩展边界框并执行覆盖测试 bbox3_proj <- st_bbox(points_proj) %>% expand_bbox(expand_factor = 2) %>% st_as_sfc() %>% st_set_crs(sa_crs) st_covers(bbox3_proj, points_proj) # 完全正常返回结果
这种方法从根源上避免了地理坐标系的多边形翻转问题,是更稳定的通用解法。
验证提示
用plot()查看4326下的bbox3,你会发现它其实是覆盖全球除南美洲外的区域,所以点不在里面;转换投影后,bbox3_proj是正常扩大的矩形,包含所有点。另外st_contains()、st_within()这类空间谓词的异常,也能用上述方法一并解决。
内容的提问来源于stack exchange,提问作者ChrKoenig
相关产品推荐
相关产品推荐

