Сначала построим плоский линейный график (PSLG) многоугольника. Другими словами, рассматривайте полигон как группу сегментов и разделенных сегментов на каждом пересечении. Существует крайний случай, когда два или более сегмента могут перекрываться в нетривиальном сегменте, а не в точке. В PSLG сегмент пересечения должен быть единым, отдельным сегментом, но нам также нужно знать, сколько сегментов линии перекрывают сегмент. Следовательно, этот вырожденный многоугольник (A-B-C-D-E-F-G-A
)
A-C-B-D
| /
| /
G--E---F
превращается в
3
*-*-*-*
| /
| /
*--*---* ,
2
опуская все метки, на которых написано 1
.
Следующим шагом является вычисление комбинаторного встраивания этого PSLG. Это означает, что мы перебираем вершины, сортируя инцидентные ребра каждой вершины по углу в направлении против часовой стрелки. Стандартным способом вычислительной геометрии мы можем использовать область со знаком, чтобы получить компаратор, который не включает триг.
Теперь у нас есть такая структура данных.
3
t-u-v-w
| /
| /
x--y---z ,
2
t: t-u, t-x, t-y
u: u-v (3), u-t
v: v-w, v-u (3)
w: w-v, w-y
x: x-y, x-t
y: y-z (2), y-w, y-x
z: z-y (2)
Мы получаем перестановку на ориентированных ребрах ( дартс здесь и далее), где каждый из них указывает на следующий в списке (в случае необходимости оборачивается).
t-u -> t-x
t-x -> t-u
u-v (3) -> u-t
u-t -> u-v (3)
v-w -> v-u (3)
v-u (3) -> v-w
w-v -> w-y
w-y -> w-v
x-y -> x-t
x-t -> x-y
y-z (2) -> y-w
y-w -> y-x
y-x -> y-z (2)
z-y (2) -> z-y (2)
Мы вычисляем двойственное для этого вложения, создавая новую перестановку, в которой каждый дротик указывает на обратную сторону своего текущего назначения.
t-u -> x-t
x-t -> y-x
y-x -> z-y (2)
z-y (2) -> y-z (2)
y-z (2) -> w-y
w-y -> v-w
v-w -> u-v (3)
u-v (3) -> t-u
t-x -> u-t
u-t -> v-u (3)
v-u (3) -> w-v
w-v -> y-w
y-w -> x-y
x-y -> t-x
Теперь я сгруппировал перестановку в циклы. Эти циклы являются гранями PSLG (внутри многоугольника по часовой стрелке и бесконечной гранью против часовой стрелки). Используйте тест области подписи , чтобы найти бесконечное лицо.
Возвращаясь к графическому представлению, выполните поиск в глубину по граням, укорененным в бесконечной грани, пометив каждую грань как нечетную (если сумма чисел по краям нечетная) или четную. Коллекция нечетных циклов - это результат, который вы ищете.
На самом деле, теперь, когда я выписал весь этот ответ, лучше просто удалить сегменты четной кратности в начале, чтобы соединить смежные многоугольники вместе. Это может привести к множеству бесконечных лиц, но метод обнаружения все еще работает.