Поиск ближайшей точки к заданной точке

Я искал все это, но я не могу найти лучший подход к этому. У меня около 22000 точек lat/lon, и я хочу найти ближайший к текущему местоположению iPhone. Я видел, как люди спрашивали о Quad Trees, Dijkstra Algorithm и пространственных базах данных. Что лучше для iPhone? Пространственные базы данных кажутся самыми легкими, но я не уверен.

РЕДАКТИРОВАТЬ: на самом деле их насчитывается более 20 000 пунктов. Вы думаете, что повторить через все это способ сделать это? Но спасибо за ваш вклад.

Спасибо.

Ответ 1

На самом деле, лучше всего использовать расчет Haversine (большой круг) для Lat/Long points, в противном случае все большие расстояния будут неправильными, особенно если вы используете простой триггер, как в Jherico answer.

Быстрый поиск предоставляет этот пример javascript:

var R = 6371; // km Radius of earth
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
        Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;

В терминах структуры данных Geohash стоит посмотреть.

Ответ 2

Если вам нужно лучше, чем O (N), вы можете получить это, только если сначала заплатите N lg N за построение пространственного хэша какого-то рода (квадрант, октет, хеш-сетку или аналогичный). Тогда каждый тест будет приблизительно равен O (lg N), и может быть намного лучше, если кэшировать последнее выбранное вами местоположение, если есть много согласованности (как правило, есть).

Я бы, вероятно, построил октет в пространстве Эйлера (геоцентрическое, XYZ), потому что это позволяет мне получить "истинное" расстояние, а не "искаженное" расстояние лат /lon. Однако на практике квадратное дерево в пространстве lat/lon, вероятно, будет работать достаточно хорошо. После того, как вы попали, вы держитесь за это дерево node (при условии, что дерево не будет перестроено во время выполнения), а следующий запрос начнет идти от этого дерева node, и только нужно беспокоиться о узлах, которые может быть ближе, если предыдущая точка отошла дальше от предыдущего ответа.

Ответ 3

Как вы на iPhone, вы можете использовать CoreLoaction для выполнения географического расстояния - используя CLLocation – getDistanceFrom:

У меня возникнет соблазн использовать линейный поиск грубой силы, хотя все 2k точек над, если это недостаточно быстро, переключитесь на нечто вроде GeoHash для хранения метаданных против ваших точек для поиска.

Ответ 4

Почему бы не разбивать земной шар на регионы? (Think hexes.) Затем, когда вы добавляете точки в свой список или в один большой цикл предварительной обработки, для каждой точки сохраняйте область, в которой она находится.

Затем при поиске точек вблизи точки A в шестнадцатеричном X вам нужно только проверить точки в шестнадцатеричном X и максимум на 3 соседних гекса.

Если это еще слишком много точек для проверки, добавьте субрегионы.

Ответ 5

вы должны учесть, что для использования Dijkstra вы должны знать свою позицию node на графике, а это проблема, которую вы пытаетесь решить; вы не находитесь на графике, но хотите узнать ближайший к вам пункт

так просто, как сказал вам Хаос, вы должны рассчитать все расстояния между вашей позицией и всеми 20 000 точками, а затем отсортировать их

Ответ 6

Я думаю, что этот алгоритм работает:

Создать массив, отсортированный по широте Создайте массив, отсортированный по долготе

Чтобы найти ближайший, сначала найдите ближайший по широте по выполняя двоичный поиск в широтном массиве. Сделайте то же самое для массива долготы. Теперь у вас есть 2 балла, один ближе всего по широте, другой ближе по долготе. Вычислите расстояния до каждой точки с помощью теоремы пифагора. Ближайшая точка выигрывает.

Роджер