Участник:Muravyov

Материал из Викиконспекты
Перейти к: навигация, поиск

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

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

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

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

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

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

Доказательство ведётся индуктивно по n. При n=3 теорема тривиальна. Рассмотрим случай при n>3 и предположим, что теорема выполняется при всех m<n. Докажем существование диагонали в многоугольнике P. Возьмём самую левую по оси x вершину v многоугольника P и две смежных с ней вершины u и w. Если отрезок uw принадлежит внутренней области P — мы нашли диагональ. В противном случае, во внутренней области треугольника Δuwv или на самом отрезке uw содержится одна или несколько вершин P. Выберем самую наиболее далеко отстоящую от uw вершину v. Отрезок, соединяющий v и v не может пересекать сторон P, поскольку в противном случае одна из вершин это отрезка будет располагаться дальше от uw, чем v. Это противоречит условию выбора v. В итоге получаем, что vv — диагональ. Любая диагональ делит P на два многоугольника P1 и P2. За m1 и m2 обозначим количество вершин в P1 и P2 соответственно. m1<n и m2<n, поэтому по предположению индукции у P1 и P2 существует триангуляция, следовательно и у P она существует.

Докажем, что триангуляция P состоит из n2 треугольников. Рассмотрим произвольную диагональ d в триангуляции TP. d делит P на два многоугольника P1 и P2, количество вершин в которых m1 и m2 соответственно. Каждая вершина P встречается только в одном из двух многоугольников P1 и P2, за исключением тех, которые являются концами d, поэтому справедливо следующее: m1+m2=n+2. По индукции, любая триангуляция Pi состоит из mi2 треугольников, откуда следует, что TP. состоит из (m12)+(m22)=n2 треугольников.

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

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

В общем случае в произвольном n-угольнике всего n2 возможных вариантов построения диагоналей. За O(n) проверим каждый из них. Для этого выясним:

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

Чтобы построить триангуляцию нужно найти n3 диагоналей. В результате получается оценка O(n4).

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

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

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


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


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

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

Основные понятия
Пять типов вершин

Рассмотрим самую верхнюю — максимальную по оси y вершину. Будем идти вниз по рёбрам до самой нижней — соотвественно минимальной по y вершине, то есть таким образом, что для некоторой вершины j: yj>yj+1. Поворотной назовём вершину i, на которой направление обхода будет меняется: yi1>yi и yi<yi+1. Опишем более подробно этот тип вершин. Уточним понятния выше и ниже: точка p лежит ниже точки q, если py<qy или если py<qy и px>qx, соответственно точка p лежит выше точки q, если py>qy или если py=qy и px<qx. Это было сделано для того, чтобы избежать неопределённых ситуаций с вершинами, у которых y-координаты равны.

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

  • start вершина — два её соседа лежат ниже её самой и ϕ<π
  • split вершина — два её соседа лежат ниже её самой и ϕ>π
  • end вершина — два её соседа лежат выше её самой и ϕ<π
  • merge вершина — два её соседа лежат выше её самой и ϕ>π
  • regular вершина — не является поворотной, в отличие от остальных, другими словами один её сосед находится выше, а другой ниже её самой.
Лемма:
Многоугольник P является y-монотонным, когда в нём отсутствуют split и merge вершины.
Доказательство:

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

Proof lemma.jpg

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

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

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

обработка split вершины
Рассмотрим каждый случай подробнее:


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

2) Merge вершина. В отличие от случая со split вершиной заранее вычислить указатель helper нельзя, поскольку merge вершина vi должна быть соединена с вершиной, лежащей ниже заметающей прямой l. Для этого в helper левого относительно vi ребра запишем саму vi. Далее спускаем заметающую прямую вниз к следующей вершине vm, обращаемся к helper'у её левого ребра. Проверяем, если там хранится merge вершина, строим диагональ vivm. Последняя проверка осуществляется для любого типа вершины, кроме split, согласно п.1.

Структуры

В подходе, описанном выше, требуется находить пересечения заметающей прямой и левых ребёр многоугольника. Создадим двоичное дерево поиска T, в листьях которого будем хранить рёбра, пересекающие l, такие, что внутренняя область многоугольника будет лежать справа от них самих. С каждым таким ребром будем хранить его helper. Порядок следования листьев в дереве соответствует порядку следования рёбер в многоугольнике: слева направо. Дерево изменяется в зависимости от текущего состояния заметающей прямой. Создадим приоритетную очередь Q из вершин, в которой приоритетом будет y-координата вершины. Если две вершины имеют одинаковые y-координаты, больший приоритет у левой. Вершины будут добавляться на "остановках" заметающей прямой.

Многоугольник P удобно хранить в виде двусвязного спика D рёбер и добавленных в процессе диагоналей, так как потом это обеспечит эффективный доступ к каждой из частей, которые нужно будет триангулировать.

Псевдокод
MakeMonotone(P)
   Construct(D);
   Construct(Q); // функция Construct создаёт объекты D и Q , описанные выше.
   bst T = new bst();
   while Q
      Remove vmax from Q // удаление вершины с наивысшим приоритетом из Q    
      switch (Type_of_vertex(vmax)): //определение типа вершины
         case 'start':
            HandleStartVertex(vmax);
         case 'end':
            HandleEndVertex(vmax);
         case 'split':
            HandleSplitVertex(vmax);
         case 'merge':
            HandleMergeVertex(vmax);
         case 'regular':
            HandleRegularVertex(vmax);

Опишем теперь каждый метод из последнего switch:

HandleStartVertex(vi)
   Insert ei in T
   helper(ei)vi
HandleEndVertex(vi)
   if (Type_of_vertex(helper(ei) = 'merge')
      Insert edge(vi, helper(ei)) in D
   Delete ei1 from T
HandleSplitVertex(vi)
   edge ej = lP
   Search ej in T
   Insert edge(vi, helper(ei)) in D
   helper(ej)vi 
   Insert ei in T
   helper(ei)vi
HandleMergeVertex(vi)
   if (Type_of_vertex(helper(ei) = 'merge')
      Insert edge(vi, helper(ei)) in D
   Delete ei1 from T
   edge ej = lP
   Search ej in T
   if (Type_of_vertex(helper(ej) = 'merge')
      Insert edge(vi, helper(ej)) in D
   helper(ej)vi
HandleRegularVertex(vi)
   if (interior of P lies to the right of vi)
      then
         if (Type_of_vertex(helper(ei) = 'merge')
            Insert edge(vi, helper(ei)) in D
         Delete ei1 from T
         Insert ei in T
         helper(ei)vi
      else
         edge ej = lP
         Search ej in T
         if (Type_of_vertex(helper(ej) = 'merge')
            Insert edge(vi, helper(ej)) in D
         helper(ej)vi
Корректность
Лемма:
Функция MakeMonotone(P) корректно выполняет разбиение многоугольника P. Другими словами эта функция добавляет в P множество непересекающихся диагоналей, которые разбивают P на монотонные части.
Доказательство:

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

Рассмотрим случай выполнения функции HandleSplitVertex, поскольку это наиболее общий случай: split вершина может быть соединена со всеми типами вершин, в отличие от остальных функций. В них рассматриваемая в данный момент вершина может быть соединена только с merge вершиной.

Допустим, что диагональ vivm была построена с помощью HandleSplitVertex по достижению split вершины vi. Рассмотрим четырёхугольник H, заключённый между ej и ek - левым и правым ребром относительно vi и горизонтальными прямыми, проведёнными через vi и vm. Внутри H, не может находиться ни одной из вершин P, в противном случае helper(ej) не равнялся бы vm. Предположим теперь, что vivm пересекает es одну из сторон P. Учитывая, что никаких вершин P не лежит внутри H и стороны P не пересекаются, то es должна пересечь либо отрезок, соединяющий ej и vm, либо ej и vi. Такое возможно только в случае, когда точками пересечения будут являться vi или vm, что не противоречит условию. Отсюда vivm не пересекает ни одну из сторон P в посторонних точках.
Оценкка работы

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

Ушной метод

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