2013-05-08 5 views
7

現時点では、ポイントフィーチャ(ポイントフィーチャには142ポイント、マルチポリゴン(約10))が含まれています。私はすべての単一のポイントとRの最も近いポリゴンフィーチャの間の距離を計算したいと思っています。ポイントフィーチャから最近傍ポリゴンまでの距離R

私の現在のアプローチは退屈で、少し長いです。私は現在、すべての単一点とすべての単一ポリゴンの間の距離を計算することを計画しています。たとえば、142点とPol​​ygon Aの距離、142点とPol​​ygon Bの距離、142点とPol​​ygon Cの距離などを計算します。次に、これらの距離計算のサンプルコードを示します。

dist_cen_polya <- dist2Line(centroids_coor, polygonA_shp) 

これらの計算を行った後、すべての単一点と最も近いポリゴンの間の最小/最短距離を選択するコードを作成します。問題は、この手順が面倒であることです。

計算の労力と計算時間を最小限に抑えるパッケージ/コードを知っている人はいますか?私は本当に一番近いポリゴンフィーチャをポイントするか、ポイントと関心のあるすべてのポリゴンの間の距離を計算するパッケージを使用したいと思いますか?

ありがとうございます。

+0

最後の段落で判断すると、数学的な問題があるように見えます。フォローの比較セットを作るよりも優れたアルゴリズムを見つけるのは正しいでしょうか?それは数学SEの方が適しているかもしれません。 – Frank

+0

'spatstat'パッケージはあなたが望むことをすることができます。私はそのツールセットの専門家ではないので、確かに確認することはできません。 –

+0

ここに含まれる数字では、10ポ​​リゴンと142ポイント(1420距離!)のブルートフォースが問題になるはずはありません。 'plyr'パッケージは、あなたがループを気に入らない場合に役立ちます。 – Gregor

答えて

13

ここでは、rgeosトポロジライブラリでgDistance関数を使用しています。私はブルートフォースダブルループを使用していますが、それは驚くほど速いです。 142ポイントと10ポリゴンでは2秒以下です。私はループを実行するためにもっと優雅な方法があると確信しています。

require(rgeos) 

    # CREATE SOME DATA USING meuse DATASET 
    data(meuse) 
     coordinates(meuse) <- ~x+y 
     pts <- meuse[sample(1:dim(meuse)[1],142),] 
    data(meuse.grid) 
     coordinates(meuse.grid) = c("x", "y") 
     gridded(meuse.grid) <- TRUE 
      meuse.grid[["idist"]] = 1 - meuse.grid[["dist"]]  
     polys <- as(meuse.grid, "SpatialPolygonsDataFrame") 
      polys <- polys[sample(1:dim(polys)[1],10),] 
    plot(polys) 
     plot(pts,pch=19,cex=1.25,add=TRUE)  

    # LOOP USING gDistance, DISTANCES STORED IN LIST OBJECT 
    Fdist <- list() 
     for(i in 1:dim(pts)[1]) { 
     pDist <- vector() 
      for(j in 1:dim(polys)[1]) { 
      pDist <- append(pDist, gDistance(pts[i,],polys[j,])) 
      } 
     Fdist[[i]] <- pDist 
     } 

    # RETURN POLYGON (NUMBER) WITH THE SMALLEST DISTANCE FOR EACH POINT 
    (min.dist <- unlist(lapply(Fdist, FUN=function(x) which(x == min(x))[1]))) 

    # RETURN DISTANCE TO NEAREST POLYGON 
    (PolyDist <- unlist(lapply(Fdist, FUN=function(x) min(x)[1]))) 

    # CREATE POLYGON-ID AND MINIMUM DISTANCE COLUMNS IN POINT FEATURE CLASS 
    [email protected] <- data.frame([email protected], PolyID=min.dist, PDist=PolyDist) 

    # PLOT RESULTS 
    require(classInt) 
    (cuts <- classIntervals([email protected]$PDist, 10, style="quantile")) 
     plotclr <- colorRampPalette(c("cyan", "yellow", "red"))(20) 
     colcode <- findColours(cuts, plotclr) 
    plot(polys,col="black") 
     plot(pts, col=colcode, pch=19, add=TRUE) 

min.distベクトルは、ポリゴンの行番号を表します。たとえば、このベクトルをそのまま使用して、最も近いポリゴンをサブセット化することができます。

near.polys <- polys[unique(min.dist),] 

PolyDistベクトルには、フィーチャの投影単位の実際のデカルト距離が含まれています。

+0

@ Jeffrey Evans私は本当にこのソリューションに感謝します。コードで自分のデータを使用しましたが、実際にはうまくいきます!ありがとう!! – user1738753

+5

@ Jeffrey Evans、gDistanceのbyid引数はダブルループと同じ結果になると思われますか? 'gDistance(pts、polys、byid = T)' - 最小距離を得るために操作できる10 x 142行列。 – CCID

1

多角形にはかなりの線があります。ポイントがポリゴン内にある場合、またはエッジにある場合、ポリゴン間の距離はゼロです。

だから、実際には2例を探しています:

  1. チェックポイントは、任意の多角形の内側にある場合(これは、単一のポリゴン
  2. 、より多くのは、すべてのエッジのコレクションを取得し、それぞれを計算するかもしれない覚えていますエッジからの点の距離。 最も近い距離はあなたにエッジがあまりにも属しているポリゴンの距離を与える。

は、これは我々が考える場合には、ポリゴンあたり10のエッジがO(10 * 10を取るという単純なアルゴリズムです。 )* 142すべてのあなたのポイント。つまり、100 * 142 = 14200の操作になります。 => O(m * deltaE)* n(mはポリゴンの数、deltaEはポリゴンあたりの平均エッジ数、nは点の数)

これをスピードアップできるかどうかを確認します。まず最初に、ポリゴンごとにバウンディングボックスチェックやバウンディングサークルを使用できるということです。

もう1つのアイデアは、一連の角度に対して各ポリゴンの最も近いエッジを準備することです。たとえば、8つの角度(45°ごと)がある場合、リストから他の辺が優先されるすべての辺を削除することができます(したがって、削除された辺の任意の点は、同じ辺の他の点ポリゴン。

通常、このように複雑さを大幅に減らすことができます。矩形を考えると、4つではなく1つまたは2つの辺があります。通常の8つのエッジポリゴンを考えると、通常はポリゴンごとに1つまたは2つ、最大3つの辺で表示されます

各エッジに法線ベクトルを追加すると、ポイントが内側にあり、スキャンラインなどのチェックを実行する必要がありますか(またはそのコンビ)を確認してください。

また、等間隔のマンノーで2次元空間をxとyで分けるようなマッピング索引も可能です。これで、9つのセクターにあるポリゴンをテストするだけです。

次のバージョンでは、各ノードの各境界ボックス(円)が最小予想距離と最大予想距離を確認する必要があるRツリーを使用している可能性があります。したがって、他のノードの最大距離よりもはるかに大きな最小距離をもたらすノードのポリゴンをチェックする必要はない。

マップデータを持っているように、注文のようなツリーがある場合はもう1つのことです。ストリートマップでは、常に世界 - >地域 - >国 - >郡 - >都市 - >都市部門 - > ...

これは、世界中の何百万もの地図ポリゴンの妥当な時間はほとんど< 10msです。

ここでは、多くのオプションがあります。ポリゴンリストを前処理して、ポリゴンのバイナリスペースパーティションツリーを使用するか、角度のあるアプローチを使用するか、さらにはさらに魅力的なものに進むこともできます。それはあなた次第です。私は、O(log(n)* log(deltaE))がO(log(n))となるような対数的な範囲で平均的な複雑さを行うことによって、

関連する問題