Straight skeleton — различия между версиями
Shersh (обсуждение | вклад) м (→Топологические свойства)  | 
				Shersh (обсуждение | вклад)   (→Топологические свойства)  | 
				||
| Строка 22: | Строка 22: | ||
* <tex> Split\ event </tex> {{---}} происходит, когда ребро разбивается на два новых ребра, исходящих из точки преломления старого. Такое событие происходит на биссектрисе вогнутой вершины многоугольника. И тогда стягиваемая многоугольником область может разбивться на две непересекающиеся многоугольные области.  | * <tex> Split\ event </tex> {{---}} происходит, когда ребро разбивается на два новых ребра, исходящих из точки преломления старого. Такое событие происходит на биссектрисе вогнутой вершины многоугольника. И тогда стягиваемая многоугольником область может разбивться на две непересекающиеся многоугольные области.  | ||
| − | На рисунке <tex> edge\ event' </tex>ы изображены зелёным кругом, а <tex> split\ event' </tex>ы {{---}} красным прямоугольником.  | + | На рисунке <tex>edge\ event'</tex>ы изображены зелёным кругом, а <tex>split\ event'</tex>ы {{---}} красным прямоугольником.  | 
[[Файл:skeleton_event_example.jpg|400px]]  | [[Файл:skeleton_event_example.jpg|400px]]  | ||
| Строка 28: | Строка 28: | ||
Таким образом, <tex> event' </tex>ы соответствуют внутренним вершинам <tex> \mathrm{straight}\ \mathrm{skeleton} </tex>, гранями являются области многоугольника, заметаемые сторонами многоугольника в процессе стягивания, дуги <tex> \mathrm{straight}\ \mathrm{skeleton} </tex> соединяют либо две внутренние вершины либо внутреннюю вершину с листом {{---}} вершиной многоугольника.  | Таким образом, <tex> event' </tex>ы соответствуют внутренним вершинам <tex> \mathrm{straight}\ \mathrm{skeleton} </tex>, гранями являются области многоугольника, заметаемые сторонами многоугольника в процессе стягивания, дуги <tex> \mathrm{straight}\ \mathrm{skeleton} </tex> соединяют либо две внутренние вершины либо внутреннюю вершину с листом {{---}} вершиной многоугольника.  | ||
| − | Стоит также отметить, что в общем случае <tex> split\ event'</tex>ы могут быть нетривиальными. На рисунке ниже в случае <tex> (c) </tex> в вершине <tex> p </tex> совпали <tex>split\ event</tex> из вершины <tex> u </tex> и <tex> edge\ event</tex> ребра <tex>   | + | Стоит также отметить, что в общем случае <tex> split\ event'</tex>ы могут быть нетривиальными. На рисунке ниже в случае <tex> (c) </tex> в вершине <tex> p </tex> совпали <tex>split\ event</tex> из вершины <tex> u </tex> и  ребра <tex> e </tex> и <tex> edge\ event</tex> ребра <tex> uv </tex>, а в случае <tex> (d) </tex> совпали два <tex> split\ event'</tex>а вершин <tex> u_1 </tex> и <tex> u_2 </tex>. Случаи <tex> (a) </tex> и <tex> (b) </tex> {{---}} простые <tex> edge </tex> и <tex> split\ event'</tex>ы.  | 
[[Файл:Event_example.png]]  | [[Файл:Event_example.png]]  | ||
Версия 00:56, 4 декабря 2014
Существует целый класс структур типа , которые описывают базовые топологические свойства объектов. Структура была придумала Oswin Aichholzer. Она используются в различных практических задачах (проектирование крыш для зданий) и для доказательства некоторых теорем[1].
Содержание
Топологические свойства
| Определение: | 
| Straight skeleton (Angular Bisector Network, ABN) полигона без самопересечений называется планарный граф, определяющий разбиение полигона на регионы, границами которых являются стороны полигона, биссектрисы углов и отрезки, соединяющие вершины straight skeleton, образовавшиеся в результате сжатия полигона. | 
Опишем подробней, как получается такое разбиение. Мы можем представить, будто все стороны прямоугольника параллельно двигаются внутрь с одинаковой постоянной скоростью, то есть многоугольник как бы сжимается внутрь. Тогда  вершины будут двигаться вдоль биссектрис  , а точки пересечения биссектрис будут являться точками, в которых рёбра полностью сократились (выродились в точку). В каждый момент времени от начала движения рёбер мы получаем слоистую структуру (рис 1.). На рис. 2 синим цветом выделен  — множество отрезков, образованных точками пересечения при движении сторон полигона. Чем-то структура похожа на строение крыши в домах (рис. 3). И для решения этой задачи как раз  и может применяться: по стенам здания необходимо спроектировать его крышу.
Процесса стягивания многоугольника продолжается до тех пор, пока происходят его топологические изменения, то есть меняется число вершин в стянутом многоугольнике, и таким образом появляются новые вершины дерева . Существуют два типа изменений, в ходе которых образуются новые вершины дерева:
- — данное изменение происходит, когда сторона многоугольника полностью стягивается, делая соседние стороны инцидентными.
 - — происходит, когда ребро разбивается на два новых ребра, исходящих из точки преломления старого. Такое событие происходит на биссектрисе вогнутой вершины многоугольника. И тогда стягиваемая многоугольником область может разбивться на две непересекающиеся многоугольные области.
 
На рисунке ы изображены зелёным кругом, а ы — красным прямоугольником.
Таким образом, ы соответствуют внутренним вершинам , гранями являются области многоугольника, заметаемые сторонами многоугольника в процессе стягивания, дуги соединяют либо две внутренние вершины либо внутреннюю вершину с листом — вершиной многоугольника.
Стоит также отметить, что в общем случае ы могут быть нетривиальными. На рисунке ниже в случае в вершине совпали из вершины и ребра и ребра , а в случае совпали два а вершин и . Случаи и — простые и ы.
Свойства Straight skeleton
Из процесса построения следует, что он является планарным графом. Ранее уже упоминалось, что он также является деревом. Будем обозначать простого полигона без самопересечений , в котором вершин, как . Тогда справедливы следующие леммы:
| Лемма (1): | 
 является деревом, содержит  граней, не более  внутренние вершины и не более  рёбер.  | 
| Доказательство: | 
| 
 Каждая грань начинает образовываться во время стягивания ребра , и даже если на ребре произошёл , сама грань не могла разделиться. Построение грани завершается, когда ребро полностью стягивается. И это ребро дальше не может появиться снова, поэтому граней в столько, сколько сторон в многоугольнике, то есть ровно . То, что является деревом, легко доказывается по индукции. База верна, когда внутренняя вершина всего одна. Тогда у листьями будут вершины многоугольника. Такой граф очевидным образом будет деревом. Если в внутренних вершин, то рассмотрим самый первый . Он закончился в какой-то внутренней вершине , у неё есть смежные листья — вершины, инцидентные этому ребру, — и из неё достижимы другие ы, с не более чем внутренними вершинами, и они являются деревьями по предположению индукцию. Тогда получаем, что для вершин тоже будет деревом. Внутренние вершины в имеют степень не меньше — простой перебор всех случаев ов (степень будет больше, если в одной вершине совпало несколько событий). Так как имеет листьев, то внутренних вершин будет не больше , а так как является деревом, то рёбер у него будет не более . | 
Замечание: если мы рассмотрим в какой-то момент времени, то он вполне может содержать циклы (это видно на рисунке ниже). Однако его конечная структура будет деревом.
Алгоритм с изпользованием SLAV
Далее будет описан алгоритм, придуманный Petr Felkel, который строит за время , или просто , где — общее число вершин в полигоне, — число вогнутых вершин в полигоне. Немного модифицированный этот алгоритм используется в открытой библиотеке вычислительной геометрии CGAL[2]. Однако этот алгоритм всё равно ещё достаточно медленный. В реальной жизни используют его модификации или более сложные алгоритмы.
Сначала алгоритм будет рассмотрен на простом случае — выпуклом многоугольнике, — а потом на невыпуклом многоугольнике.
Выпуклый полигон
В случае выпуклого многоугольника возникают только ы по определению. Поэтому просто алгоритм можно описать следующим образом: найдём точки пересечения биссектрис многоугольника для каждой вершины со всеми соседними вершинами, возьмём такую точку, в которой произойдёт самый первый , добавим полученную вершину в , соеденим её с вершинами ребра, которое исчезло в процессе текущего а, а потом перестроим полигон, создав новую вершину и подвинув все остальные вдоль биссектрис на одинаковое расстояние. Будем продолжать этот процесс до тех пор, пока многоугольник не превратится в треугольник.
Теперь реализуем этот алгоритм более эффективно. Для этого мы будем использовать специальную структуру данных — (set of circular lists of active vertices). Эта структура хранит цикл всех вершин для внешней грани, а так же цикл для каждой дыры многоугольника и для всех многоугольников, возникающих в процессе построения . В данном случае у нас будет просто — циклический список всех вершин многоугольника.
Алгоритм для выпуклых полигонов
Далее считаем, что полигон представлен рёбрами вдоль движения по контуру полигона против часовой стрелки.
Шаг 1. Инициализация:
- Поместим все вершины многоугольника в двусвязный циклический список в порядке обхода вдоль контура. Все вершины в считаются активными сейчас.
 - Для каждой вершины в добавим указатели на инцидентные рёбра и , а также найдём луч биссектрисы .
 - Для каждой вершины найдём ближайшее пересечение биссектрисы с лучами и . Если это пересечение существует, то положим его в приоритетную очередь согласно — расстоянию от точки пересечения до одного из рёбер, инцидентных вершине . Для каждой точки пересечения будем так же хранить два указателя на вершины и — начала лучей биссектрис, которые пересекаются в точке . Эти указатели понадобятся в будущем, когда нужно будет определять соответствующие вершинам рёбра (см. рисунок ниже).
 
Шаг 2. Следующие действия выполняются в цикле, пока приоритетная очередь не пустая:
- Извлечём точку пересечения из приоритетной очереди.
 - Если вершины и , соответствующие данной точке пересечения помечены как обработанные, то переходим к следующей итерации цикла шага 2. Это означает, что ребро между данными вершинами полностью стянулось (обработанные вершины и стянутые рёбра помечены крестом на рисунке ниже).
 - Если осталось всего три вершины , то добавим в рёбра . В случае выпуклого многоугольника в этом месте можно завершить алгоритм. Но в общем случае нужно будет перейти к началу цикла снова.
 - Добавим в рёбра .
 -  Теперь необходимо модифицировать  (детали на рисунке ниже):
- пометим вершины и как обработанные (напомню, что они обозначаются крестом на рисунке к данному алгоритму),
 - создадим новую вершину в точке пересечения (отмечена квадратиком на рисунке),
 - добавим вершину в , то есть между предыдущем к и следующим к узлами,
 - добавим вершине указатели на соответствующие рёбра и .
 
 -  Посчитаем дополнительные величины для вершины :
- луч биссектрисы между рёбрами и ,
 - точки пересечения луча b с соседями в , как в шаге
 - сохраним ближайшие точки пересечения в приоритетной очереди.
 
 
Заметим, что нам не нужно пересчитывать все расстояния в очереди приоритетов. Если мы стянем полигон до первого события исчезания ребра, то относительный порядок остальных событий не изменится. Нам необходимо только вставить новые точки пересечения в правильные места. Это можно эффективно сделать, если использовать структуру данных типа skip list.
В этом случае асимптотика алгоритма составляет , так как на каждой итерации цикла нам нужно положить константное число элементов в очередь, а итераций цикла не больше .
Частные случаи
Частным случаем в алгоритме может быть совпадение нескольких ов в одной точке. Эти совпадения добавляются в шагах и , но могут быть относительно легко обработаны в шаге . Также может случиться, что какие-то рёбра не стянулись в итоге в одну вершину, а слились. Такое возможно, если какие-то стороны полигона были изначально параллельны (этот случай легко увидеть на прямоугольнике, не являющемся квадратом). С этим частным случаем можно разобраться в шаге , проверив, не совпала ли одна из трёх вершин с другой. В выпуклом многоугольнике слияние двух рёбер может произойти только один раз (что неправда для невыпуклого многоугольника), поэтому здесь несложно разобраться с таким случаем.
Невыпуклый полигон
Основной принцип для невыпуклых полигонов такой же. Только с вершиной ещё хранится дополнительный атрибут, обозначающий событие, которое в ней произошло: или .
Наличие невыпуклой вершины может привести (а может и не привести) к разделению внутренней области. Невыпуклая вершина может так же участвовать в обычном е (точка на рисунке выше). В таком случае ы обрабатываются так же, как и в алгоритме с выпуклым многоугольником.
Посмотрим теперь, что делать с точкой , в которой возникает .
Нахождение координат точки B
Работа с LAV в момент возникновения split event'a
Частный случай множественных split event'ов на одном ребре
Алгоритм для невыпуклых полигонов
Случай полигонов с дырами
Данный алгоритм может работать и с многоугольниками, содержащими дыры, если они ориентированы по часовой стрелки, чтобы внутренняя область многоугольника лежала слева от рёбер. И в самом начале алгоритма каждый замкнутый контур помещается в свой в множестве .
Алгоритм построения с помощью Motorcycle graph
Рассмотрим алгоритм построения на основе мотографов.
TODO: Алгоритм на мотографах
Другие алгоритмы
Существует простой в понимании и реализации алгоритм для построения на основе триангуляции, который работает за время [3]. Aichholzer смог обобщить этот алгоритм для построения произвольного планарного графа[4]. Также автором в его оригинальной статье был представлен алгоритм построения данной структуры, базирующийся на понятии волнового фронта (англ. wavefront). Этот алгоритм может быть реализован за время с использованием памяти либо с использованием приоритетной очереди за время и памяти[5]. Известен алгоритм построения для монотонных полигонов за время с использованием памяти[6].
В данном конспект был (P.S. точнее, ещё будет) представлен алгоритм на основе мотографов, который придумали Stefan Huber и Martin Held. Они говорят, что даже смогли реализовать этот алгоритм, но код нигде не выкладывали.
Примечания
- ↑ Wikipedia — Fold-and-cut theorem
 - ↑ Stepan Obdrazalek, "The Angular bisector network Implementation and the CGAL library"
 - ↑ Stefan Huber, Martin Held, "Straight Skeletons and their Relation to Triangulations"
 - ↑ Oswin Aichholzer, Franz Aurenhammera, "Straight Skeletons for General Polygonal Figures in the Plane"
 - ↑ Oswin Aichholzer, Franz Aurenhammera, "A Novel Type of Skeleton for Polygons"
 - ↑ Therese Biedl, Martin Held, Stefan Huber, Dominik Kaaser, Peter Palfrader, "Straight Skeletons of Monotone Polygons"
 
Источники информации
- Wikipedia — Straight skeleton
 - Designing roofs and drawing phylogenetic trees
 - Eric Berberich, "Straight Skeleton, Computational Geometry and Geometric Computing Seminar"
 - Petr Felkel, Stepan Obdrazalek, "Straight Skeleton Implementation"
 - Engineering a weighted straight skeleton algorithm
 - Визуализатор алгоритма
 



