我正在尝试沿约 600 条样线制作单面缓冲区,但是缓冲区无法正常工作。
我错过了什么!?
library(sf) #v1.0 -16
library(ggplot2)
library(dplyr)
library(units)
library(terra)
library(tmap)
#Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
#code for building the Linestring from full dataset - multipoint saved for trouble shooting
obs_pt<-obs %>% filter(is.na(Transect_ID)==FALSE)%>%
st_as_sf(coords = c("lon", "lat"), na.fail = FALSE, crs = "epsg:4326") %>%
group_by(Transect_ID) %>%
summarize() %>%
filter(st_geometry_type(.) == "MULTIPOINT")
obs_ls<-obs_pt %>%
st_cast("LINESTRING", keep=TRUE)
#switch from lat/lon to UTM for planer geometry
obs_ls_planer<-obs_ls%>%st_transform("EPSG:32610") #Zone 10= most of study area
#filter data for reproducible example:
obs_ls_125<-obs_ls_planer%>%filter(Transect_ID==125)
saveRDS(obs_ls_125,paste0(usr,dir,"obs_ls_125.rda"))
[obs_ls_125](https://www.dropbox.com/scl/fi/47c83vgxeccphb1rkjumv/obs_ls_125.rda?rlkey=c1ymlbky7iohzhke6dap2x4ep&dl=0)
obs_ls_125<-readRDS("obs_ls_125.rda")
obs_ls_125
具有 1 个特征和 5 个字段的简单特征集合 几何类型:LINESTRING 尺寸:XY 边界框:xmin:361857.1 ymin:4786302 xmax:362981.9 ymax:4787215 预计 CRS:WGS 84 / UTM 区域 10N
Transect_ID 几何 Cruise_ID 日期 条件 ObsSidePS
<int> <LINESTRING [m]> <chr> <date> <chr> <chr>
1 125 (362210.4 4786933, 362299.5 4786863, 362378.3 4786793, … 202210 2022-10-14 1 右舷
#buffer implementation in sf
obs_ls_125.b <- st_buffer(obs_ls_125, dist = 100, endCapStyle = "FLAT", singleSide = TRUE)
#buffer implementation in terra
vsp <- terra::vect(obs_ls_125)
buffer_terra <- terra::buffer(vsp, width = 100, capstyle = "FLAT", singlesided = TRUE)
buffer_terra.sf <- sf::st_as_sf(buffer_terra)
ggplot() +
geom_sf(data = obs_ls_125.b, fill = "yellow")+
geom_sf(data = obs_ls_125, color = "blue", linewidth = 1)+
geom_sf(data = obs_ls_125.b%>%st_cast("POINT"), color = "orange") #points of polygon
ggplot() +
geom_sf(data = buffer_terra.sf, fill = "pink")+
geom_sf(data = buffer_terra.sf%>%st_cast("POINT"), color = "orange")
不是真的,它按预期工作,问题与横断面的几何形状有关。本身不是问题,但它不是一条直线,这使得事情变得更加困难。如下图所示,缓冲区是单侧的,但是线是弯曲的,因此缓冲区半径较大时,多边形会包围整条线。
a <- readRDS("~/Downloads/obs_ls_125.rda")
b <- a |>
sf::st_buffer(dist = 30, singleSide = TRUE)
tmap::tm_shape(a) +
tmap::tm_lines() +
tmap::tm_shape(b) +
tmap::tm_polygons() +
tmap::tm_grid()
b <- a |>
sf::st_buffer(dist = 1000, singleSide = TRUE)
tmap::tm_shape(b) +
tmap::tm_polygons() +
tmap::tm_shape(a) +
tmap::tm_lines() +
这是
linestring
的详细信息:
terra::plot(a["geometry"], axes = TRUE,
xlim = c(362450, 362550),
ylim = c(4786650, 4786750))
创建于 2024-03-27,使用 reprex v2.1.0
编辑
处理不直的横断面就是简化它们。您可以尝试使用足够大的
sf::st_simplify()
参数的 dTolerance = 1000
函数,但它也会移动最左/最右坐标。下面是如何在最左/右坐标之间创建线条并创建缓冲区的简单方法。
不知道您的样线来源是什么,是一种 GPS 文件吗?如果给出了线坐标,那么我们已经以某种方式处理了它;如果这是您可以选择/创建的内容,请查看 sf::st_make_grid()
函数。
a <- readRDS("~/Downloads/obs_ls_125.rda")
crd <- a |>
sf::st_coordinates()
xleft <- crd[which(crd[, "X"] == min(crd[, "X"])), "X"]
yleft <- crd[which(crd[, "X"] == min(crd[, "X"])), "Y"]
xright <- crd[which(crd[, "X"] == max(crd[, "X"])), "X"]
yright <- crd[which(crd[, "X"] == max(crd[, "X"])), "Y"]
l <- matrix(c(xleft, yleft, xright, yright), nrow = 2, ncol = 2, byrow = TRUE) |>
sf::st_linestring() |>
sf::st_sfc()
b <- l |>
sf::st_buffer(dist = 30, singleSide = TRUE)
tmap::tm_shape(l) +
tmap::tm_lines(lwd = 3, col = "blue") +
tmap::tm_shape(b) +
tmap::tm_polygons() +
tmap::tm_grid()
创建于 2024-03-27,使用 reprex v2.1.0