Использование пространственного индекса для поиска точек в пределах досягаемости друг друга - PullRequest
2 голосов
/ 03 апреля 2019

Я пытаюсь найти структуру пространственного индекса, подходящую для конкретной задачи: используя структуру данных объединения-поиска, я хочу соединить \ связать точки, которые находятся в определенном диапазоне друг от друга.У меня много точек, и я пытаюсь оптимизировать существующее решение, используя лучший пространственный индекс.

Сейчас я использую простую двумерную сетку, индексирующую каждый квадрат ширины [пороговое расстояние]моя карта точек, и я ищу потенциальные объединения, ища точки в соседних квадратах в сетке.

Затем я вычисляю квадрат евклидова расстояния до комбинаций соседних ячеек, который я сравниваю с моим квадратным порогом, и яиспользуйте структуру union-find (оптимизированную с использованием сжатия пути и т. д.) для построения групп точек.

Вот несколько иллюстраций метода.Одиночные черные точки фактически представляют собой набор точек, принадлежащих ячейке сетки, а исходящие цветные стрелки представляют фактическое сравнение расстояний с внешними точками.

Simple grid index

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

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

Проблема в том, что этот подход еще недостаточно близок к тому, чтобы быть достаточно быстрым, и я пытаюсь заменить метод «индекса пространственной сетки» чем-то, что может быть быстрее.

Я посмотрелв квадродерево в качестве подходящего пространственного индекса для этой задачи, но я не думаю, что он подходит для решения этой проблемы (я не вижу способа выполнить повторные проверки «соседей» для конкретной ячейки более эффективно с использованием квадродерева), новозможно я ошибаюсь в этом.

Поэтому я ищу лучший алгоритм \ структуру данных, чтобы эффективно индексировать мои точки и запрашивать их о близости.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 05 апреля 2019

У меня есть несколько комментариев:

1) Я думаю, что ваша проблема эквивалентна «пространственному соединению».Пространственное соединение принимает два набора геометрий, например, набор R прямоугольников и набор P точек, и находит для каждого прямоугольника все точки в этом прямоугольнике.В вашем случае R будет прямоугольниками (длина ребра = 2 * максимальное расстояние) вокруг каждой точки и P набором ваших точек.Поиск пространственного соединения может дать вам несколько полезных ссылок.

2) Возможно, вы захотите взглянуть на кривые заполнения пространства.Кривые заполнения пространства создают линейный порядок для набора пространственных объектов (точек) со свойством, указывающим, что замыкание в линейном порядке обычно также близко в пространстве (и наоборот).Это может быть полезно при разработке алгоритма.

3) Посмотрите на OpenVDB .OpenVDB имеет структуру пространственного индекса, которая оптимизирована для прохождения «воксельных» ячеек и их соседей.

4) Посмотрите на PH-Tree (отказ от ответственности: это мое собственноепроект).PH-дерево в некоторой степени похоже на дерево квадрантов, но использует битовые операции низкого уровня для оптимизации навигации.Он также Z-упорядочен / упорядочен по Мортену (см. Кривые заполнения пространства выше).Вы можете создать оконный запрос для каждой точки, который возвращает все точки в этом прямоугольнике.Насколько мне известно, PH-дерево является самой быстрой структурой индекса для такого рода операций, особенно если у вас обычно есть только 9 точек в прямоугольнике.Если вас интересует код, реализация V13, вероятно, самая быстрая, однако V16 должно быть намного проще для понимания и изменения.Я попробовал на своем довольно старом настольном компьютере, используя около 1 000 000 точек, я могу выполнять около 200 000 запросов окна в секунду, поэтому для поиска всех соседей для каждой точки потребуется около 5 секунд.

Если вы используете Java,Моя коллекция пространственных индексов также может быть полезна.

1 голос
/ 03 апреля 2019

Стандартным подходом к этому является алгоритм "s weep and prune ". Сортируйте все точки по координате X, затем итерируйте их. При этом сохраняйте самый низкий индекс точки, который находится в пределах порогового расстояния (в X) от текущей точки. Точки в этом диапазоне являются кандидатами на слияние. Затем вы делаете ту же самую сортировку по Y. Тогда вам нужно только проверить евклидово расстояние для тех пар, которые обнаружились как в скане X, так и в Y.

Обратите внимание, что с вашим текущим подходом поиска объединения вы можете в конечном итоге объединить точки, которые находятся довольно далеко друг от друга, если есть множество соседних точек, "соединяющих" их. Таким образом, ваш основной подход - объединение групп точек на основе близости - может вызвать произвольную величину ошибки расстояния, а не только пороговое расстояние.

...