Участник:RS42/Quickhull: различия между версиями

Материал из Алговики
Перейти к навигации Перейти к поиску
Строка 13: Строка 13:
 
Ребро (ridge) определяется как пересечение двух соседних граней и имеет размерность <math>d-2</math>. Граница грани состоит из ребер.
 
Ребро (ridge) определяется как пересечение двух соседних граней и имеет размерность <math>d-2</math>. Граница грани состоит из ребер.
  
Нам понадобится вычисление ориентированного расстояния от некоей точки <math>x</math> до гиперплоскости (signed distance to hyperplane). Зададим начало координат в точке <math>O</math>, плоскость определяется нормалью
+
Нам понадобится вычисление ориентированного расстояния от некоей точки <math>x</math> до гиперплоскости (signed distance to hyperplane). Зададим начало координат в точке <math>O</math>, плоскость определяется единичной нормалью
 
<math>\vec n</math> и смещением <math>h</math> относительно начала координат. Тогда ориентированное расстояние будет равно <math>(\vec x, \vec n) - h</math>, где <math>\vec x = x - O</math>.
 
<math>\vec n</math> и смещением <math>h</math> относительно начала координат. Тогда ориентированное расстояние будет равно <math>(\vec x, \vec n) - h</math>, где <math>\vec x = x - O</math>.
 
Если ориентированное расстояние положительно, то можно сказать, что точка находится выше плоскости (или плоскость видна из точки). В нашем случае все грани выпуклой оболочки во время построения будут иметь
 
Если ориентированное расстояние положительно, то можно сказать, что точка находится выше плоскости (или плоскость видна из точки). В нашем случае все грани выпуклой оболочки во время построения будут иметь
 
такие нормали и смещения, что для точек внутри оболочки расстояния до каждой плоскости будут неположительными.
 
такие нормали и смещения, что для точек внутри оболочки расстояния до каждой плоскости будут неположительными.
 +
 +
Рассмотрим сам алгоритм:
 
<source>
 
<source>
 
create a simplex of d+1 points
 
create a simplex of d+1 points
Строка 39: Строка 41:
 
   delete the facets in V
 
   delete the facets in V
 
</source>
 
</source>
 +
 +
Стартовый симплекс, который по ходу работы алгоритма будет расти до окончательной оболочки, можно создать из любых <math>d+1</math> точек, исходя из условия на <math>X</math>. Но в реальности это условие общего положения (general position) можно заменить на требование возможности выбрать
 +
<math>d</math>-мерный симплекс. Имеет смысл выбрать его таким образом, чтобы как можно больше точек уже оказалось в нем, поэтому его вершинами следует сделать точки с минимальными и максимальными координатами. Если таких точек не будет хватать, произведем добор произвольными.
 +
 +
Дальнейшие шаги алгоритма позволяют добавлять к промежуточной выпуклой оболочке новые вершины. По сути выбирается оптимальная в каком-то смысле внешняя точка <math>p</math>, а затем определяется множество <math>V</math> видимых из этой точки граней. Данные видимые грани отделены от невидимых
 +
множеством граничных ребер (horizon ridges). Далее граничные ребра и точка <math>p</math> образуют
 +
новые грани, видимые грани удаляются. Тем самым совершен переход к новой промежуточной выпуклой оболочке. Такое описание является обобщенным и ему также соответствует randomized incremental algorithm, в котором точка <math>p</math> выбирается случайным образом. В нашем случае точка <math>p</math> будет наиболее отдаленной точкой от плоскости текущей рассматриваемой грани <math>F</math>, что гарантирует
 +
присутствие <math>p</math> в итоговой выпуклой оболочке.
 +
Также можно выбрать <math>p</math> как наиболее отдаленную точку среди всех пар (грань-"самая дальняя точка этой грани").
 +
 +
Как решается проблема определения граничных ребер, когда уже выбрана точка <math>p</math>?
 +
Множество внешних точек (outside set) грани <math>F</math> представляет из себя множество точек (возможно не всех), из которых эта грань видна. Поэтому если <math>p</math> из множества внешних точек грани
 +
<math>F</math>, то это означает, что <math>F</math> будет видна из <math>p</math>, и следует начать поиск границы именно с соседей <math>F</math>. Пусть <math>H</math> - соседняя к <math>F</math> грань. Если <math>H</math> видна, то следует проверить таким же образом и соседей <math>H</math>. Если <math>H</math> не видна, то мы наткнулись на участок границы, и рассматривать соседей <math>H</math> нет смысла.
 +
 +
Получив граничные ребра, строим новые грани. Требуется обновить списки соседей и понять, какие внешние точки были захвачены. Захватить мы могли только те точки, которые были внешними для уничтоженных на этом шаге граней. То есть множество таких точек - это объединение множеств внешних точек граней из <math>V</math>. Распределяем эти точки по множествам внешних точек для новых граней.
 +
 +
Алгоритм будет продолжать свою работу до тех пор, пока не останется ни одного пустого множества внешних точек.
  
 
= Программная реализация алгоритма =
 
= Программная реализация алгоритма =

Версия 13:58, 21 октября 2017

1 Свойства и структура алгоритмов

1.1 Общее описание алгоритма

Задача построения выпуклой оболочки является одной из важных проблем вычислительной геометрии. Выпуклую оболочку множества точек [math]X[/math] можно определить следующим образом: это пересечение всевозможных выпуклых множеств, содержащих [math]X[/math]. В случае конечного числа [math]n[/math] точек из [math]X[/math]:

[math]\mathrm{Conv}(X)=\left\{\left.\sum_{i=1}^{n} \alpha_i x_i\ \right| (\forall i: \alpha_i\ge 0)\wedge \sum_{i=1}^{n} \alpha_i=1 \right\}.[/math]

Алгоритм Quickhull позволяет провести построение в пространстве произвольной размерности [math]d[/math]. Результатом работы является множество [math]d-1[/math]-мерных граней (facets) и вершин (vertices) полученной выпуклой оболочки.

1.2 Математическое описание алгоритма

Наложим на множество [math]X[/math] следующее условие: любые [math]d+1[/math] точки аффинно независимы (что тождественно тому, что они не лежат в одной [math]d-1[/math]-мерной плоскости). Выпуклая оболочка будет задаваться списком вершин и граней. Для каждой грани известны ее вершины, ее соседние грани и уравнение гиперплоскости, в которой эта грань лежит. Ребро (ridge) определяется как пересечение двух соседних граней и имеет размерность [math]d-2[/math]. Граница грани состоит из ребер.

Нам понадобится вычисление ориентированного расстояния от некоей точки [math]x[/math] до гиперплоскости (signed distance to hyperplane). Зададим начало координат в точке [math]O[/math], плоскость определяется единичной нормалью [math]\vec n[/math] и смещением [math]h[/math] относительно начала координат. Тогда ориентированное расстояние будет равно [math](\vec x, \vec n) - h[/math], где [math]\vec x = x - O[/math]. Если ориентированное расстояние положительно, то можно сказать, что точка находится выше плоскости (или плоскость видна из точки). В нашем случае все грани выпуклой оболочки во время построения будут иметь такие нормали и смещения, что для точек внутри оболочки расстояния до каждой плоскости будут неположительными.

Рассмотрим сам алгоритм:

create a simplex of d+1 points
for each facet F
  for each unassigned point p
    if p is above F
      assign p to F's outside set
for each facet F with non-empty outside set
  select the furthest point p of F's outside set
  initialize the visible set V to F
  for all unvisited neighbors N of facets in V
    if p is above N
      add N to V
  the boundary of V is the set of horizon ridges H
  for each ridge R in H
    create a new facet from R and p
     link the new facet to its neighbors
  for each new facet G
    for each unassigned point q in an outside set of a facet in V
      if q is above G
        assign q to outside set of G
  delete the facets in V

Стартовый симплекс, который по ходу работы алгоритма будет расти до окончательной оболочки, можно создать из любых [math]d+1[/math] точек, исходя из условия на [math]X[/math]. Но в реальности это условие общего положения (general position) можно заменить на требование возможности выбрать [math]d[/math]-мерный симплекс. Имеет смысл выбрать его таким образом, чтобы как можно больше точек уже оказалось в нем, поэтому его вершинами следует сделать точки с минимальными и максимальными координатами. Если таких точек не будет хватать, произведем добор произвольными.

Дальнейшие шаги алгоритма позволяют добавлять к промежуточной выпуклой оболочке новые вершины. По сути выбирается оптимальная в каком-то смысле внешняя точка [math]p[/math], а затем определяется множество [math]V[/math] видимых из этой точки граней. Данные видимые грани отделены от невидимых множеством граничных ребер (horizon ridges). Далее граничные ребра и точка [math]p[/math] образуют новые грани, видимые грани удаляются. Тем самым совершен переход к новой промежуточной выпуклой оболочке. Такое описание является обобщенным и ему также соответствует randomized incremental algorithm, в котором точка [math]p[/math] выбирается случайным образом. В нашем случае точка [math]p[/math] будет наиболее отдаленной точкой от плоскости текущей рассматриваемой грани [math]F[/math], что гарантирует присутствие [math]p[/math] в итоговой выпуклой оболочке. Также можно выбрать [math]p[/math] как наиболее отдаленную точку среди всех пар (грань-"самая дальняя точка этой грани").

Как решается проблема определения граничных ребер, когда уже выбрана точка [math]p[/math]? Множество внешних точек (outside set) грани [math]F[/math] представляет из себя множество точек (возможно не всех), из которых эта грань видна. Поэтому если [math]p[/math] из множества внешних точек грани [math]F[/math], то это означает, что [math]F[/math] будет видна из [math]p[/math], и следует начать поиск границы именно с соседей [math]F[/math]. Пусть [math]H[/math] - соседняя к [math]F[/math] грань. Если [math]H[/math] видна, то следует проверить таким же образом и соседей [math]H[/math]. Если [math]H[/math] не видна, то мы наткнулись на участок границы, и рассматривать соседей [math]H[/math] нет смысла.

Получив граничные ребра, строим новые грани. Требуется обновить списки соседей и понять, какие внешние точки были захвачены. Захватить мы могли только те точки, которые были внешними для уничтоженных на этом шаге граней. То есть множество таких точек - это объединение множеств внешних точек граней из [math]V[/math]. Распределяем эти точки по множествам внешних точек для новых граней.

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

2 Программная реализация алгоритма

3 Литература

  • Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull algorithm for convex hulls," ACM Trans. on Mathematical Software, 22(4):469-483, Dec 1996, http://www.qhull.org