[英]Verify vector coordinates in polygon matrix in R
從R
中的給定矩陣和向量。 驗證一個點是否在一個區域中的短代碼方法是什么? (目標:得到True
或False
)
我當時嘗試的是:
library(sf)
library(spatialEco)
# Lat long provided
Area <- SpatialPolygons(list(Polygons(list(Polygon(do.call(rbind,list(
c(45.406164, 28.429255),
c(44.182204, 27.395851),
c(43.699651, 29.055894),
c(45.259422,30.474260))))),'1')))
point=data.frame(t(c(44.590467, 28.057815)))
names(point)=c("lat", "long")
coordinates(point)=~lat+long
point.in.poly(point, Area)
我的期望是獲得一個特征( True/False
)來確認它是否在里面。
通過對我知道它不在多邊形內的點做同樣的事情,我看到唯一改變到 point.in.poly 的point.in.poly
的是poly.ids
給出NA
。 這是正確的 output 來完成我想要檢查的嗎?
point2=data.frame(t(c(-44.590467, -28.057815)))
point.in.poly(point2, Area)
當然,還有更短的代碼方式嗎?
在我看來,有兩種方法,具體取決於您需要的強大解決方案。 如果您不需要高精度解決方案,您可以使用光線追蹤( 光線交點和多邊形中的點)輕松編寫 function。
我所說的“不准確的解決方案”的意思是您同意這樣一個事實,即恰好位於線上或多邊形節點等中的點將非常、非常、非常罕見地被錯誤分類。 在 x64 計算機中,這個問題是可以忽略的,除非您確實構建了高精度三角測量算法或類似的東西(您可能不會在 R 中這樣做)。
在這種情況下,做起來真的很簡單,但如前所述,function 有時會由於浮點算術精度缺陷而失敗。 更多關於這個問題的信息可以在計算幾何書籍和CGAL 文檔中找到。
基本的 function 可能如下所示:
section.ray.intersection <- function(p,d,a,b)
# this function tests if a ray r=[p,d] intersects the segment [a,b]
# p - point c(x,y)
# d - ray direction c(x,y)
# a - one of the nodes of the section [a,b] (not ordered with respect to computational geometry standards)
# b - remaining node of the section [a,b]
{
v1 = p-a
v2 = b-a
v3 = c(-d[2],d[1])
t1 = (v2[1]*v1[2] - v2[2]*v1[1])/(v2 %*% v3)
t2 = (v1 %*% v3)/(v2 %*% v3)
return(t1 >=0. & (t2 >= 0. & t2 <= 1.0))
}
in.polygon <- function(px,py,Ax,Ay)
# basic function testing if the point is in the polygon
# px - x coordinate of the point
# py - y coordinate of the point
# Ax - a vector of x coordinates of the polygon
# Ay - a vector of y coordinates of the polygon
{
n <- length(Ax) # gent the number of nodes of the polygon
if (n != length(Ay)) return(NA) # can be ommitted if Ax and Ay are always valid
d = runif(2) # get the random vector of the direction
is = 0 # number of intersections
for (i in 2:n) # go trough all edges
is <- is + section.ray.intersection(c(px,py),d,c(Ax[i-1],Ay[i-1]),c(Ax[i],Ay[i])) # and count TRUEs
return( !(is %% 2==0)) # if the number of intersections is odd the point is inside
}
以及示例用法:
# libs
library(ggplot2)
library(purrr)
library(dplyr)
# polygon
Ax <- c(0,1,2,0.25,0)
Ay <- c(0,0,1,1.00,0)
# points
N = 1000 # number of points
p <- data.frame(x = rnorm(N,0.5,.4), y= rnorm(N,0.5,.4)) # data frame od point coordinates
# apply the function to points - this is a "for loop" equivalent
p$is.inside <- apply(p, 1, function(X){return(in.polygon(X[1],X[2],Ax,Ay))})
# make a plot
ggplot() + geom_path(data=data.frame(x=Ax,y=Ay),aes(x,y)) + geom_point(data=p,aes(x,y,col = is.inside))
但是,如果您需要更准確的解決方案,您可以進行多次測試,然后使用一些投票方法。 例如,假設在單次測試中,不正確分類的風險約為 p=0.001(實際上要低得多),那么在所有三個測試(使用隨機方向向量)中分類不正確的概率僅為 ppp = 0.000000001。 function 的修改版本可能如下所示:
in.polygon.robust <- function(px,py,Ax,Ay)
{
n <- length(Ax)
if (n != length(Ay)) return(NA) # can be ommitted if Ax and Ay are always valid
d1 <- runif(2) # direction 1
d2 <- runif(2) # direction 2
d3 <- runif(2) # direction 3
is1 <- 0 # number of intersections in direction 1
is2 <- 0 # number of intersections in direction 2
is3 <- 0 # number of intersections in direction 3
for (i in 2:n) # go trough all edges
{
P <- c(px,py)
Ap1 <- c(Ax[i-1],Ay[i-1])
Ap2 <- c(Ax[i],Ay[i])
# count intersections
is1 <- is1 + section.ray.intersection(P,d1,Ap1,Ap2)
is2 <- is2 + section.ray.intersection(P,d2,Ap1,Ap2)
is3 <- is3 + section.ray.intersection(P,d3,Ap1,Ap2)
}
r <- (is1 %% 2==0) + (is2 %% 2==0) + (is3 %% 2==0) # sum the even outcomes
return( !(r>=2)) # return voting outcome
}
但是,如果這仍然不夠,您可以選擇通過 RCpp 或( R 綁定)使用例如CGAL ,或者如果許可證不適合您,那么您必須編寫自己的強大算法,這是一件非常困難的事情.
另一件事是效率問題。 如果您希望將該測試應用於大量多邊形(尤其是用大量邊進行描述),那么您必須使用一些特定的數據結構才能使每一項都具有可接受的效率。 更多細節可以在本書或本書中找到。 並將所有內容寫在 C 或 C++ 中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.