sf线对象缓冲区锯齿问题及米制单位适配方案咨询
我有一个line sf对象,想要为其创建10米的缓冲区,并最终计算缓冲区的面积(单位:平方米)。但当前设置下生成的缓冲区不规则且呈锯齿状,无法贴合原线条。
初始代码(带CRS参数)
#creating simulated coordinate data Seqlat <- seq(from=-90, to=90, by=.01) Seqlong <- seq(from=-180, to=180, by=.01) Latitude <- sample(Seqlat, size=20, replace=TRUE) Longitude <- sample(Seqlong, size=20, replace=TRUE) VirtualCoordinates <- data.frame(x= Longitude, y = Latitude) #create a line sf object from the simulated data sf_object <- st_as_sf(VirtualCoordinates, coords = c("x", "y")) #create a linestring object of the telemetry data L1 <- st_combine(sf_object) %>% st_cast("LINESTRING") plot(L1, axes = TRUE) #convert linestring to sf object line <- st_as_sf(L1,crs=4269) plot(line, axes = TRUE) crs(line) #buffer around the line buff_line <- st_buffer(line, dist = 10,endCapStyle="ROUND") #plotting the buffered line plot(buff_line, axes = TRUE) #calculate area of buffer area<-st_area(buff_line)
有趣的是,若从st_as_sf中移除crs参数,缓冲区效果会好很多,但面积计算的单位却发生了变化。据我对st_buffer函数的了解,这可能是因为缺少CRS导致面积以原始数据的默认单位(度)计算,但我不确定这对缓冲区计算的具体影响。
无CRS参数的代码
#convert linestring to sf object (NO CRS ARGUMENT) line <- st_as_sf(L1) plot(line, axes = TRUE) crs(line) #buffer around the line buff_line <- st_buffer(line, dist = 10,endCapStyle="ROUND") #plotting the buffered line plot(buff_line, axes = TRUE) #calculate area of buffer area<-st_area(buff_line)
问题
A) 为何初始生成的缓冲区会如此不规则且呈锯齿状?
B) 为何移除crs参数后缓冲区效果变好,但单位却不同?
C) 是否存在方法可以创建以米为单位的均匀线缓冲区?
解答
A) 缓冲区不规则的原因
你指定的CRS是4269(NAD83地理坐标系),它的单位是度而非米。调用st_buffer(line, dist = 10)时,这里的10代表10度,而非10米。10度在地球上的实际跨度极大(赤道上1度约等于111公里),但你的线是由随机经纬度点组成的短线条,用10度做缓冲区会导致图形严重变形,呈现出锯齿状的不规则形态。
B) 移除CRS后缓冲区效果变好但单位不同的原因
移除CRS参数后,sf对象会被当作无地理参考的平面坐标系处理,此时st_buffer直接按照输入的坐标数值(模拟的经纬度被视为平面坐标)计算缓冲区,10就是平面上的10个单位,所以缓冲区形状看起来更规整。但因为没有地理CRS,st_area计算的是平面坐标下的面积,单位是“度的平方”,没有实际地理意义。
C) 创建米级均匀缓冲区的方法
核心是将地理坐标系转换为以米为单位的投影坐标系,再执行缓冲区操作,步骤如下:
- 给无CRS的线对象指定正确的地理CRS;
- 转换为米制投影坐标系(如UTM分区、国家平面坐标系等);
- 在投影坐标系下创建10米缓冲区;
- 直接在投影坐标系下计算面积,结果单位即为平方米。
示例代码:
# 给线对象指定地理CRS line <- st_as_sf(L1, crs = 4269) # 转换为UTM投影(替换XX为研究区域对应的UTM带号,如32610) line_utm <- st_transform(line, crs = st_crs(326XX)) # 创建10米缓冲区 buff_line_utm <- st_buffer(line_utm, dist = 10, endCapStyle = "ROUND") # 计算面积(单位:平方米) area_sqm <- st_area(buff_line_utm) # 可选:将缓冲区转换回地理坐标系用于绘图 buff_line_wgs84 <- st_transform(buff_line_utm, crs = 4269) plot(buff_line_wgs84, axes = TRUE)
如果不确定UTM分区,可使用st_transform(line, crs = "+proj=utm +zone=auto +datum=NAD83 +units=m")让sf自动匹配合适的分区,或根据研究区域选择对应投影坐标系。
内容的提问来源于stack exchange,提问作者Jason Edelkind

