Как определить, пересекаются ли два выпуклых многоугольника?

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

alt text

Чтобы проверить, перекрываются ли два полигона P и Q, сначала я могу проверить каждое ребро в P, чтобы увидеть, пересекается ли оно с любым из края в Q. Если найдено пересечение, я объявляю, что P и Q пересекаются. Если ни одна из них не пересекается, тогда я должен проверить на случай, что P полностью содержится Q, и наоборот. Далее, есть случай, когда P == Q. Наконец, есть случай, который разделяет несколько ребер, но не все из них. (Эти последние два случая, вероятно, можно рассматривать как один и тот же общий случай, но это может быть неважно.)

У меня есть алгоритм, который определяет, где пересекаются два отрезка. Если два сегмента являются колинейными, они не считаются пересекающимися для моих целей.

Правильно ли я перечислил случаи? Любые предложения по тестированию для этих случаев?

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

Ответ 1

Вы можете использовать этот алгоритм столкновений:

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

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

Первое утверждение легко. Так как полигоны оба выпуклые, вы сможете нарисовать линию с одним полигоном с одной стороны, а другой многоугольник с другой стороны, если они не пересекаются. Второй - немного менее интуитивно понятный. Посмотрите на рисунок 1. Если ближайшая сторона многоугольников параллельна друг другу, точка, где они становятся ближе друг к другу, является точкой, где угол одного полигона ближе всего ближе к стороне другого полигона. Эта сторона затем образует разделительную ось между многоугольниками. Если стороны параллельны, они оба разделяют оси.

Итак, как это конкретно помогает нам решить, пересекаются ли полигон A и B? Ну, мы просто переходим по каждой стороне каждого полигона и проверяем, образует ли он разделительную ось. Для этого мы будем использовать некоторую базовую векторную математику для сквоша всех точек обоих полигонов на линию, перпендикулярную линии разделения потенциалов (см. Рис. 2). Теперь вся задача удобно 1-мерная. Мы можем определить область, в которой лежат точки для каждого многоугольника, и эта линия является разделительной осью, если эти области не перекрываются.

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

Ответ 2

  • если многоугольники всегда выпуклые, сначала вычислите угол линии, проведенной от центра к центру многоугольников. вы можете устранить необходимость протестировать сегменты края в половине полигона (ей) на 180 градусов от другого многоугольника.

  • чтобы устранить края, Начните с многоугольника слева. возьмите отрезок линии от центра многоугольника, который перпендикулярен отрезку линии от предыдущей пули, и касается обеих сторон многоугольника. назовем этот отрезок p, с вершинами p1 и p2. Тогда для всех вершин, если координата x меньше p1.x и p2.x Эта вершина может идти в "безопасном ковше".

  • Если это не так, вам нужно проверить, чтобы убедиться, что он находится на "безопасной" стороне линии (просто проверьте координаты y)

- если сегмент линии в многоугольнике имеет все вершины в "безопасном ковше", вы можете его игнорировать.

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

Ответ 3

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

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

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

Ответ 5

Вот идея:

  • Найдите центральную точку каждого многоугольника

  • Найдите две точки каждого многоугольника, ближайшего к центральной точке другого. Они будут соседними точками в выпуклых многоугольниках. Они определяют ближайший край каждого многоугольника, назовем точки {A, B} и {Y, Z}

  • Найдите пересечение линий AB и YZ. Если сегменты линии пересекаются (пересечение на AB лежит между A и B), ваши полигоны пересекаются. Если AB и XY параллельны, проигнорируйте это условие, следующий шаг поймает проблему.

  • Есть еще один случай, который вам нужно проверить, когда многоугольники пересекаются достаточно сильно, чтобы AB и XY полностью прошли друг друга и фактически не пересекаются. Чтобы заманить этот случай, вычислите перпендикулярные расстояния AB и XY к каждой точке центра полигонов. Если какая-либо центральная точка ближе к противоположному сегменту линии полигона, ваш многоугольник сильно перекрывается.

Ответ 7

Существует несколько способов обнаружения пересечения и/или сдерживания между выпуклыми многоугольниками. Все зависит от того, насколько эффективно вы хотите, чтобы алгоритм был. Рассмотрим два выпуклых многоугольника R и B с r и b вершинами соответственно:

  • алгоритм развертки. Как вы упомянули, вы можете выполнить процедуру линии развертки и сохранить интервалы, возникающие в результате пересечения полигонов с помощью линии подметания. Если в любое время интервалы перекрываются, то полигоны пересекаются. Сложность - это O ((r + b) log (r + b)) время.
  • Вращающийся алгоритм, основанный на искателях звонков. Подробнее см. здесь и здесь. Сложность - время O (r + b).
  • Самые эффективные методы можно найти здесь и здесь. Эти алгоритмы принимают время O (log r + log b).