简体   繁体   English

验证 R 中多边形矩阵中的矢量坐标

[英]Verify vector coordinates in polygon matrix in R

From a given matrix and vector in R .R中的给定矩阵和向量。 Which is the short code way to verify if a point is in an area?验证一个点是否在一个区域中的短代码方法是什么? (Target: get True or False ) (目标:得到TrueFalse

What I tried at the moment:我当时尝试的是:

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)

My expectation is to get a feature( True/False ) to confirm if it is inside or not.我的期望是获得一个特征( True/False )来确认它是否在里面。

By doing the same with a point that i know that it is not inside the polygon I see that the only that changes at into the output of point.in.poly is poly.ids giving NA .通过对我知道它不在多边形内的点做同样的事情,我看到唯一改变到 point.in.poly 的point.in.poly的是poly.ids给出NA Is this correct output to accomplish what I want to check?这是正确的 output 来完成我想要检查的吗?

point2=data.frame(t(c(-44.590467, -28.057815)))
point.in.poly(point2, Area)

And of course, is there any shorter code way?当然,还有更短的代码方式吗?

In my opinion there are two approaches, depdendently on how robust soution you require.在我看来,有两种方法,具体取决于您需要的强大解决方案。 If you do not need a high accuracy solution you can easily write the function yourself using ray tracing ( ray-line intersection and point in polygon ).如果您不需要高精度解决方案,您可以使用光线追踪( 光线交点多边形中的点)轻松编写 function。

What I mean by "not accurate solution" is that you agree to the fact that points that lie exactly on the line or in the polygon nodes etc. will be very, very, very rarely improperly classified.我所说的“不准确的解决方案”的意思是您同意这样一个事实,即恰好位于线上或多边形节点等中的点将非常、非常、非常罕见地被错误分类。 In x64 computers this issue is neglectible unless you do build a high accuracy triangulation algorithm or something similar (which you probably wouldn't do in R).在 x64 计算机中,这个问题是可以忽略的,除非您确实构建了高精度三角测量算法或类似的东西(您可能不会在 R 中这样做)。

In such a case it is really simple thing to do, but as mentioned before such function can sometimes fail due to floating point arithmetic precision flaws.在这种情况下,做起来真的很简单,但如前所述,function 有时会由于浮点算术精度缺陷而失败。 More on this issue can be found in computational geometry books and in docs of CGAL .更多关于这个问题的信息可以在计算几何书籍和CGAL 文档中找到。

The basic function could look like:基本的 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
}

And the sample usage:以及示例用法:

# 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))

在此处输入图像描述

However if you need a bit more accurate solution you can make multiple tests and then use some voting methodology.但是,如果您需要更准确的解决方案,您可以进行多次测试,然后使用一些投票方法。 For example assume that during a single test a risk of improper classification is about p=0.001 (which in reality is much lower) then the probability that in all three tests (with random direction vectors) it will be classified improperly would be only ppp = 0.000000001.例如,假设在单次测试中,不正确分类的风险约为 p=0.001(实际上要低得多),那么在所有三个测试(使用随机方向向量)中分类不正确的概率仅为 ppp = 0.000000001。 A modified version of the function could look like: 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
}

However if that still is insufficient, you have an option to use for example CGAL via RCpp or ( R bindings ) or if the license does not suit you, then you have to write your own robust algorithm, which is a really hard thing to do.但是,如果这仍然不够,您可以选择通过 RCpp 或( R 绑定)使用例如CGAL ,或者如果许可证不适合您,那么您必须编写自己的强大算法,这是一件非常困难的事情.

Other thing is efficiency issue.另一件事是效率问题。 If you wish to apply that test to lots of polygons (especially described with large amounts of edges) than you have to use some specific data structures in order to make everyting acceptably efficient.如果您希望将该测试应用于大量多边形(尤其是用大量边进行描述),那么您必须使用一些特定的数据结构才能使每一项都具有可接受的效率。 More details on that can be found in this book or in this book .更多细节可以在本书本书中找到。 And write that all in C or C++.并将所有内容写在 C 或 C++ 中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM