Участник:Muravyov — различия между версиями
Muravyov (обсуждение | вклад) (→Триангуляция монотонного многоугольника) |
Muravyov (обсуждение | вклад) (→Триангуляция монотонного многоугольника) |
||
Строка 177: | Строка 177: | ||
Идея такова: будем проходить сверху вниз по вершинам многоугольника проводя диагонали где это возможно. | Идея такова: будем проходить сверху вниз по вершинам многоугольника проводя диагонали где это возможно. | ||
− | Отсортируем все вершины многоугольника <tex>P</tex> в порядке убывания их <tex>y</tex>-координаты | + | Отсортируем все вершины многоугольника <tex>P</tex> в порядке убывания их <tex>y</tex>-координаты. Заведём стек вершин <tex>S</tex>. В стеке будем хранить вершины, которые были обработаны, но не были отрезаны от многоугольника, то есть находятся в той части многоугольника, которая ещё не была триангулирована. В момент обработки некоторой вершины, будем пытаться провести из неё как можно больше диагоналей к вершинам, содержащимся в стеке. Эти диагонали отрезают треугольники от <tex>P</tex>. На вершине стека будет храниться вершина, которая будет обрабатываться последней. |
+ | |||
+ | Часть многоугольника <tex>P</tex>, лежащая выше последней обработанной вершины и которая ещё не была триангулирована имеет форму перевёрнутой воронки (см. рисунки). Одна сторона воронки состоит из одной из сторон <tex>P</tex>, а другая состоит из цепи вершин, внутренние углы которых не меньше <tex>\pi</tex>. Несложно догадаться тогда, что самая нижняя вершина стека является выпуклой. | ||
+ | |||
+ | Рассмотрим алгоритм обработки вершины более подробно. | ||
=== Ушной метод === | === Ушной метод === | ||
Более эффективным я | Более эффективным я |
Версия 17:07, 7 мая 2012
Триангуляция полигона — декомпозиция многоугольника
на множество треугольников, внутренние области которых попарно не пересекаются и объединение которых в совокупности составляет . В строгом смысле слова, вершины этих треугольников должны совпадать с вершинами исходного многоугольника. Триангуляция любого многоугольника не единственна. В этом можно убедиться из примера на рисунке.Содержание
Постановка задачи
На плоскости задан произвольный многоугольник. Стороны многоугольника не пересекаются. Требуется найти его триангуляцию.
Теорема о существовании трингуляции
Простым многоугольником является фигура, ограниченная одной замкнутой ломаной, стороны которой не пересекаются. Таким образом, случаи многоугольников с дырками в теореме исключаются.
Теорема (О существовании триангуляции многоугольника): |
У любого простого -вершинного многоугольника всегда существует триангуляция, причём количество треугольников в ней независимо от самой триангуляции. |
Доказательство: |
Доказательство ведётся индуктивно по Докажем, что триангуляция . При теорема тривиальна. Рассмотрим случай при и предположим, что теорема выполняется при всех . Докажем существование диагонали в многоугольнике . Возьмём самую левую по оси вершину многоугольника и две смежных с ней вершины и . Если отрезок принадлежит внутренней области — мы нашли диагональ. В противном случае, во внутренней области треугольника или на самом отрезке содержится одна или несколько вершин . Выберем самую наиболее далеко отстоящую от вершину . Отрезок, соединяющий и не может пересекать сторон , поскольку в противном случае одна из вершин это отрезка будет располагаться дальше от , чем . Это противоречит условию выбора . В итоге получаем, что — диагональ. Любая диагональ делит на два многоугольника и . За и обозначим количество вершин в и соответственно. и , поэтому по предположению индукции у и существует триангуляция, следовательно и у она существует. состоит из треугольников. Рассмотрим произвольную диагональ в триангуляции . делит на два многоугольника и , количество вершин в которых и соответственно. Каждая вершина встречается только в одном из двух многоугольников и , за исключением тех, которые являются концами , поэтому справедливо следующее: . По индукции, любая триангуляция состоит из треугольников, откуда следует, что . состоит из треугольников. |
Способы нахождения триангуляции
Примитивный алгоритм
В общем случае в произвольном
-угольнике всего возможных вариантов построения диагоналей. За проверим каждый из них. Для этого выясним:- пересекает ли данная диагональ многоугольник — находится за линейное время проверкой по всем рёбрам
- принадлежит ли диагональ внутренней область многоугольника.
Чтобы построить триангуляцию нужно найти
диагоналей. В результате получается оценка .Для некоторых классов многоугольников предыдущую оценку можно улучшить. Например, если многоугольник выпуклый, то достаточно лишь выбирать одну его вершину и соединять со всеми остальными, кроме его соседей. В итоге оценка
.Монотонный метод
Определение: |
Простой многоугольник | называется монотонным относительно прямой , если любая , такая что , пересекает стороны не более двух раз (результатом пересечения и может быть только один отрезок или точка).
Определение: |
Многоугольник, монотонный относительно | -оси называется -монотонным.
Суть данного метода заключается в том, чтобы разбить многоугольник на монотонные части, а затем триангулировать каждую из них.
Разбиение многоугольника на монотонные части
Основные понятия
Рассмотрим самую верхнюю — максимальную по оси
вершину. Будем идти вниз по рёбрам до самой нижней — соотвественно минимальной по вершине, то есть таким образом, что для некоторой вершины : . Поворотной назовём вершину , на которой направление обхода будет меняется: и . Опишем более подробно этот тип вершин. Уточним понятния выше и ниже: точка лежит ниже точки , если или если и , соответственно точка лежит выше точки , если или если и . Это было сделано для того, чтобы избежать неопределённых ситуаций с вершинами, у которых -координаты равны.Обозначим за
внутренний угол при некоторой вершине вершине и определим далее пять типов вершин, четыре из которых являются поворотными:- start вершина — два её соседа лежат ниже её самой и
- split вершина — два её соседа лежат ниже её самой и
- end вершина — два её соседа лежат выше её самой и
- merge вершина — два её соседа лежат выше её самой и
- regular вершина — не является поворотной, в отличие от остальных, другими словами один её сосед находится выше, а другой ниже её самой.
Лемма: |
Многоугольник является -монотонным, когда в нём отсутствуют split и merge вершины. |
Доказательство: |
Предположим, что не -монотонный. Тогда докажем, что содержит split и merge вершины. Поскольку не -монотонный, горизонтальная прямая пересекает его стороны более двух раз. Выберем таким образом, чтобы самой левой компонентой пересечения и был бы отрезок . Далее будем двигаться наверх по сторонам , начиная от точки . В результате в некоторой точке , где (случай (a) на рисунке), прямая снова пересечёт одну из сторон . Отсюда самая высокая точка, которую мы достигли во время движения по сторонам , будет split вершиной. Если же (случай (b) на рисунке), начём опять двигаться по сторонам теперь уже вниз. Как и в предыдущем случае найдётся некоторая точка , которая будет результатом пересечения и . При этом , в противном случае будет пересекать только два раза, то есть будет -монотонным, что противоречит нашему предположению. Аналогично предыдущему случаю, выберем теперь самую низкую точку, которую мы достигли во время движения по сторонам P. Она будет merge вершиной. |
Алгоритм
Чтобы сделать многоугольник монотонным, нужно избавиться от split и merge вершин путём проведения непересекающихся дигоналей из таких вершин.
Рассмотрим заметающую прямую
, перпендукулярную -оси, будем перемещать её сверху вниз вдоль плоскости на которой лежит исходный многоугольник . Будем останавливать её в каждой вершине многоугольника. В тот момент, когда на пути заметающей прямой встречается split или merge вершина её нужно соединить с вершиной, у которой расстояние до минимально, при этом она должна лежать соответственно выше или ниже . Рассмотрим каждый случай подробнее:
1) Split вершина. Пусть и — ближайшее левое и правое ребро относительно split вершины , которые пересекает в данный момент. Нам нужно найти вершину, лежащую между и , наиболее приближённую к , либо если такой точки не существет выбрать минимальную из верхних вершин и . Для этого будем хранить указатель на искомую вершину у левого ребра , который можно заранее вычислить. Тип вершины, хранящийся в не имеет значения. Таким образом, чтобы построить диагональ для split вершины нужно обратиться к указателю её левого ребра, которое пересекает в данный момент.
2) Merge вершина. В отличие от случая со split вершиной заранее вычислить указатель
нельзя, поскольку merge вершина должна быть соединена с вершиной, лежащей ниже заметающей прямой . Для этого в левого относительно ребра запишем саму . Далее спускаем заметающую прямую вниз к следующей вершине , обращаемся к 'у её левого ребра. Проверяем, если там хранится merge вершина, строим диагональ . Последняя проверка осуществляется для любого типа вершины, кроме split, согласно п.1.Структуры данных
В подходе, описанном выше, требуется находить пересечения заметающей прямой и левых ребёр многоугольника. Создадим двоичное дерево поиска
, в листьях которого будем хранить рёбра, пересекающие , такие, что внутренняя область многоугольника будет лежать справа от них самих. С каждым таким ребром будем хранить его . Порядок следования листьев в дереве соответствует порядку следования рёбер в многоугольнике: слева направо. Дерево изменяется в зависимости от текущего состояния заметающей прямой. Создадим приоритетную очередь из вершин, в которой приоритетом будет -координата вершины. Если две вершины имеют одинаковые -координаты, больший приоритет у левой. Вершины будут добавляться на "остановках" заметающей прямой.Многоугольник
удобно хранить в виде двусвязного спика рёбер и добавленных в процессе диагоналей, так как потом это обеспечит эффективный доступ к каждой из частей, которые нужно будет триангулировать.Псевдокод
MakeMonotone(P) Construct(); Construct( ); // функция Construct создаёт объекты и , описанные выше. bst = new bst(); while Remove from // удаление вершины с наивысшим приоритетом из switch (Type_of_vertex( )): //определение типа вершины case 'start': HandleStartVertex( ); case 'end': HandleEndVertex( ); case 'split': HandleSplitVertex( ); case 'merge': HandleMergeVertex( ); case 'regular': HandleRegularVertex( );
Опишем теперь каждый метод из последнего switch:
HandleStartVertex() Insert in
HandleSplitVertex() edge = Search in Insert edge( , ) in Insert in v
В последующих трех функциях обработки вершины
происходит обращение к смежному ребру . Это сделано для вершин, относительно которых внутренняя область лежит справа от них самих (вершина ), либо для двух подряд идущих merge вершин, таких как и .HandleEndVertex() if (Type_of_vertex( = 'merge') Insert edge( , ) in Delete from
HandleMergeVertex() if (Type_of_vertex( = 'merge') Insert edge( , ) in Delete from edge = Search in if (Type_of_vertex( = 'merge') Insert edge( , ) in
HandleRegularVertex() if (interior of lies to the right of ) then if (Type_of_vertex( = 'merge') Insert edge( , ) in Delete from Insert in else edge = Search in if (Type_of_vertex( = 'merge') Insert edge( , ) in
Корректность
Лемма: |
Функция MakeMonotone(P) корректно выполняет разбиение многоугольника . Другими словами эта функция добавляет в множество непересекающихся диагоналей, которые разбивают на монотонные части. |
Доказательство: |
Тот факт, что разбивается на монотонные части следует из предыдущей леммы. Остаётся доказать, что диагонали, построенные в процессе выполнения алгоритма, не попарно не пересекаются и не пересекают стороны .Рассмотрим случай выполнения функции HandleSplitVertex, поскольку это наиболее общий случай: split вершина может быть соединена со всеми типами вершин, в отличие от остальных функций (в них рассматриваемая в данный момент вершина может быть соединена только с merge вершиной). Допустим, что диагональ была построена с помощью HandleSplitVertex по достижению split вершины . Рассмотрим четырёхугольник , заключённый между и - левым и правым ребром относительно и горизонтальными прямыми, проведёнными через и . Внутри , не может находиться ни одной из вершин , в противном случае не равнялся бы . Предположим теперь, что пересекает одну из сторон . Учитывая, что никаких вершин не лежит внутри и стороны не пересекаются, то должна пересечь либо отрезок, соединяющий и , либо и . Такое возможно только в случае, когда точками пересечения будут являться или , что не противоречит условию. Отсюда не пересекает ни одну из сторон в посторонних точках.
|
Оценкка работы
Построение описанной выше приоритетной очереди
происходит за линейное время. Когда заметающая прямая останавливается в вершине: операции с очередью занимают константу по времени, операции с деревом на запросы и обновления требуют . Добавление диагонали в требует . В итоге обработка каждой вершины требует , а весь алгоритм соответственно . Что касается памяти, она очевидно составляет . Очередь и дерево занимают линейную память.Триангуляция монотонного многоугольника
Идея такова: будем проходить сверху вниз по вершинам многоугольника проводя диагонали где это возможно. Отсортируем все вершины многоугольника
в порядке убывания их -координаты. Заведём стек вершин . В стеке будем хранить вершины, которые были обработаны, но не были отрезаны от многоугольника, то есть находятся в той части многоугольника, которая ещё не была триангулирована. В момент обработки некоторой вершины, будем пытаться провести из неё как можно больше диагоналей к вершинам, содержащимся в стеке. Эти диагонали отрезают треугольники от . На вершине стека будет храниться вершина, которая будет обрабатываться последней.Часть многоугольника
, лежащая выше последней обработанной вершины и которая ещё не была триангулирована имеет форму перевёрнутой воронки (см. рисунки). Одна сторона воронки состоит из одной из сторон , а другая состоит из цепи вершин, внутренние углы которых не меньше . Несложно догадаться тогда, что самая нижняя вершина стека является выпуклой.Рассмотрим алгоритм обработки вершины более подробно.
Ушной метод
Более эффективным я