Быстрый алгоритм поиска X ближайших точек к заданной точке на плоскости

Я хотел бы найти быстрый алгоритм, чтобы найти X ближайших точек к данной точке на плоскости.

на самом деле мы имеем дело с не слишком большим количеством точек (между 1,000 и 100,000), но мне нужны X ближайших точек для каждой из этих точек. (где x обычно будет между 5 и 20.)

Мне нужно написать это на C#.

немного больше контекста об использовании: эти точки являются координатами на карте. (Я знаю, это означает, что мы не совсем говоря о самолете, но я надеюсь избежать проблем с проекцией.) В конечных точках, которые имеют много других точек, близких к ним, должны отображаться красным цветом, точки, которые имеют не слишком много точек, близких к ним, должны отображаться зеленым цветом. Между этими двумя extremees точки на градиент.

4 ответов


вам нужна структура данных, подходящая для организации точек на плоскости. K-D-дерево часто используется в таких ситуациях. См.К-Д Дерево на Википедии.

здесь я нашел общее описание Геометрические Алгоритмы


обновление

я портировал Java-реализацию KD-дерева на C#. Пожалуйста, смотрите пользователь: Ojd / KD-Tree на RoboWiki. Вы можете скачать код там или вы можете скачать CySoft.Коллекции.zip С Домашняя страница (только загрузка, без документов).


для данной точки (не для всех) и поскольку количество точек не является экстремальным, вы можете рассчитать расстояние от каждой точки:

var points = new List<Point>();
Point source = ...
....
var closestPoints = points.Where(point => point != source).
                           OrderBy(point => NotReallyDistanceButShouldDo(source, point)).
                           Take(20);

private double NotReallyDistanceButShouldDo(Point source, Point target)
{
   return Math.Pow(target.X - source.X, 2) + Math.Pow(target.Y - source.Y, 2);
}

(я использовал x = 20)

расчет основан на двойниках, поэтому fpu должен быть в состоянии сделать достойную работу здесь. Обратите внимание, что вы можете получить лучшую производительность, если Point является классом, а не структурой.


вам нужно создать функцию расстояния, затем вычислить расстояние для каждой точки и отсортировать результаты и взять первый x.

Если результаты должны быть 100% точными, то вы можете использовать стандартную функцию расстояния:

d = SQRT ((x2 - x1)^2 + (y2 - y1)^2)


чтобы сделать это более эффективным. допустим, расстояние k. Возьмите все точки с координатами x между x-k и x+k. аналогично возьмем y-k и y+k. Таким образом, вы удалили все лишние координаты. теперь сделайте расстояние (x-x1)^2 + (y-y1)^2. Сделайте на них минимальную кучу из k элементов и добавьте их в кучу, если новая точка