使用nngeo包st_remove_holes函数去除shapefile孔洞存在残留问题
孔洞去除不彻底的原因
st_remove_holes()仅识别单个POLYGON对象的内部环作为孔洞:你按街区分组并调用st_union()后得到的是MULTIPOLYGON对象,多个POLYGON子要素围合形成的空白区域不会被判定为孔洞,因此不会被移除。- 合并后存在拓扑错误:原始普查 tract 数据合并后可能存在自相交、环方向错误等拓扑异常,导致函数无法正确识别内部孔洞。
- 未明确匹配面积阈值:若残留孔洞面积极小,可能触发函数的精度识别阈值,导致遗漏。
解决方案
你可以按照以下步骤调整代码,即可完全移除所有孔洞:
library(dplyr) library(sf) library(nngeo) library(geobr) sf_use_s2(FALSE) # 读取原始普查小区数据 shape.muni <- read_census_tract(year = 2010, code_tract = 3304557) # 方法1:基础修复方案,适配绝大多数场景 shape.muni <- shape.muni %>% group_by(code_neighborhood, name_neighborhood) %>% summarise(geometry = st_union(geom)) %>% # 先修复拓扑错误,避免识别异常 st_make_valid() %>% # 明确指定移除所有面积大于0的孔洞 st_remove_holes(min_area = 0) # 方法2:如果方法1仍有残留孔洞,可追加缓冲区二次处理 # 缓冲区距离根据数据坐标系调整,地理坐标系下0.0001约对应10米精度,可按需调整 shape.muni <- shape.muni %>% st_buffer(0.0001) %>% st_buffer(-0.0001) %>% st_remove_holes(min_area = 0) # 方法3:终极方案,手动提取外环直接移除所有内部环 remove_all_holes <- function(sf_obj) { sf_obj$geometry <- st_sfc(lapply(st_geometry(sf_obj), function(x) { if (st_geometry_type(x) == "MULTIPOLYGON") { polys <- lapply(x, function(poly) st_polygon(poly[1])) st_multipolygon(polys) } else if (st_geometry_type(x) == "POLYGON") { st_polygon(x[1]) } else { x } }), crs = st_crs(sf_obj)) return(sf_obj) } shape.muni <- remove_all_holes(shape.muni)
内容的提问来源于stack exchange,提问作者Igor
相关产品推荐
相关产品推荐

