如果我在R中有一个spatialpolygons对象,我该如何生成一组n个点,使其位于该多边形的边缘上?
起初我想只从多边形顶点进行采样,但似乎有时会出现没有顶点的拉伸部分,因为多边形边缘是一条直线...
起初我想只从多边形顶点进行采样,但似乎有时会出现没有顶点的拉伸部分,因为多边形边缘是一条直线...
sf
包中的st_segmentize()
,它会在直线上添加点,然后沿着这些更细的点进行采样。
st_segmentize()
有一个参数dfMaxLength
,它定义了允许沿线行进的最大距离。您设置得越小,就会得到更多的点。它至少应该与任何两个点之间的最小距离一样小。library(sf)
library(tidyverse)
## original form
poly <- st_polygon(x=list(cbind(x=c(1,2,3,1),y=c(1,2,1,1))))
# segmentize, then convert to points
poly_points <- st_segmentize(poly, dfMaxLength = 0.1) %>%
st_coordinates() %>%
as.data.frame() %>%
select(X, Y) %>%
st_as_sf(coords = c("X", "Y"))
## plot: you can just use sample() now on your point dataset
plot(poly, reset = FALSE, main = "segmentize (black point), then sample 5 (red points)")
plot(poly_points, reset = FALSE, add = TRUE)
plot(poly_points[sample(1:nrow(poly_points), size = 5),], add = TRUE, col = 2, pch = 19)
获取任意两点之间的最小距离(注意避免零): poly %>%
st_coordinates() %>%
as.data.frame() %>%
st_as_sf(coords = c("X", "Y")) %>%
st_distance() %>% c() %>%
unique() %>%
sort
P(边缘e上的点p) = P(点p | 边缘e) * P(边缘e)
其中P(边缘e)与其长度成比例。因此,首先随机选择一条边,然后在其上随机选择一个点。
这是一个三角形示例:
poly <- Polygon(list(x=c(1,2,3,1),y=c(1,2,1,1)))
我们将计算边长:
require(gsl) #for fast hypot function
xy <- poly@coords
dxy <- diff(xy)
h <- hypot(dxy[,"x"], dxy[,"y"])
并随机选择一侧:
e <- sample(nrow(dxy), 1, probs=h)
然后在该边缘上绘制一个点:
u <- runif(1)
p <- xy[e,] + u * dxy[e,]
将整个内容包装在一个函数中,我们有:
rPointOnPerimeter <- function(n, poly) {
xy <- poly@coords
dxy <- diff(xy)
h <- hypot(dxy[,"x"], dxy[,"y"])
e <- sample(nrow(dxy), n,replace=TRUE, prob=h)
u <- runif(n)
p <- xy[e,] + u * dxy[e,]
p
}
带有演示:
plot( rPointOnPerimeter(100,poly) )