Python kdtree найти «n» ближайших соседних групп (координат)

1

Задача. Если задана координата X, найдите "n" ближайшую линию-многоугольник для координаты X, а не только "n" ближайших точек. Пример: https://i.imgur.com/qyxV2MF.png


У меня есть группа пространственных линейных полигонов, которые могут иметь более двух координат. Их координаты хранятся в (Scipy) KDtree, чтобы включить поиск NN.

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

Чтобы достичь "n" ближайших линий, мне нужно увеличить "i". Моя проблема в том, что "i" может быть непредсказуемым, потому что количество коордов варьируется между каждым линейным полигоном. Например, многоугольник линии может быть представлен двумя координатами, а другой может быть представлен с использованием 10 координат. Большую часть времени мне нужно только 2 ближайших соседних линейных полигона из точки X.

В примере изображения мне нужны строки A и B в качестве результата. Даже с "i" = 3 будет найдена только строка A, потому что A1, A2, A3 являются ближайшими соседями к X.


Вопрос: Есть ли способ группировать координаты формы вместе, а затем выполнять поиск NN для получения "n" уникальных форм? (кроме грубой форсировки "i" для обеспечения "n" уникальных форм)


Текущий псевдоод обходного пути:

found = []
while True:
    if first_loop:
        result = look up N nearest coords
    else:
        result = look up Nth nearest coord

    look up shapes using result and append to found
    perform de-duplication of found

    if len(found) >= required:
         return found
    else:
         N = N+1 # to check the Nth neighbor next iteration
  • 0
    Будет ли смысл преобразовывать ваши группы в «средние / средние баллы»? Таким образом, вы должны перевести свою задачу в точку NN, сопоставить k ближайших точек, а затем развернуть эти совпадения в исходные группы.
  • 0
    Привет, randomir, я подумал о том, чтобы представлять каждую фигуру, используя отдельные координаты. Тем не менее, мои геопространственные формы также различаются по размеру, поэтому использование центроидов для ближайших соседей может не дать желаемого результата (мне нужно максимум 4 для каждого запроса). Представьте себе сеть дорог в форме звезды, где я нахожусь в центре, и есть 5 дорог (фигур), разветвляющихся. Технически расстояние между 5 дорогами и мной одинаковое. Но если мы будем использовать центроиды, длина дороги будет иметь значение.
Теги:
algorithm
data-structures
nearest-neighbor
kdtree

2 ответа

0
Лучший ответ

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

Пусть имеют следующие структуры данных: 1. Словарь из линейных полигонов в точки 2. Другой словарь из точек в линейные многоугольники (или, что то же самое, одно двунаправленную карту из bidict вместо пары словарей) 3. посещенный булевой массив с размером, равным количеству точек

Теперь следующий алгоритм должен решить вашу проблему (может быть эффективно реализован с вышеуказанными структурами данных):

  1. Для всех точек инициализируйте посещенный массив False.

  2. Найдите ближайшую точку к точке запроса сначала из kd-дерева, пометьте совпадающую точку и все точки из соответствующего многоугольника, совпадающие с точкой, которые были посещены, и возвратите этот конкретный многоугольник (id) в качестве ближайшего многоугольника (если там многократные такие многоугольники, возвращают все из них).

  3. Повторите шаг 2 до тех пор, пока не будут возвращены такие (разные) полигоны. Рассмотрим новую точку, возвращенную из kd-дерева, в соответствии с точкой запроса, если она еще не была посещена (если совпадающая точка, возвращаемая kd-деревом, уже посещена, отбросьте ее и запросите следующую ближайшую согласованную точку). Как только точка посещается, отметьте точку и все точки из соответствующего многоугольника (ов) по мере посещения и верните многоугольник (ы).

  • 1
    Привет @ Сандипан, да, ты прав, это больше проблема алгоритма и структуры данных. В моей текущей реализации у меня есть # 1 и # 2. Я пытался избежать логического массива # 3, потому что это грубое принуждение. Я подробно опишу мою работу (которая очень похожа на вашу) в моем вопросе. Спасибо! :)
0

Я вижу два способа сделать это эффективно:

  1. Индексируйте полные "линейные полигоны": для этого вы можете связать каждый линейный многоугольник с помощью минимального ограничивающего прямоугольника. Затем проиндексируйте все прямоугольники с соответствующей структурой индекса, например R-Tree. Вместо точек у вас будут линейные полигоны на самом низком уровне, поэтому вам придется адаптировать расстояние для этого случая.
  2. Использование просмотра расстояний: идея состоит в том, чтобы прикрепить к каждой точке идентификатор своего полигона линии и индексировать точки в структуре индекса (например, KD-Tree). Затем вы последовательно извлекаете следующую ближайшую точку в свой запрос, используя дистанционный просмотр. Вы продолжаете это до тех пор, пока не найдете точки из n разных полигонов линии.
  • 0
    Привет @SaiBot, спасибо за ваш ответ: | 1. Я понимаю, что rtree может использоваться для хранения пространственного индекса (ограничивающего прямоугольника) фигур и может быстро использоваться для поиска возможного пересечения. Вы предлагаете увеличить размер этих ограничивающих прямоугольников, чтобы они могли пересекаться с точкой X в дальнейшем? Я мог бы рассмотреть ограничивающую точку X вместо этого. | 2. Спасибо за ссылку. Это выглядит сложно, хотя я понимаю ваше объяснение. Я ищу библиотеку, которая позволяет это вложение. В противном случае требуется ручная реализация, аналогичная ответу Сандипан Дея ниже.
  • 0
    1. Вы можете найти не только пересечения с R-деревом, но и ближайших соседей. Вам не нужно увеличивать размер прямоугольников! 2. Документ выглядит сложным, но идея действительно проста: вы должны создать минимальную кучу, в которой точки и прямоугольники (например, узлы KD-дерева) хранятся на минимальном расстоянии до запроса X. Затем вы вставляете корневой узел Ваш индекс. Всякий раз, когда вы удаляете запись из кучи, вы заново вставляете детей. Когда вы получаете точку, вы получаете следующий ближайший сосед.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню