Метод “заворачивания подарка”
Метод “заворачивания подарка” [4] предназначен для построения выпуклой оболочки в пространстве произвольной размерности.
Вследствие того, что в симплициальном политопе любое ребро является общим в точности для двух граней и две грани имеют общее ребро тогда и только тогда, когда ребро определяется общим подмножеством из двух вершин для множеств вершин, определяемых этими гранями, то можно использовать следующий метод, известный как метод заворачивания подарка.
На
каждом шаге строится связная часть
выпуклой оболочки (из одной грани можно
пройти в другую, если у них есть общее
ребро). Выбирается грань
из текущей построенной части выпуклой
оболочки, у этой грани выбирается ребро
такое, что другая грань этого ребра
еще не найдена. Строится плоскость
,
содержащая в себе грань
.
Построенная плоскость ”наклоняется”
через ребро
к множеству точек, пока не встретится
некоторая точка
.
На базе ребра
и точки
строится новая грань выпуклой оболочки
и алгоритм продолжает работу. Как и в
двумерном случае, точку
можно охарактеризовать наименьшим
углом поворота плоскости
(см.
рисунок 4).
|
|
Рисунок 4 Иллюстрация
выбора грани, определяемой ребром
|
Определим
для грани
верхнее полупространство как
,
где
и
– нормаль
и нижнее полупространство как
–
верхнее полупространство.
Алгоритм содержит несколько основных этапов, реализацию которых необходимо проанализировать более подробно:
Algorithm GIFT-WRAPPING(P) CH(P)
|
1 |
инициализировать выпуклую оболочку пустой |
|
2 |
найти некоторое исходное ребро выпуклой оболочки и добавить его в стек ребер S |
|
3 |
while Size(S) > 0 do |
|
4 |
|
|
5 |
найти такую
плоскость
|
|
6 |
найти множество
|
|
7 |
построить
|
|
8 |
создать новые
грани, определяемые
|
|
9 |
обойти новые
крайние ребра
|
|
10 |
end-do |
|
11 |
вернуть построенную
выпуклую оболочку
|
Построение
начального ребра
(строка 2), принадлежащего выпуклой
оболочке
,
может быть сделано за время
:
Найти точку
,
заведомо являющейся вершиной выпуклой
оболочки, в качестве такой точки можно
взять наименьшую точку, если на точках
определен следующий порядок: для точек
,
если вектор
лексикографически меньше вектора
(сложность шага
).Построить плоскость
,
(сложность шага
).Плоскость
наклоняется через прямую, параллельную
осиOY
и проходящую через точку
,
до тех пор, пока не будет встречена
первая точка
(сложность шага
).Сформировать множество точек
,
принадлежащих плоскости
(
)
за время
.Найти любое ребро e выпуклой оболочки множества точек
(аналогично как в алгоритме Джарвиса)
за время
.
Это ребро будет ребром
.
В
процессе работы алгоритма используется
стек ориентированных ребер. Таким
образом, если пара
определяет ребро
,
то в стек на разных шагах алгоритма
будут добавлены ориентированные ребра
и
.
На
5-ой строке алгоритма нормаль плоскости
определяется как
(ребро
ориентировано в порядке обхода против
часовой стрелки вершин грани, содержащейся
в плоскости
,
если смотреть извне на выпуклую оболочку).
Таким образом, шаги 5 и 6 могут быть
сделаны за время
.
На
шаге 7 строится двумерная выпуклая
оболочка найденного множества точек
(больше трех точек могут лежать в
плоскости
).
Этот шаг можно сделать за время
,
где
– множество крайних точек выпуклой
оболочки из множества
.
Для достижения такой оценки можно
использовать алгоритм заворачивания
подарка на плоскости, либо асимптотически
оптимальный алгоритм со сложностью
.
При анализе общей сложности алгоритма
важно, чтобы на этом шаге использовался
“output-sensitive”
алгоритм.
После
построения выпуклой оболочки
можно выделить копланарные грани (строка
8), принадлежащие
(см. рисунок 5) за линейное время от
количества этих граней (таких граней
будет
).
Крайние ребра можно найти также за
линейное время (исключая ребро
их будет
).
|
|
Рисунок 5
созданные грани:
новые ориентированные ребра:
|
Узнать
было ли ориентированное ребро ранее
добавлено в стек можно за
,
используя сбалансированное дерево
поиска (строка 9) и введя произвольный
порядок на ребрах. Заметим, что поскольку
необходимо только добавлять ребра в
структуру данных и искать в ней, то в
качестве такой структуры можно
использовать хеш-таблицу.
Общее
количество выполнения цикла while
(строки 3-10) равно количеству граней
,
принадлежащих разным плоскостям.
Оценим
общую сложность алгоритма в трехмерном
пространстве. Обозначим за
множество
,
а за
множество
наi-ом
шаге работы алгоритма (другими словами
при нахождении i-ой
плоскости). Поиск множества
можно выполнить за
операций (строки 5-6). Построение двумерной
выпуклой оболочки делается за
операций (строка 7). Создание новых
граней требует линейного времени (строка
8), поиск и добавление
ориентированных ребер в стек требует
.
Пусть
L
– количество ребер в
,
тогда
и
.
Общее
время работы:
![]()
.
Краткие результаты:
лучший случай, количество крайних точек
:
;худший случай, все точки множества на оболочке:
;среднее время:
.


