点の位置のリストが与えられると(距離の計算が容易になるように、できれば投影座標で)、この問題は5つの簡単な操作で解決できます。
点間距離を計算します。
各ポイントi、i = 1、2、...について、バッファー半径よりも短い距離(1500など)にあるポイントのインデックスを特定します。
それらのインデックスをi以上に制限します。
ブレークのない最初の連続するインデックスのグループのみを保持します。
そのグループの数を出力します。
ではR
、これらのそれぞれが1つの操作に対応しています。このシーケンスを各ポイントに適用するには、定義する関数内にほとんどの作業をカプセル化すると便利です。
#
# forward(j, xy, r) counts how many contiguous rows in array xy, starting at index j,
# are within (Euclidean) distance r of the jth row of xy.
#
forward <- function(j, xy, r) {
# Steps 1 and 2: compute an array of indexes of points within distance r of point j.
i <- which(apply(xy, 1, function(x){sum((x-xy[j,])^2) <= r^2}))
# Step 3: select only the indexes at or after j.
i <- i[i >= j]
# Steps 4 and 5: retain only the first consecutive group and count it.
length(which(i <= (1:length(i) + j)))
}
(この関数のより効率的なバージョンについては、以下を参照してください。)
この関数は、さまざまなポイントリスト(xy
)とバッファー距離(r
)をパラメーターとして受け入れるのに十分な柔軟性を備えています。
通常、ポイントの場所のファイルを読み取ります(必要に応じて、時間順に並べ替えます)。ここでは、この動作を示すために、サンプルデータをランダムに生成します。
# Create sample data
n<-16 # Number of points
set.seed(17) # For reproducibility
xy <- matrix(rnorm(2*n) + 1:n, n, 2) * 300
#
# Display the track.
plot(xy, xlab="x", ylab="y")
lines(xy, col="Gray")
典型的な間隔は300 * Sqrt(2)=約500 です。この関数を配列内のポイントに適用して計算を行いますxy
(そして、結果をに戻しxy
ます。これは、GISへのエクスポートに便利な形式であるためです。 ):
radius <- 1500
z <- sapply(1:n, function(u){forward(u,xy,radius)})
result <- cbind(xy, z) # List of points, counts
次に、result
配列をさらに分析しR
ます。これを、ファイルに書き込むか、ファイルに書き込んで、他のソフトウェアにインポートします。 サンプルデータの結果は次のとおりです。
z
[1,] -4.502615 551.5413 4
[2,] 576.108979 647.8110 3
[3,] 830.103893 1087.7863 4
[4,] 954.819620 1390.0754 3
...
[15,] 4977.361529 4146.7291 2
[16,] 4783.446283 4511.9500 1
(カウントにはそれらが基づいているポイントが含まれるため、各カウントは1以上でなければなりません。)
何千ものポイントがある場合、この方法は非効率的です。不要なポイント間距離を計算しすぎます。ただし、作業をforward
関数内にカプセル化しているため、非効率は簡単に修正できます。 以下は、数百以上のポイントが関係している場合によりよく機能するバージョンです。
forward <- function(j, xy, r) {
n <- dim(xy)[1] # Limit the search to the number of points in xy
r2 <- r^2 # Pre-compute the squared distance threshold
z <- xy[j,] # Pre-fetch the base point coordinates
i <- j+1 # Initialize an index into xy (just past point j)
# Advance i while point i remains within distance r of point j.
while(i <= n && sum((xy[i,]-z)^2) <= r2) i <- i+1
# Return the count (including point j).
i-j
}
これをテストするために、以前と同じようにランダムなポイントを作成しましたが、2つのパラメーターn
(ポイントの数)とそれらの標準偏差(上記の300としてハードコード化)を変化させました。標準偏差は、各バッファー内の平均ポイント数を決定します(以下の表の「平均」)。この数が多いほど、このアルゴリズムの実行に時間がかかります。(より高度なアルゴリズムを使用すると、ランタイムは各バッファーにあるポイントの数にそれほど依存しません。)次に、いくつかのタイミングを示します。
Time (sec) n SD Average Distances checked per minute
1.30 10^3 3 291 13.4 million
1.72 10^4 30 35.7 12.5
2.50 10^5 300 3.79 9.1
16.4 10^6 3000 1.04 3.8