Участник:Muravyov — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм)
(Алгоритм)
Строка 71: Строка 71:
 
Рассмотрим заметающую прямую <tex>l</tex>, перпендукулярную <tex>y</tex>-оси, будем перемещать её сверху вниз вдоль плоскости на которой лежит исходный многоугольник <tex>P</tex>. Будем останавливать её в каждой вершине многоугольника. Создадим приоритетную очередь <tex>Q</tex> из вершин, в которой приоритетом будет <tex>y</tex>-координата вершины. Если две вершины имеют одинаковые <tex>y</tex>-координаты, больший приоритет у левой.
 
Рассмотрим заметающую прямую <tex>l</tex>, перпендукулярную <tex>y</tex>-оси, будем перемещать её сверху вниз вдоль плоскости на которой лежит исходный многоугольник <tex>P</tex>. Будем останавливать её в каждой вершине многоугольника. Создадим приоритетную очередь <tex>Q</tex> из вершин, в которой приоритетом будет <tex>y</tex>-координата вершины. Если две вершины имеют одинаковые <tex>y</tex>-координаты, больший приоритет у левой.
 
В тот момент, когда на пути заметающей прямой встречается split или merge вершина её нужно соединить с вершиной, у которой расстояние до <tex>l</tex> минимально, при этом она должна лежать соответственно выше или ниже <tex>l</tex>. Рассмотрим каждый случай подробнее:
 
В тот момент, когда на пути заметающей прямой встречается split или merge вершина её нужно соединить с вершиной, у которой расстояние до <tex>l</tex> минимально, при этом она должна лежать соответственно выше или ниже <tex>l</tex>. Рассмотрим каждый случай подробнее:
 +
 
1) '''Split вершина'''. Пусть <tex>e_j</tex> и <tex>e_k</tex> — ближайшее левое и правое ребро относительно split вершины <tex>v_i</tex>, которые <tex>l</tex> пересекает в данный момент. Нам нужно найти вершину, лежащую между <tex>e_j</tex> и <tex>e_k</tex>, наиболее приближённую к <tex>l</tex>, либо если такой точки не существет выбрать минимальную из верхних вершин <tex>e_j</tex> и <tex>e_k</tex>. Для этого будем хранить указатель на искомую вершину у левого ребра <tex>e_j</tex>, который можно заранее вычислить. Таким образом, чтобы построить диагональ для split вершины нужно обратиться к указателю <tex>helper</tex> её левого ребра, которое <tex>l</tex> пересекает в данный момент.
 
1) '''Split вершина'''. Пусть <tex>e_j</tex> и <tex>e_k</tex> — ближайшее левое и правое ребро относительно split вершины <tex>v_i</tex>, которые <tex>l</tex> пересекает в данный момент. Нам нужно найти вершину, лежащую между <tex>e_j</tex> и <tex>e_k</tex>, наиболее приближённую к <tex>l</tex>, либо если такой точки не существет выбрать минимальную из верхних вершин <tex>e_j</tex> и <tex>e_k</tex>. Для этого будем хранить указатель на искомую вершину у левого ребра <tex>e_j</tex>, который можно заранее вычислить. Таким образом, чтобы построить диагональ для split вершины нужно обратиться к указателю <tex>helper</tex> её левого ребра, которое <tex>l</tex> пересекает в данный момент.
  

Версия 18:09, 2 мая 2012

Триангуляция полигона — декомпозиция многоугольника [math]P[/math] на множество треугольников, внутренние области которых попарно не пересекаются и объединение которых в совокупности составляет [math]P[/math]. В строгом смысле слова, вершины этих треугольников должны совпадать с вершинами исходного многоугольника. Триангуляция любого многоугольника не единственна. В этом можно убедиться из примера на рисунке.

Постановка задачи

На плоскости задан произвольный многоугольник. Стороны многоугольника не пересекаются. Требуется найти его триангуляцию.

Теорема о существовании трингуляции

Простым многоугольником является фигура, ограниченная одной замкнутой ломаной, стороны которой не пересекаются. Таким образом, случаи многоугольников с дырками в теореме исключаются.

Теорема (О существовании триангуляции многоугольника):
У любого простого [math]n[/math]-вершинного многоугольника [math]P[/math] всегда существует триангуляция, причём количество треугольников в ней [math]n - 2[/math] независимо от самой триангуляции.
Доказательство:
[math]\triangleright[/math]

Доказательство ведётся индуктивно по [math]n[/math]. При [math]n = 3[/math] теорема тривиальна. Рассмотрим случай при [math]n \gt 3[/math] и предположим, что теорема выполняется при всех [math]m \lt n[/math]. Докажем существование диагонали в многоугольнике [math]P[/math]. Возьмём самую левую по оси [math]x[/math] вершину [math]v[/math] многоугольника [math]P[/math] и две смежных с ней вершины [math]u[/math] и [math]w[/math]. Если отрезок [math]uw[/math] принадлежит внутренней области [math]P[/math] — мы нашли диагональ. В противном случае, во внутренней области треугольника [math]\Delta uwv[/math] или на самом отрезке [math]uw[/math] содержится одна или несколько вершин [math]P[/math]. Выберем самую наиболее далеко отстоящую от [math]uw[/math] вершину [math]v'[/math]. Отрезок, соединяющий [math]v[/math] и [math]v'[/math] не может пересекать сторон [math]P[/math], поскольку в противном случае одна из вершин это отрезка будет располагаться дальше от [math]uw[/math], чем [math]v'[/math]. Это противоречит условию выбора [math]v'[/math]. В итоге получаем, что [math]v'v[/math] — диагональ. Любая диагональ делит [math]P[/math] на два многоугольника [math]P_1[/math] и [math]P_2[/math]. За [math]m_1[/math] и [math]m_2[/math] обозначим количество вершин в [math]P_1[/math] и [math]P_2[/math] соответственно. [math]m_1 \lt n[/math] и [math]m_2 \lt n[/math], поэтому по предположению индукции у [math]P_1[/math] и [math]P_2[/math] существует триангуляция, следовательно и у [math]P[/math] она существует.

Докажем, что триангуляция [math]P[/math] состоит из [math]n - 2[/math] треугольников. Рассмотрим произвольную диагональ [math]d[/math] в триангуляции [math]T_P[/math]. [math]d[/math] делит [math]P[/math] на два многоугольника [math]P_1[/math] и [math]P_2[/math], количество вершин в которых [math]m_1[/math] и [math]m_2[/math] соответственно. Каждая вершина [math]P[/math] встречается только в одном из двух многоугольников [math]P_1[/math] и [math]P_2[/math], за исключением тех, которые являются концами [math]d[/math], поэтому справедливо следующее: [math]m_1 + m_2 = n + 2[/math]. По индукции, любая триангуляция [math]P_i[/math] состоит из [math]m_i - 2[/math] треугольников, откуда следует, что [math]T_P[/math]. состоит из [math](m_1 - 2) + (m_2 - 2) = n - 2[/math] треугольников.
[math]\triangleleft[/math]

Способы нахождения триангуляции

Примитивный алгоритм

В общем случае в произвольном [math]n[/math]-угольнике всего [math]n^2[/math] возможных вариантов построения диагоналей. За [math]\mathcal{O}(n)[/math] проверим каждый из них. Для этого выясним:

  • пересекает ли данная диагональ многоугольник — находится за линейное время проверкой по всем рёбрам
  • принадлежит ли диагональ внутренней область многоугольника.

Чтобы построить триангуляцию нужно найти [math]n - 3[/math] диагоналей. В результате получается оценка [math]\mathcal{O}(n^4)[/math].

Для некоторых классов многоугольников предыдущую оценку можно улучшить. Например, если многоугольник выпуклый, то достаточно лишь выбирать одну его вершину и соединять со всеми остальными, кроме его соседей. В итоге оценка [math]\mathcal{O}(n)[/math].

Монотонный метод

Определение:
Простой многоугольник [math]P[/math] называется монотонным относительно прямой [math]l[/math], если любая [math]l'[/math], такая что [math]l' \perp l[/math], пересекает стороны [math]P[/math] не более двух раз (результатом пересечения [math]l'[/math] и [math]P[/math] может быть только один отрезок или точка).


Определение:
Многоугольник, монотонный относительно [math]y[/math]-оси называется [math]y[/math]-монотонным.


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

Разбиение многоугольника на монотонные части

Идея
Пять типов вершин

Рассмотрим самую верхнюю — максимальную по оси [math]y[/math] вершину. Будем идти вниз по рёбрам до самой нижней — соотвественно минимальной по [math]y[/math] вершине, то есть таким образом, что для некоторой вершины [math]j[/math]: [math]y_j \gt y_{j+1}[/math]. Поворотной назовём вершину [math]i[/math], на которой направление обхода будет меняется: [math]y_{i-1} \gt y_i[/math] и [math]y_i \lt y_{i+1}[/math]. Опишем более подробно этот тип вершин. Уточним понятния выше и ниже: точка [math]p[/math] лежит ниже точки [math]q[/math], если [math]p_y \lt q_y[/math] или если [math]p_y \lt q_y[/math] и [math]p_x \gt q_x[/math], соответственно точка [math]p[/math] лежит выше точки [math]q[/math], если [math]p_y \gt q_y[/math] или если [math]p_y = q_y[/math] и [math]p_x \lt q_x[/math]. Это было сделано для того, чтобы избежать неопределённых ситуаций с вершинами, у которых [math]y[/math]-координаты равны.

Обозначим за [math]\phi[/math] внутренний угол при некоторой вершине вершине и определим далее пять типов вершин, четыре из которых являются поворотными:

  • start вершина — два её соседа лежат ниже её самой и [math] \phi \lt \pi [/math]
  • split вершина — два её соседа лежат ниже её самой и [math] \phi \gt \pi [/math]
  • end вершина — два её соседа лежат выше её самой и [math] \phi \lt \pi [/math]
  • merge вершина — два её соседа лежат выше её самой и [math] \phi \gt \pi [/math]
  • regular вершина — не является поворотной, в отличие от остальных, другими словами один её сосед находится выше, а другой ниже её самой.
Лемма:
Многоугольник [math]P[/math] является [math]y[/math]-монотонным, когда в нём отсутствуют split и merge вершины.
Доказательство:
[math]\triangleright[/math]

Предположим, что [math]P[/math] не [math]y[/math]-монотонный. Тогда докажем, что [math]P[/math] содержит split и merge вершины. Поскольку [math]P[/math] не [math]y[/math]-монотонный, горизонтальная прямая [math]l[/math] пересекает его стороны более двух раз. Выберем [math]l[/math] таким образом, чтобы самой левой компонентой пересечения [math]l[/math] и [math]P[/math] был бы отрезок [math]pq[/math]. Далее будем двигаться наверх по сторонам [math]P[/math], начиная от точки [math]q[/math]. В результате в некоторой точке [math]r[/math], где [math]r \neq p[/math] (случай (a) на рисунке), прямая [math]l[/math] снова пересечёт одну из сторон [math]P[/math]. Отсюда самая высокая точка, которую мы достигли во время движения по сторонам [math]P[/math], будет split вершиной.

Proof lemma.jpg

Если же [math]r = p[/math] (случай (b) на рисунке), начём опять двигаться по сторонам [math]P[/math] теперь уже вниз. Как и в предыдущем случае найдётся некоторая точка [math]r'[/math], которая будет результатом пересечения [math]l[/math] и [math]P[/math]. При этом [math]r' \neq p[/math], в противном случае [math]l[/math] будет пересекать [math]P[/math] только два раза, то есть [math]P[/math] будет [math]y[/math]-монотонным, что противоречит нашему предположению. Аналогично предыдущему случаю, выберем теперь самую низкую точку, которую мы достигли во время движения по сторонам P. Она будет merge вершиной.
[math]\triangleleft[/math]

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

Алгоритм

Рассмотрим заметающую прямую [math]l[/math], перпендукулярную [math]y[/math]-оси, будем перемещать её сверху вниз вдоль плоскости на которой лежит исходный многоугольник [math]P[/math]. Будем останавливать её в каждой вершине многоугольника. Создадим приоритетную очередь [math]Q[/math] из вершин, в которой приоритетом будет [math]y[/math]-координата вершины. Если две вершины имеют одинаковые [math]y[/math]-координаты, больший приоритет у левой. В тот момент, когда на пути заметающей прямой встречается split или merge вершина её нужно соединить с вершиной, у которой расстояние до [math]l[/math] минимально, при этом она должна лежать соответственно выше или ниже [math]l[/math]. Рассмотрим каждый случай подробнее:

1) Split вершина. Пусть [math]e_j[/math] и [math]e_k[/math] — ближайшее левое и правое ребро относительно split вершины [math]v_i[/math], которые [math]l[/math] пересекает в данный момент. Нам нужно найти вершину, лежащую между [math]e_j[/math] и [math]e_k[/math], наиболее приближённую к [math]l[/math], либо если такой точки не существет выбрать минимальную из верхних вершин [math]e_j[/math] и [math]e_k[/math]. Для этого будем хранить указатель на искомую вершину у левого ребра [math]e_j[/math], который можно заранее вычислить. Таким образом, чтобы построить диагональ для split вершины нужно обратиться к указателю [math]helper[/math] её левого ребра, которое [math]l[/math] пересекает в данный момент.

2) Merge вершина. В отличие от случая со split вершиной заранее вычислить указатель [math]helper[/math] нельзя, поскольку merge вершина [math]v_i[/math] должна быть соединена с вершиной, лежащей ниже заметающей прямой [math]l[/math]. Для этого в [math]helper[/math] левого относительно [math]v_i[/math] ребра запишем саму [math]v_i[/math]. Далее спускаем заметающую прямую вниз к следующей вершине [math]v_m[/math], обращаемся к [math]helper[/math]'у её левого ребра. Проверяем, если там хранится merge вершина, строим диагональ [math]v_{i}v_{m}[/math].

Корректность

Триангуляция монотонного треугольника

Ушной метод

Более эффективным я