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

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


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

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

Чтобы получить «n» ближайших строк, мне нужно будет увеличить «i». Моя проблема в том, что «i» может быть непредсказуемым, потому что количество координат варьируется между каждым линейным многоугольником. Например, линия-многоугольник может быть представлена ​​2 координатами, а другая может быть представлена ​​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

person Tri    schedule 27.08.2018    source источник
comment
Имеет ли смысл преобразовывать ваши группы в средние/средние баллы? Итак, вы должны перевести свою проблему в точку NN, сопоставить k ближайших точек, а затем разложить эти совпадения на исходные группы.   -  person randomir    schedule 27.08.2018
comment
Привет, randomir, я тоже подумал о представлении каждой формы с использованием одиночных координат. Однако мои геопространственные формы также различаются по размеру, поэтому использование центроидов для ближайших соседей может не дать желаемого результата (мне нужно не более 4 для каждого запроса). Представьте себе дорожную сеть в форме звезды, где я нахожусь в центре, а от нее расходятся 5 дорог (форм). Технически расстояние между 5 дорогами и мной одинаковое. Но если мы используем центроиды в качестве ориентира, длина дороги будет иметь значение.   -  person Tri    schedule 27.08.2018


Ответы (2)


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

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

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

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

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

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

person Sandipan Dey    schedule 27.08.2018
comment
Привет @Sandipan, да, ты прав, это скорее проблема алгоритма и структуры данных. В моей текущей реализации у меня есть №1 и №2. Я пытался избежать логического массива № 3, потому что это грубая сила. Я подробно расскажу о своей работе (которая очень похожа на вашу) в моем вопросе. Благодарю вас! :) - person Tri; 27.08.2018

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

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