Оптимизация поиска полигонов

1

Я разбил мир на X случайных полигонах.

Изображение 174551

Тогда мне присваивается координата C1, например (-21.45, 7.10), и я хочу привязать правый многоугольник к этой координате.

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

Улучшение этого основывается на следующей идее: для оптимизации поиска я создаю grid (коллекцию) с шагом n, k, где я уже отношу каждую пару координат так, что:

for i=-180 to 180 step n 
    for j = -90 to 90 step k
        grid.add(i,j)

Затем я создаю словарь, и для каждой пары в коллекции я нахожу соответствующий многоугольник

For each g in grid
    For each p in polygons
        If point_in_polygon(g,p) == True
            my_dict(g) = p

Затем, когда я получаю C1, я ищу ближайшую координату в своей сетке, скажем g1. Благодаря my_dict, я могу быстро получить p1 = my_dict(g1) Затем я вычисляю point_in_polygon(C1, p1) который, вероятно, будет истинным. Если его нет, я нахожу ближайший g, который присваивается другому полигону, и я повторяю тест. И т.д., Пока не найду правильный полигон.

Теперь возникает вопрос: каково оптимальное n, k для создания сетки?

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

Моя интуиция заключается в том, что самый маленький полигон будет давать шаги.

Я не уверен, что это проблема программирования, проблема математики или что-то, что я могу найти эмпирически, поэтому я спрашиваю ее здесь.

Любые входы оцениваются!

Теги:
algorithm
polygon

2 ответа

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

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

Эффективность вашей сетки коррелирует с отношением однополигональных ячеек и полных клеток (поскольку это вероятность того, что не нужно выполнять тесты включения полигонов). Сам накопитель довольно дешев. Вы можете использовать плотный массив и получать постоянный доступ к ячейкам. Следовательно, с теоретической точки зрения, у вас должно быть как можно больше клеток (поскольку, поскольку у вас больше клеток, отношение однополигональных клеток увеличивается). На практике вы можете обнаружить, что кеш и другие эффекты памяти могут сделать большие сетки непрактичными. Однако нет хорошего способа узнать, кроме теста. Поэтому просто попробуйте с несколькими размерами на нескольких разных машинах и постарайтесь найти подходящее место.

Если бы я должен был догадаться, я бы сказал, что ваши клетки должны быть квадратными и иметь площадь около 1% - 5% от средней площади полигона. Кроме того, более компактные полигоны можно обрабатывать более эффективно, чем многие длинные и тонкие полигоны.

  • 0
    Мне нравится такой подход, в нем много смысла! Спасибо, я постараюсь реализовать это.
1

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

Итак, если вы не хотите делать полигональные тесты, вместо того, чтобы делить пространство на обычную сетку, сначала разрежьте его на полосы с вертикальными разрезами, проходящими через все пересечения многоугольников.

Теперь в каждой полосе ни одна из краев многоугольника не пересекается или не заканчивается, поэтому вы можете сделать упорядоченный список всех этих краев снизу вверх.

Если вы хотите найти многоугольник, содержащий точку, выполните двоичный поиск, используя координату x, чтобы найти нужную полосу. Затем в списке ребер, которые охватывают полосу, вы можете выполнить двоичный поиск, используя координату y, чтобы найти ближайший под точкой, и это говорит вам, в каком полигоне находится точка.

Трапецеидальная декомпозиция Google, чтобы найти много информации о подобных методах.

Ещё вопросы

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