Нахождение выровненного по оси прямоугольника внутри многоугольника - PullRequest
16 голосов
/ 04 марта 2009

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

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

В моей реализации тестирование пересечений сторон довольно дешево, но тесты "точка в многоугольнике" дороги, поэтому в идеале их следует минимизировать.

Ответы [ 4 ]

7 голосов
/ 04 марта 2009

http://cgm.cs.mcgill.ca/~athens/cs507/Projects/2003/DanielSud/
Имеет алгоритм для выпуклых ссылок, возможно, стоит посмотреть.
не уверен, что его можно расширить до невыпуклых.

3 голосов
/ 10 марта 2009

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

Поскольку у вас действительно есть две разные фундаментальные проблемы, рассматривали ли вы другие альтернативы задаче проверки попадания, такие как использование дерева BSP? Вы можете ускорить это дальше, наложив сетку на поли и построив дерево BSP для каждого квадрата сетки. Или kd-дерево с не более чем одним ребром в каждом листе?

Редактировать: Я разработаю kd-дерево (без скуки, даже если оно кому-нибудь пригодится):

kd-деревья имеют следующие свойства:

  1. Они двоичные
  2. Каждый неконечный узел разделяет пространство вдоль плоскости, перпендикулярной оси, по одной стороне на каждого дочернего элемента. Например. корень разбивает пространство на x = x0
  3. Уровни дерева по очереди разделяются по разным осям, например, уровень 0 (корень) разделяется перпендикулярно X, уровень 1 -> Y и т. д.

Чтобы использовать это для обнаружения попадания многоугольника, постройте дерево следующим образом:

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

Если расщепленная вершина выбрана надлежащим образом, глубина дерева должна быть близка к log (N), где N - количество вершин. Каждый листовой узел будет иметь не более одного ребра, проходящего через него. Для определения попадания:

  1. Найдите лист, в который попадает точка.
  2. Если на листе есть ребро, сравните точку с ним. В противном случае должно быть очевидно, находится ли точка внутри или снаружи (сохраняйте эту информацию в таких листьях при построении дерева).
2 голосов
/ 04 марта 2009

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

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

По понятным причинам это довольно медленно и неточно, не говоря уже о не элегантности:)

0 голосов
/ 30 апреля 2012

Как насчет использования ушной клипсы? Вы можете найти максимальный выровненный по оси прямоугольник в каждом треугольнике. Тогда вы можете попытаться соединить треугольники и пересчитать свои прямоугольники.

...