2012-02-22 12 views
7

Mam zestaw punktu (x, y) na płaszczyźnie 2d. Biorąc pod uwagę punkt (x0, y0) i liczbę k, jak znaleźć k-tego najbliższego sąsiada (x0, x0) w zestawie punktów. Szczegółowo, zestaw punktów jest reprezentowany przez dwie tablice: x i y. Punkt (x0, y0) jest podany przez indeks i0. Oznacza to x0 = x (i0) i y0 = y (i0).jak znaleźć k-najbliższego sąsiada punktu w zestawie punktu

Czy istnieje jakaś funkcja lub coś w Matlab pomaga mi ten problem. Jeśli Matlab nie ma takiej funkcji, możesz zaproponować inne skuteczne sposoby.

EDIT: Muszę obliczyć ten rodzaj odległości dla każdego punktu (x0, y0) w zbiorze. Rozmiar zestawu wynosi około 1000. Wartość k powinna wynosić około sqrt (1500). Najgorsze jest to, że robię to wiele razy. Przy każdej iteracji zestaw ulega zmianie i ponownie obliczam odległości. Tak więc czas pracy jest krytycznym problemem.

Odpowiedz

6

jeśli zrobisz to czek na wielu punktach może chcesz zbudować między pierwszym punktem

squareform(pdist([x y])) 
+0

Tak. Zrobię to dla każdego punktu w secie. Tak więc pewien rodzaj tabeli odległości pomógłby zaoszczędzić czas pracy. Dowiesz się, jak działa funkcja kwadratów w moim problemie. Dziękuję Ci bardzo. –

+0

funkcja jest w rzeczywistości pdist, to tylko kwadratowa matryca z wyjściowego wektora pdisty – zamazalotta

+0

dzięki zamazalotta. Mam to. –

4

Jeśli masz przybornik statystyk, możesz użyć funkcji knnsearch.

+0

odległość stół knnsearch wydaje się być rozwiązaniem, ale nie jestem pewien, jak zastosować knnsearch do mojego problem dokładnie. Znajdę to. W każdym razie, możesz podać mi więcej szczegółów na temat sposobu korzystania z knnsearch. Dziękuję Ci bardzo. –

+0

Czy obejrzałeś pomoc Matlaba (dodano link do powyższej odpowiedzi)? – 3lectrologos

+0

Przeczytałem dokument online o knnsearch, ale jest to dla mnie trochę skomplikowane i naprawdę nie mam zbyt wiele czasu, aby go zrozumieć i wykorzystać. Próbowałem prostszego podejścia. Trwa to dłużej, ale najpierw spróbuję tego podejścia. Dziękuję za pomoc. –

2

algorytm brute force byłoby coś takiego:

array x[n] =() 
array y[n] =() 
array d[n] =() 

... populate x and y arrays with your n points ... 

/* step over each point and calculate its distance from (x0, y0) */ 
for i = 1 to n 
do 
    d[i] = distance((x0, y0), (x[i], y[i]) 
end 

/* sort the distances in increasing order */ 
sort(d) 

/* the k'th element of d, is the k'th nearest point to (x0, y0) */ 
return d[k] 
+0

dzięki za pomoc! –

2

Podejście brute force wygląda mniej więcej tak:

%Create some points 
n = 10; 
x = randn(n,1); 
y = randn(n,1); 

%Choose x0 
ix0 = randi(n); 

%Get distances 
d = sqrt(... 
    (x - x(ix0)).^2 + ... 
    (y - y(ix0)).^2); 

%Sort distances 
[sorted_Dstances, ixSort] = sort(d); 

%Get kth point 
k = 3; 
kth = [x(ixSort(k+1)); y(ixSort(k+1))]; %+1 since the first element will always be the x0 element. 
+0

Nie powinieneś usunąć samego elementu? Pomyśl o przypadku k = 1 –

+0

Dobra uwaga. Generalnie nie lubię zmieniać wielkości wektorów dopasowujących takich jak ten. Może dodać "+1" do końcowego indeksowania. EDYCJA: chociaż pozostawia lukę, jeśli istnieje punkt identyczny z punktem początkowym. Jeśli chcesz zagwarantować odpowiedź, to inny punkt, nawet jeśli jakiś punkt może być równy, wtedy potrzeba więcej pracy. – Pursuit

+0

@Pursuit nie ma sensu, aby usunąć równe punkty. jeśli masz 5 równych punktów do szukanego punktu, 3. najdalszy dystans powinien wynosić 0 – ardnew

2

Wolną i opensource VLFeat Toolbox zawiera implementację kd-drzewa, wśród innych przydatnych rzeczy.

+0

dziękuję bardzo. Przekonasz się, czy to pomoże. –