找到近似规则网格点子集的周长

时间:2015-02-16 09:26:35

标签: r computational-geometry r-grid

让我们考虑一组二维近似规则的网格。这些网格与相邻网格相邻(相邻网格具有一个或多个相同顶点)。以下是10个网格的样本,顶点坐标(经度,纬度)如下

A<-

        lon    lat
        [,1]     [,2]
  [1,] 85.30754 27.91250
  [2,] 85.32862 27.95735
  [3,] 85.34622 27.89880
  [4,] 85.36732 27.94364
  [5,] 85.34958 28.00202
  [6,] 85.38831 27.98830
  [7,] 85.38487 27.88508
  [8,] 85.40598 27.92991
  [9,] 85.42353 27.87134
 [10,] 85.44466 27.91616
 [11,] 85.42698 27.97456
 [12,] 85.46567 27.96081
 [13,] 85.48334 27.90239
 [14,] 85.50437 27.94703
 [15,] 85.48645 28.00502
 [16,] 85.52517 27.99123
 [17,] 85.52198 27.88862
 [18,] 85.54302 27.93325
 [19,] 85.56384 27.97745

上述样本点集(顶点)的散点图:

enter image description here

网格的构造如下图所示。

enter image description here

我的问题是如何获得周长(红色轮廓通过所有边界点)??

注意:图1中的红色环绕点(1,3,7,9,10,13,17,18,19,16,15,12,11,6,5,2)是边界点

注意:观察到网格的边长小于6000米,所有网格的对角线长度都超过6000米。

我正在使用R中distHaversine包函数中的geosphere来查找两点之间的距离。

3 个答案:

答案 0 :(得分:3)

解决此问题的一种方法是计算点周围的alpha船体。

alphahull包可以执行此操作。该软件包具有出色的文档,包括动画,http://yihui.name/en/2010/04/alphahull-an-r-package-for-alpha-convex-hull/

值得一看这篇文档,特别是了解alpha参数的含义。

首先,复制您的数据

A <- read.table(header=TRUE, text="
lon    lat
[1,] 85.30754 27.91250
[2,] 85.32862 27.95735
[3,] 85.34622 27.89880
[4,] 85.36732 27.94364
[5,] 85.34958 28.00202
[6,] 85.38831 27.98830
[7,] 85.38487 27.88508
[8,] 85.40598 27.92991
[9,] 85.42353 27.87134
[10,] 85.44466 27.91616
[11,] 85.42698 27.97456
[12,] 85.46567 27.96081
[13,] 85.48334 27.90239
[14,] 85.50437 27.94703
[15,] 85.48645 28.00502
[16,] 85.52517 27.99123
[17,] 85.52198 27.88862
[18,] 85.54302 27.93325
[19,] 85.56384 27.97745")

现在计算并绘制阿尔法船体。您必须提供alpha值。我不得不尝试找到一个足够小的值来捕捉ouline。

library("alphahull")
hull <- with(A, ahull(lat, lon, alpha=0.033))
plot(hull)

enter image description here

答案 1 :(得分:1)

概述:距离小于6000米的所有点对形成网格方格的图形。构造该图,然后找到与正方形同构的所有子图(大小为4的循环)。外部边缘看起来比内部边缘少,因为它们只是一个正方形的一部分(内部边缘由多个正方形共享)。因此找到所有内部边并删除它们,然后遍历结果图,这应该是一个简单的循环。

代码:

library(igraph); library(geosphere)

# main function
perimeterGrid <- function(pts, maxdist=6000, mindist=1){
    g = edgeP(makegrid(pts, maxdist=maxdist, mindist=mindist))
    loop = graph.dfs(minimum.spanning.tree(g),1)$order
    cbind(V(g)$x, V(g)$y)[loop,]
}

# haversine distance matrix
dmat <- function(pts){
    n=nrow(pts)
    do.call(rbind,lapply(1:n,function(i){distHaversine(pts[i,],pts)}))
}

# make the grid cells given a maxdist (and a mindist to stop self-self edges)    
makegrid <- function(pts, maxdist=6000,  mindist=1){
    dists = dmat(pts)
    g = graph.adjacency(dists<maxdist & dists>mindist,
        mode="undirected")
    V(g)$x=pts[,1]
    V(g)$y=pts[,2]
    g
}

# clever function that does the grid edge count etc
edgeP <- function(g){
    # find all the simple squares
    square=graph.ring(4)
    subs = graph.get.subisomorphisms.vf2(g,square)
    # expand all the edges
    subs = do.call(rbind, lapply(subs, function(s){
        rbind(s[1:2], s[2:3], s[3:4], s[c(4,1)])
    }))
    # make new graph of the edges of all the squares
    e = graph.edgelist(subs,directed=FALSE)
    # add the weight as the edge count
    E(e)$weight=count.multiple(e)

    # copy the coords from the source
    V(e)$x=V(g)$x
    V(e)$y=V(g)$y

    # remove multiple edges
    e=simplify(e)

    # internal edges now have weight 256.
    e = e - edges(which(E(e)$weight==256))
    # internal nodes how have degree 0
    e = e - vertices(degree(e)==0)
    return(e)
}

用法:

 plot(pts)
 polygon(perimeterGrid(pts),lwd=2)

结果:

enter image description here

警告:

这是在带有孔的网格片段上或网格单元仅在单个角点处接触时未经测试的。也许这不可能发生。此外,我不确定算法的效率如何,但似乎很快。

答案 2 :(得分:1)

由于点集是一个网格,或者至少非常接近网格,似乎一个好的方法是利用Delaunay三角剖分。

  1. 找到Delaunay三角剖分。
  2. 找到两个有效的边角。如果网格是轴对齐的,那么这些将是垂直和水平线。
  3. 根据边缘的角度,删除超出误差容差的所有边,使其成为网格上的有效边。几度的容错可能就足够了。
  4. 绕着剩下的边缘走动以找到周边。最左边或最右边的点是开始散步的好地方。
  5. 效果应为O(N log N)