2009-03-04 11 views
16

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

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

В моей реализации тестирование пересечения сторон является довольно дешевым, но тесты «точка в полигоне» являются дорогостоящими, поэтому идеально следует минимизировать.

+0

Считаете ли вы, что «точка в полигоне» тяжелая? Большую часть времени это всего лишь тест «больше, чем» и/или «меньше» всех точек, из которых состоит многоугольник, и только в некоторых случаях проверка пересечения строк? Или...? –

+0

Не уверен, что вы имеете в виду ... Я использую метод четного скрещивания для полупрямой (после проверки ограничивающего прямоугольника, конечно). Это заканчивается тестированием многих сторон, и если многоугольник имеет много сторон, он довольно медленный. –

+0

Coud вы ссылаетесь на некоторые наборы данных, это звучит как нечто, что может быть интересно попробовать. –

ответ

2

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

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

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

+0

Сверху моей головы создайте горизонтальные и вертикальные линии через каждую вершину вместо единой сетки. –

+0

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

+0

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

3

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

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

Edit: Я ellaborate на кД дерева (от скуки, даже если это может быть полезным для тех, кто):

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

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

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

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

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

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

пытался избежать этого ... знаете ли вы хорошее введение? Спасибо :) –

+0

Я не могу дать ни одного, но вы можете легко google многое, и то, что я только что написал, должно дать общую идею. – TrayMan

0

А как насчет использования обрезки ушей? В каждом треугольнике можно найти максимальный прямоугольник, выровненный по оси. Затем вы можете попытаться объединить треугольники и перепроверить свои прямоугольники.