Диаграмма Вороного — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Источники)
м (Инкрементальный алгоритм)
Строка 71: Строка 71:
 
[[Файл:voronoi-incremental.png|200px|thumb|right]]Храним диаграмму в РСДС. Пусть у нас уже есть диаграмма для точек <tex>p_1, p_2, ..., p_i</tex>. Добавим новый сайт <tex>p_{i+1}</tex>. Сначала найдём сайт <tex>p_j</tex>, в ячейку которого попадает <tex>p_{i+1}</tex>. После этого строим новую ячейку: сначала проведём серединный перпендикуляр для <tex>p_{i+1}p_j</tex>, он пересечёт границу ячейки <tex>\mathcal{V}(p_j)</tex> с ячейкой <tex>\mathcal{V}(p_k)</tex>; на следующем шаге будем строить серединный перпендикуляр для <tex>p_{i+1} p_k</tex> и так далее.
 
[[Файл:voronoi-incremental.png|200px|thumb|right]]Храним диаграмму в РСДС. Пусть у нас уже есть диаграмма для точек <tex>p_1, p_2, ..., p_i</tex>. Добавим новый сайт <tex>p_{i+1}</tex>. Сначала найдём сайт <tex>p_j</tex>, в ячейку которого попадает <tex>p_{i+1}</tex>. После этого строим новую ячейку: сначала проведём серединный перпендикуляр для <tex>p_{i+1}p_j</tex>, он пересечёт границу ячейки <tex>\mathcal{V}(p_j)</tex> с ячейкой <tex>\mathcal{V}(p_k)</tex>; на следующем шаге будем строить серединный перпендикуляр для <tex>p_{i+1} p_k</tex> и так далее.
  
[[Файл:voronoi-update-dcel.png|400px|thumb|left]]В процессе построения перпендикуляров необходимо обновлять РСДС. Каждый раз, когда новое ребро <tex>e</tex>, порождаемое <tex>p_{i+1}</tex> и <tex>p_j</tex>, пересекает существовавшее ранее ребро <tex>e'</tex>, создаются новая вершина <tex>v</tex> и начинается новое ребро <tex>e+1</tex>.
+
[[Файл:voronoi-update-dcel.png|400px|thumb|left]]В процессе построения перпендикуляров необходимо обновлять РСДС. Каждый раз, когда новое ребро <tex>e</tex>, порождаемое <tex>p_{i+1}</tex> и <tex>p_j</tex>, пересекает существовавшее ранее ребро <tex>e'</tex>, создаётся новая вершина <tex>v</tex> и начинается новое ребро <tex>e+1</tex>.
  
 
* для ребра <tex>e</tex> в РСДС конец в вершине <tex>v</tex>, следующее ребро — <tex>e'</tex>, инцидентные грани — слева <tex>\mathcal{V}(i+1)</tex>, справа — <tex>\mathcal{V}(j)</tex>;
 
* для ребра <tex>e</tex> в РСДС конец в вершине <tex>v</tex>, следующее ребро — <tex>e'</tex>, инцидентные грани — слева <tex>\mathcal{V}(i+1)</tex>, справа — <tex>\mathcal{V}(j)</tex>;

Версия 18:38, 10 мая 2015

Эта статья находится в разработке!

Определения

Неформальное определение

Пример диаграммы Вороного

Есть множество точек [math]P[/math] на плоскости. Для всех точек [math]q \notin P[/math] этой плоскости узнаем ближайшую к [math]q[/math] точку из [math]P[/math]. Таким образом получим разбиение плоскости на кусочки, в каждом из которых содержится одна точка [math]p_i[/math] из [math]P[/math] и все точки [math]q[/math], для которых [math]p_i[/math] — ближайшая среди точек из [math]P[/math].

Формальное определение

[math]P = \{ p_1, p_2, ..., p_n\}[/math] — множество точек на плоскости. Назовём их сайтами (site).


Определение:
Диаграмма Вороного (Voronoi diagram, [math]Vor(P)[/math]) для сайтов [math]P = \{ p_1, p_2, ..., p_n\}[/math] на плоскости — это разбиение плоскости на [math]n[/math] ячеек (ячейка Вороного, Voronoi cell, [math]\mathcal{V}(p_i)[/math]), по одной для каждого сайта, которые обладают свойством: [math]\rho(q, p_i) \lt \rho(q, p_j)[/math] для всех [math]p_j \in P, \ j \neq i[/math].


В зависимости от контекста будем называть диаграммой Вороного как разбиение на ячейки, так и составляющие эти ячейки вершины и рёбра.

Свойства

Количество вершин и рёбер в ячейке

Возьмём две точки плоскости: [math]p[/math] и [math]q[/math]. Проведём серединный перпендикуляр к отрезку [math]pq[/math]; полученную полуплоскость, которая содержит в себе [math]p[/math], обозначим [math]h(p, q)[/math], другую — [math]h(q, p)[/math]. Заметим, что [math]r \in h(p, q)[/math] тогда и только тогда, когда [math]\rho(r, p) \lt \rho(r, q)[/math]. Отсюда вытекает следующее:

Утверждение:
[math]\mathcal{V}(p_i) = \cap_{1 \leqslant j \leqslant n, j \neq i} h(p_i, p_j)[/math]

Отсюда получаем, что что ячейка Вороного — это пересечение [math]n - 1[/math] полуплоскостей, и поэтому представляет собой (возможно, неограниченную) открытую выпуклую область с не более чем [math]n - 1[/math] вершинами и [math]n - 1[/math] рёбрами.

Отсутствие прямых в общем случае

Теорема:
Пусть [math]P[/math] — множество из [math]n[/math] сайтов. Если они все лежат на одной прямой, то [math]Vor(P)[/math] представляет собой [math]n - 1[/math] параллельную прямую. Иначе [math]Vor(P)[/math] связная и все её рёбра — либо отрезки, либо лучи.
Доказательство:
[math]\triangleright[/math]
Voronoi-not-lines.png
В случае, если все сайты лежат на одной прямой, каждая пара соседних сайтов порождает серединный перпендикуляр к отрезку, содержащему их, и, соответственно, к прямой, которая содержит все сайты. Так получаются [math]n - 1[/math] прямая, каждая из которых перпендикулярна прямой, содержащей сайты, а значит, эти прямые параллельны.

Рассмотрим теперь случай, когда сайты не лежат на одной прямой. Покажем, что рёбра — это отрезки или лучи, от противного. Предположим, что есть ребро [math]e[/math], являющееся прямой. Пусть оно — граница ячеек [math]\mathcal{V}(p_i)[/math] и [math]\mathcal{V}(p_j)[/math]. Пусть точка [math]p_k \in P[/math] не лежит на прямой [math]p_i p_j[/math] (по условию такая точка существует). Тогда серединный перпендикуляр к [math]p_j p_k[/math] не параллелен [math]e[/math], и, значит, он его пересекает. Но тогда та часть [math]e[/math], что лежит в [math]h(p_k, p_j)[/math], не может быть границей [math]\mathcal{V}(p_j)[/math], потому что она ближе к [math]p_k[/math], чем к [math]p_j[/math]. Пришли к противоречию.

Докажем теперь, что диаграмма связна. Предположим, что это не так. Тогда на её рёбрах найдутся две точки [math]s[/math] и [math]t[/math], между которыми нет пути по рёбрам диаграммы. Рассмотрим отрезок [math]st[/math]. Он пересекает некоторое количество ячеек диаграммы, и, раз пути по рёбрам нет, какая-то из них несвязная. Это возможно, только если какая-то ячейка представляет собой полосу, ограниченную двумя параллельными прямыми. Но в нашем случае в диаграмме не может быть прямых, пришли к противоречию.
[math]\triangleleft[/math]

Линейность

Теорема:
Для [math]n \geqslant 3[/math] сайтов диаграмма Вороного содержит не больше [math]2n - 5[/math] вершин и [math] 3n - 6[/math] рёбер.
Доказательство:
[math]\triangleright[/math]
Voronoi-infinite-vertex.png
Для случая сайтов, лежащих на одной прямой, утверждение напрямую следует из вида диаграммы для этого случая, поэтому рассмотрим общий случай. По формуле Эйлера [math]v - e + f = 2[/math], где [math]v[/math] — число вершин, [math]e[/math] — число рёбер и [math]f[/math] — число граней связного планарного графа. Мы не можем сразу применить эту формулу к [math]Vor(P)[/math], потому что в этом графе есть полубесконечные рёбра. Поэтому добавим вершину [math]n_\infty[/math], и все полубесконечные рёбра мы превратим в рёбра, инцидентные ей. Таким образом мы увеличили число вершин на одну, а число рёбер не изменилось. Число граней равно [math]n[/math] по определению диаграммы Вороного. Тогда по формуле Эйлера получаем [math](v + 1) - e + n = 2[/math].

Сумма степеней всех вершин полученного графа равна [math]2e[/math], так как у каждого ребра есть ровно два конца (нет петель). Также у из каждой вершины исходят как минимум три ребра. Отсюда получаем [math]2e \geqslant 3 (n + 1)[/math].

Домножим равенство на два и вычтем из него полученную нижнюю границу для [math]2 \cdot e[/math], в результате получим [math] v \leqslant 2n - 5[/math]. Далее подставим этот результат в равенство и получим [math]e \leqslant 3n - 6[/math], что и требовалось доказать.
[math]\triangleleft[/math]

Связь с триангуляцией Делоне

Определение:
Наибольшая пустая окружность точки [math]q[/math] по отношению к [math]P[/math] ([math]C_P(q)[/math]) — наибольшая окружность с центром в [math]q[/math] такая, что во внутренности соответствующего ей круга не лежит ни одного сайта из [math]P[/math].


Лемма:
Точка [math]q[/math] — вершина диаграммы Вороного в том и только в том случае, когда [math]C_P(q)[/math] содержит три и более сайтов на своей границе.
Доказательство:
[math]\triangleright[/math]

Предположим, что [math]q[/math] существует, а [math]p_i, \ p_j, \ p_k[/math] — соответствующие точки. Так как внутри [math]C_P(q)[/math] нет других сайтов, [math]q[/math] должна быть на границе [math]\mathcal{V}(p_i), \ \mathcal{V}(p_j), \ \mathcal{V}(p_k)[/math] одновременно, то есть вершиной диаграмму.

Докажем в другую сторону: каждая вершина [math]q[/math] диаграммы инцидентна минимум трём рёбрам, и, поэтому, как минимум трём ячейкам [math]\mathcal{V}(p_i), \ \mathcal{V}(p_j), \ \mathcal{V}(p_k)[/math]. Тогда [math]q[/math] лежит на равном расстоянии от [math]p_i, \ p_j, \ p_k[/math] и не может быть другого сайта ближе к [math]q[/math], так как иначе [math]\mathcal{V}(p_i), \ \mathcal{V}(p_j), \ \mathcal{V}(p_k)[/math] не сойдутся в [math]q[/math]. Поэтому можно построить окружность с центром в [math]q[/math] и [math]p_i, \ p_j, \ p_k[/math] на границе так, что внутри не будет других сайтов.
[math]\triangleleft[/math]
Лемма:
Серединный перпендикуляр к отрезку [math]p_i p_j[/math] образует ребро диаграммы Вороного в том и только в том случае, если на нём есть точка [math]q[/math] такая, что [math]C_P(q)[/math] содержит на своей границе только сайты [math]p_i, \ p_j[/math].
Доказательство:
[math]\triangleright[/math]
Voronoi-circles.png
Предположим, что [math]q[/math] существует. Тогда, так как [math]C_P(q)[/math] не содержит в себе сайтов и содержит [math]p_i, \ p_j[/math] на границе, [math] \rho(q, p_i) = \rho(q, p_j) \leqslant \rho(q, p_k), \ 1 \leqslant k \leqslant n[/math]. Отсюда выходит, что [math]q[/math] лежит — вершина [math]Vor(P)[/math] или лежит на ребре диаграммы. Но по предыдущей лемме выходит, что [math]q[/math] не может быть вершиной диаграммы. Значит, она лежит на ребре, заданном серединным перпендикуляром к [math]p_i p_j[/math]. Докажем в другую сторону: пусть серединный перпендикуляр к [math]p_i p_j[/math] задаёт ребро диаграммы. Наибольшая пустая окружность любой точки [math]q[/math] на этом ребре должна содержать на границе [math]p_i[/math] и [math]p_j[/math], и никаких других сайтов внутри.
[math]\triangleleft[/math]
Теорема:
Если соединить все сайты, соответствующие смежным ячейкам диаграммы Вороного, получится триангуляция Делоне для этого множества точек.
Доказательство:
[math]\triangleright[/math]
Если ячейки, соответствующие сайтам [math]p_i, \ p_j[/math], смежны, то серединный перпендикуляр к отрезку [math]p_i p_j[/math] образует ребро диаграммы Вороного, то есть к нему применима предыдущая лемма и можно построить окружность с [math]p_i[/math] и [math]p_j[/math] на границе, внутри которой не будет других сайтов. Вспомним, что триангуляции Делоне принадлежат те и только те рёбра (с поправкой на точки, лежащие на одной окружности), на которых можно построить такую окружность, что внутри неё не будет лежать никаких точек. Тогда ребро [math]p_i p_j[/math] является ребром триангуляции Делоне. За счёт равносильности в обеих используемых леммах мы добавим все рёбра и не построим лишних.
[math]\triangleleft[/math]

Построение

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

Будем пересекать полуплоскости по по свойству ячейки диаграммы. Необходимо [math]n[/math] раз пересечь [math]n - 1[/math] плоскость, что суммарно делается за [math]O(n^2 \log n)[/math].

Инкрементальный алгоритм

Voronoi-incremental.png
Храним диаграмму в РСДС. Пусть у нас уже есть диаграмма для точек [math]p_1, p_2, ..., p_i[/math]. Добавим новый сайт [math]p_{i+1}[/math]. Сначала найдём сайт [math]p_j[/math], в ячейку которого попадает [math]p_{i+1}[/math]. После этого строим новую ячейку: сначала проведём серединный перпендикуляр для [math]p_{i+1}p_j[/math], он пересечёт границу ячейки [math]\mathcal{V}(p_j)[/math] с ячейкой [math]\mathcal{V}(p_k)[/math]; на следующем шаге будем строить серединный перпендикуляр для [math]p_{i+1} p_k[/math] и так далее.
Voronoi-update-dcel.png
В процессе построения перпендикуляров необходимо обновлять РСДС. Каждый раз, когда новое ребро [math]e[/math], порождаемое [math]p_{i+1}[/math] и [math]p_j[/math], пересекает существовавшее ранее ребро [math]e'[/math], создаётся новая вершина [math]v[/math] и начинается новое ребро [math]e+1[/math].
  • для ребра [math]e[/math] в РСДС конец в вершине [math]v[/math], следующее ребро — [math]e'[/math], инцидентные грани — слева [math]\mathcal{V}(i+1)[/math], справа — [math]\mathcal{V}(j)[/math];
  • добавляем в РСДС ребро [math]e + 1[/math] с началом в [math]v[/math] и предыдущим ребром [math]e[/math];
  • удаляем все рёбра, лежащие между вершиной начала [math]e[/math] и вершиной конца [math]e[/math], по часовой стрелке;
  • обновляем ребро, соответствующее [math]p_j[/math] — им становится [math]e[/math];
  • создаём вершину [math]v[/math] с ребром [math]e[/math].

Каждый шаг выполняется за [math]O(i)[/math], значит, суммарно диаграмма из [math]n[/math] сайтов с нуля создаётся за [math]O(n^2)[/math].

Диаграмма [math]k[/math]-го порядка

Ячейка Вороного [math]k[/math]-го порядка — множество точек, имеющих в качестве ближайших [math]k[/math] соседей определённое множество из [math]k[/math] сайтов. Чтобы построить диаграмму [math]k[/math]-го порядка, нужно взять диаграмму [math]k - 1[/math]-го порядка для первых [math]k - 1[/math] сайтов и заменить каждую ячейку на диаграмму Вороного на множестве остальных сайтов.

Диаграмма [math]n - 1[/math]-го порядка является farthest-point диаграммой, т.е. в каждой её ячейке все точки являются наиболее удалёнными от какого-то сайта.

Диаграмма первого порядка
Диаграмма второго порядка
Диаграмма третьего порядка
Диаграмма десятого порядка, она же farthest-point
Утверждение:
Сайт имеет ячейку в farthest-point диаграмме тогда и только тогда, когда он является вершиной выпуклой оболочки всех сайтов.
Утверждение:
Все ячейки в farthest-point диаграмме неограничены.

Чтобы найти farthest-point диаграмму, сначала найдём выпуклую оболочку всех сайтов. Обозначим сайты, её образующие, через [math]p_1, p_2, ..., p_m[/math]. Делаем их случайную перестановку, но запомним порядки обхода в выпуклой оболочке по часовой стрелке ([math]cw(p_i)[/math]) и против часовой ([math]ccw(p_i)[/math]). Далее удаляем из выпуклой оболочки все точки, кроме первых трёх (запоминая при этом их соседей в оболочке на момент удаления). После этого мы строим farthest-point диаграмму для первых трёх точек и последовательно добавляем остальные (удалённые) в порядке, обратном порядку удаления.

Voronoi-farthest-construct.png

Для точки [math]p_i[/math] ячейка встанет «между» ячейками, соответствующими [math]cw(p_i)[/math] и [math]ccw(p_i)[/math]. Перед добавлением [math]p_i[/math] [math]cw(p_i)[/math] и [math]ccw(p_i)[/math] — соседи, поэтому между ними построен серединный перпендикуляр. Серединный перпендикуляр к [math]p_i ccw(p_i)[/math] даст новое ребро, которое лежит в farthest-point ячейке [math]ccw(p_i)[/math] и является частью границы ячейки [math] p_i[/math]. Обойдём ячейку [math]ccw(p_i)[/math] по часовой стрелке, чтоб понять, какое ребро пересечёт перпендикуляр. С другой стороны этого ребра лежит ячейка какой-то точки [math]p_j[/math], и серединный перпендикуляр [math]p_i p_j[/math] тоже даст ребро ячейке [math]p_i[/math]. Аналогично совершим обход и так далее. Последний серединный перпендикуляр будет построен для [math]p_i cw(p_i)[/math]. После этого удаляем рёбра, которые лежат внутри новой ячейки.

Источники