You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建锥形多边形模拟相机视场以采样SpatRaster

问题描述

我正在研究野生动物相机网格,希望从相机点位对应的SpatRaster中提取视场范围内的数据。为模拟相机视场,需创建与相机方位角一致的锥形多边形。

最小可运行示例

library(terra)
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)

WildCams <- spatSample(r,10, "regular", as.points=TRUE)
bearings <- sample.int(180,10)
WildCams$bearings <- bearings    
WildCams_buf <- buffer(WildCams,5000)
WildCams_sf <- sf::st_as_sf(WildCams)

我曾尝试基于单个点位创建锥形,但无法扩展到多点网格,以下是未成功的尝试代码:

# Attempt 1: Create a cone polygon
theta <- 120 # 感兴趣的角度
radius <- 500 # 感兴趣的半径长度(单位:米)

WildCams_buf_sf <- sf::st_as_sf(WildCams_buf)
theta = pi*theta/180
cone1 <- vect(WildCams_buf_sf)
conegrid = rast(cone1, nrow=nrow(r), ncol=ncol(r))
conegrid2 = rasterize(cone, conegrid, field="bearings")
conegrid3 <- project(conegrid2, crs(r), res=res(r))

plot(conegrid3)
xy = crds(conegrid3)
xy[,1] = xy[,1] - st_coordinates(WildCams_sf)[1]
xy[,2] = xy[,2] - st_coordinates(WildCams_sf)[2]

v = (atan2(xy[,1], xy[,2]) + theta)

conegrid3[] = (1+sin(v))/2
conegrid4 = mask(conegrid3, vect(WildCams_sfbuf ))
plot(conegrid4 >0.05)

请问在terra或其他R包中,是否存在可基于多点集创建带各自相机方位角的视场锥形多边形的函数?我希望通过这些锥形提取SpatRaster的值。


解决方案

可以通过自定义函数结合批量处理,基于terra或sf包为每个相机点位生成带方位角的视场锥形多边形,进而提取栅格数据。

方法1:基于terra构建批量锥形多边形

核心思路是为每个相机点位,根据方位角、视场角和半径生成扇形多边形,再批量合并。

步骤1:定义单个锥形生成函数

library(terra)

# 生成单个相机视场锥形的函数
create_cone <- function(point, bearing, fov_angle = 120, radius = 500) {
  # 转换角度为弧度,调整方位角坐标系(正北为0度)
  bearing_rad <- (bearing - 90) * pi / 180
  fov_rad <- fov_angle * pi / 180
  
  # 计算锥形左右边界角度
  left_angle <- bearing_rad - fov_rad / 2
  right_angle <- bearing_rad + fov_rad / 2
  
  # 计算左右边界点坐标
  left_x <- point[1] + radius * cos(left_angle)
  left_y <- point[2] + radius * sin(left_angle)
  right_x <- point[1] + radius * cos(right_angle)
  right_y <- point[2] + radius * sin(right_angle)
  
  # 构建多边形(原点→左边界→右边界→原点)
  coords <- matrix(c(point[1], point[2], left_x, left_y, right_x, right_y, point[1], point[2]),
                   ncol=2, byrow=TRUE)
  cone_poly <- vect(coords, type="polygons", crs=crs(point))
  
  return(cone_poly)
}

步骤2:批量生成所有相机的锥形

# 转换相机点位为数据框方便遍历
cams_df <- as.data.frame(WildCams, geom="XY")

# 批量生成锥形多边形列表
cone_list <- lapply(1:nrow(cams_df), function(i) {
  create_cone(point = cams_df[i,c("x","y")],
              bearing = cams_df$bearings[i],
              fov_angle = 120,
              radius = 500)
})

# 合并所有锥形为单个SpatVector
all_cones <- do.call(rbind, cone_list)
# 添加相机ID用于后续关联
all_cones$cam_id <- 1:length(cone_list)

步骤3:提取栅格数据

使用terra::extract批量提取每个锥形范围内的栅格统计值:

# 提取每个锥形内的栅格均值(可替换为sum、max等函数)
cone_extract <- terra::extract(r, all_cones, fun=mean, na.rm=TRUE)
# 合并相机点位信息与提取结果
final_result <- cbind(cams_df, cone_extract)

方法2:使用sf包实现扇形裁剪

若更习惯sf生态,可结合缓冲区与交集操作生成扇形:

library(sf)

# 生成单个sf格式扇形的函数
create_sf_cone <- function(sf_point, bearing, fov_angle=120, radius=500) {
  # 创建圆形缓冲区
  buf <- st_buffer(sf_point, radius)
  # 计算扇形起止角度(适配sf坐标系)
  start_angle <- bearing - fov_angle/2
  end_angle <- bearing + fov_angle/2
  
  # 生成扇形边界射线
  rays <- st_sfc(st_linestring(rbind(
    st_coordinates(sf_point),
    st_coordinates(sf_point) + c(cos((start_angle-90)*pi/180), sin((start_angle-90)*pi/180)) * radius,
    st_coordinates(sf_point),
    st_coordinates(sf_point) + c(cos((end_angle-90)*pi/180), sin((end_angle-90)*pi/180)) * radius
  )), crs=st_crs(sf_point))
  
  # 裁剪缓冲区得到扇形
  cone <- st_intersection(buf, st_polygonize(st_union(rays)))
  return(cone)
}

# 批量生成所有相机的扇形
sf_cones <- do.call(rbind, lapply(1:nrow(WildCams_sf), function(i) {
  create_sf_cone(WildCams_sf[i,], WildCams_sf$bearings[i])
}))

# 转换为terra格式后提取栅格数据
terra_cones <- vect(sf_cones)
extract_result <- terra::extract(r, terra_cones)

注意事项

  • 确保相机点位使用投影坐标系(带米单位),若为地理坐标系(如WGS84),需先转换为投影坐标系,否则半径计算会出错。
  • 方位角坐标系需与数据匹配:函数中默认正北为0度,顺时针递增,可根据实际数据调整角度转换逻辑。

内容的提问来源于stack exchange,提问作者Mark Thompson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:26:00