Diberikan daftar lokasi titik (lebih disukai dalam koordinat yang diproyeksikan, sehingga jaraknya mudah dihitung), masalah ini dapat diselesaikan dengan lima operasi sederhana :
Hitung jarak titik-titik.
Untuk setiap titik i, i = 1, 2, ..., identifikasi indeks titik-titik tersebut pada jarak kurang dari radius buffer (seperti 1500).
Batasi indeks tersebut menjadi i atau lebih besar.
Pertahankan hanya grup indeks berurutan pertama yang tidak memiliki jeda.
Keluarkan hitungan grup itu.
Dalam R
, masing-masing sesuai dengan satu operasi. Untuk menerapkan urutan ini pada setiap titik, akan lebih mudah untuk merangkum sebagian besar pekerjaan dalam fungsi yang kita tentukan , dengan demikian:
#
# 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)))
}
(Lihat di bawah untuk versi yang lebih efisien dari fungsi ini.)
Saya telah membuat fungsi ini cukup fleksibel untuk menerima berbagai daftar titik ( xy
) dan jarak buffer ( r
) sebagai parameter.
Biasanya, Anda akan membaca file lokasi titik (dan, jika perlu, urutkan berdasarkan waktu). Di sini, untuk menunjukkan ini dalam tindakan, kami hanya akan menghasilkan beberapa data sampel secara acak :
# 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")
Jarak tipikal mereka adalah 300 * Sqrt (2) = sekitar 500. Kami melakukan perhitungan dengan menerapkan fungsi ini ke titik-titik dalam arrayxy
(dan kemudian menempelkan hasilnya kembali ke xy
, karena ini akan menjadi format yang nyaman untuk mengekspor ke GIS ):
radius <- 1500
z <- sapply(1:n, function(u){forward(u,xy,radius)})
result <- cbind(xy, z) # List of points, counts
Anda kemudian akan menganalisis result
array lebih lanjut , baik dalam R
atau dengan menulisnya ke file dan mengimpornya ke perangkat lunak lain. Berikut adalah hasil untuk data sampel :
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
(Ingatlah bahwa penghitungan mencakup titik di mana mereka didasarkan, sehingga setiap penghitungan harus 1 atau lebih besar.)
Jika Anda memiliki ribuan titik, metode ini terlalu tidak efisien : ini menghitung terlalu banyak jarak titik-ke-titik yang tidak perlu. Tetapi karena kami telah merangkum pekerjaan dalam forward
fungsi, inefisiensi mudah untuk diperbaiki. Ini adalah versi yang akan bekerja lebih baik ketika lebih dari beberapa ratus poin terlibat:
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
}
Untuk menguji ini, saya membuat poin acak seperti sebelumnya tetapi memvariasikan dua parameter: n
(jumlah poin) dan standar deviasi mereka (hard-coded seperti 300 di atas). Deviasi standar menentukan jumlah rata-rata poin dalam setiap buffer ("rata-rata" pada tabel di bawah): semakin banyak, semakin lama algoritma ini diperlukan untuk berjalan. (Dengan algoritme yang lebih canggih, waktu tayang tidak akan terlalu tergantung pada berapa banyak poin di setiap buffer.)
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