Быстрый алгоритм поиска 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 элементов и добавьте их в кучу, если новая точка