R 经纬度点集之间的最大距离

R 经纬度点集之间的最大距离,r,algorithm,geospatial,latitude-longitude,cran,R,Algorithm,Geospatial,Latitude Longitude,Cran,我有一套lng/lat坐标。计算集合中任意两点之间最大距离的有效方法是什么(如果愿意,“最大直径”) 一种简单的方法是计算每两个点之间的距离并获得最大值,但这显然不能很好地扩展 编辑:这些点位于一个足够小的区域上,用于测量携带移动设备的人在一天内活动的区域。我认为以下可能是一个有用的近似值,它与点的数量成线性比例,而不是二次比例,并且非常容易实现: 计算各点的质心M 找到距离M最大的点P0 找到距离P0最大的点P1 用P0和P1之间的距离近似最大直径 这可以通过重复步骤3 N次来概括, 取PN-

我有一套lng/lat坐标。计算集合中任意两点之间最大距离的有效方法是什么(如果愿意,“最大直径”)

一种简单的方法是计算每两个点之间的距离并获得最大值,但这显然不能很好地扩展


编辑:这些点位于一个足够小的区域上,用于测量携带移动设备的人在一天内活动的区域。

我认为以下可能是一个有用的近似值,它与点的数量成线性比例,而不是二次比例,并且非常容易实现:

  • 计算各点的质心M
  • 找到距离M最大的点P0
  • 找到距离P0最大的点P1
  • 用P0和P1之间的距离近似最大直径
  • 这可以通过重复步骤3 N次来概括, 取PN-1和PN之间的距离

    可以有效地执行步骤1,将M近似为经度和纬度的平均值,当距离“小”且极点足够远时,这是正常的。其他步骤可以使用精确的距离公式执行,但如果可以将点的坐标近似为位于平面上,则速度要快得多。一旦找到“距离对”(希望是距离最大的一对),就可以用精确的公式重新计算其距离

    近似示例如下:如果φ(M)和λ(M)是质心的纬度和经度,计算为∑φ(p)/n和∑λ(p)/n

    • x(P)=(λ(P)-λ(M)+C)cos(φ(P))
    • y(P)=φ(P)-φ(M)[这只是为了清楚起见,它也可以是y(P)=φ(P)]
    式中,C通常为0,但如果一组点穿过λ=±180°线,则C可以为±360°。要找到最大距离,您只需找到

    • 最大值((x(PN)-x(PN-1))2+(y(PN)-y(PN-1))2)
    (不需要平方根,因为它是单调的)

    可以使用相同的坐标变换重复步骤1(在新坐标系中),以获得更好的起点。我怀疑,如果满足某些条件,上述步骤(不重复步骤3)总是会导致“真正的距离对”(我的术语)。如果我只知道什么情况

    编辑:

    我讨厌依赖别人的解决方案,但总有人会这么做的

    仍然保留上述4个步骤,并可选择(但可能有益,取决于点的典型分布)重复步骤3, 在这之后,, 在3D中进行计算克服了接近极点和与极点距离的限制:

    • x(P)=sin(φ(P))
    • y(P)=cos(φ(P))sin(λ(P))
    • z(P)=cos(φ(P))cos(λ(P))
    (唯一的近似值是,这仅适用于完美球体)

    质心由x(M)=∑x(p)/n等给出。, 而我们要寻找的最大目标就是

    • 最大值((x(PN)-x(PN-1))2+(y(PN)-y(PN-1))2+(z(PN)-z(PN-1))2)
    因此:首先将球面坐标变换为笛卡尔坐标,然后从质心开始,至少分两步(第2步和第3步)找到距离前一点最远的点。只要距离增加,您就可以重复步骤3,也许重复次数最多,但这不会使您偏离局部最大值。如果这些点分布在地球上,从质量中心开始也没有多大帮助

    编辑2:

    我学到了足够的R来写下算法的核心(数据分析的好语言!)

    对于平面近似,忽略λ=±180°线周围的问题:

    # input: lng, lat (vectors)
    rad = pi / 180;
    x = (lng - mean(lng)) * cos(lat * rad)
    y = (lat - mean(lat))
    i = which.max((x - mean(x))^2 + (y       )^2)
    j = which.max((x - x[i]   )^2 + (y - y[i])^2)
    # output: i, j (indices)
    
    在我的电脑上,查找1000000个点的索引
    i
    j
    只需不到一秒钟。
    以下3D版本稍慢,但适用于任何点分布(当λ=±180°线交叉时,无需修改):

    根据数据和要求,
    k
    的计算可以省略(即,结果可以由
    i
    j
    给出)。另一方面,我的实验表明,计算进一步的指数是无用的

    应记住,在任何情况下,结果点之间的距离都是一个估计值,是集合“直径”的下限,尽管它通常是直径本身(频率取决于数据)

    编辑3:

    不幸的是,在极端情况下,平面近似的相对误差可能高达1-1/√3.≅ 42.3%,这可能是不可接受的,即使非常罕见。该算法可以修改,以便有一个大约20%的上限,这是我用指南针和直尺推导出来的(解析解很麻烦)。修改后的算法找到一对具有局部最大距离的点,然后重复相同的步骤,但这次从第一对点的中点开始,可能会找到另一对点:

    # input: lng, lat
    rad = pi / 180
    x = (lng - mean(lng)) * cos(lat * rad)
    y = (lat - mean(lat))
    i.n_1 = 1 # n_1: n-1
    x.n_1 = mean(x)
    y.n_1 = 0 # = mean(y)
    s.n_1 = 0 # s: square of distance
    repeat {
       s = (x - x.n_1)^2 + (y - y.n_1)^2
       i.n = which.max(s)
       x.n = x[i.n]
       y.n = y[i.n]
       s.n = s[i.n]
       if (s.n <= s.n_1) break
       i.n_1 = i.n
       x.n_1 = x.n
       y.n_1 = y.n
       s.n_1 = s.n
    }
    i.m_1 = 1
    x.m_1 = (x.n + x.n_1) / 2
    y.m_1 = (y.n + y.n_1) / 2
    s.m_1 = 0
    m_ok  = TRUE
    repeat {
       s = (x - x.m_1)^2 + (y - y.m_1)^2
       i.m = which.max(s)
       if (i.m == i.n || i.m == i.n_1) { m_ok = FALSE; break }
       x.m = x[i.m]
       y.m = y[i.m]
       s.m = s[i.m]
       if (s.m <= s.m_1) break
       i.m_1 = i.m
       x.m_1 = x.m
       y.m_1 = y.m
       s.m_1 = s.m
    }
    if (m_ok && s.m > s.n) {
       i = i.m
       j = i.m_1
    } else {
       i = i.n
       j = i.n_1
    }
    # output: i, j
    
    #输入:液化天然气,纬度
    rad=pi/180
    x=(液化天然气-平均值(液化天然气))*cos(纬度*rad)
    y=(横向-平均横向)
    i、 n_1=1#n_1:n-1
    x、 n_1=平均值(x)
    y、 n_1=0#=平均值(y)
    s、 n_1=0#s:距离的平方
    重复{
    s=(x-x.n_1)^2+(y-y.n_1)^2
    i、 n=哪个最大值
    x、 n=x[i.n]
    y、 n=y[i.n]
    s、 n=s[i.n]
    
    如果(s.n这里有一个简单的例子,它不能很好地扩展(如您所说),但可能有助于在R中构建解决方案

    ## lonlat points
    n <- 100
    d <- cbind(runif(n, -180, 180), runif(n, -90, 90))
    
    
    library(sp)
    ## distances on WGS84 ellipsoid
    x <- spDists(d, longlat = TRUE)
    
    ## row, then column index of furthest points
    ind <- c(row(x)[which.max(x)], col(x)[which.max(x)])
    
    ## maps
    library(maptools)
    data(wrld_simpl)
    plot(as(wrld_simpl, "SpatialLines"), col = "grey")
    
    points(d, pch = 16, cex = 0.5)
    
    ## draw the points and a line between  on the page
    points(d[ind, ], pch = 16)
    lines(d[ind, ], lwd = 2)
    
    
    ## for extra credit, draw the great circle on which the furthest points lie
    library(geosphere)
    
    
    lines(greatCircle(d[ind[1], ], d[ind[2], ]), col = "firebrick")
    
    ##lonlat points
    n定理#1:沿地球表面任意两个大圆距离的顺序与穿过地球的点之间直线距离的顺序相同

    因此,把你的车床长
    ## lonlat points
    n <- 100
    d <- cbind(runif(n, -180, 180), runif(n, -90, 90))
    
    
    library(sp)
    ## distances on WGS84 ellipsoid
    x <- spDists(d, longlat = TRUE)
    
    ## row, then column index of furthest points
    ind <- c(row(x)[which.max(x)], col(x)[which.max(x)])
    
    ## maps
    library(maptools)
    data(wrld_simpl)
    plot(as(wrld_simpl, "SpatialLines"), col = "grey")
    
    points(d, pch = 16, cex = 0.5)
    
    ## draw the points and a line between  on the page
    points(d[ind, ], pch = 16)
    lines(d[ind, ], lwd = 2)
    
    
    ## for extra credit, draw the great circle on which the furthest points lie
    library(geosphere)
    
    
    lines(greatCircle(d[ind[1], ], d[ind[2], ]), col = "firebrick")