Выпуклая оболочка в n-мерном пространстве — различия между версиями
Строка 5: | Строка 5: | ||
Выберем любые две точки <tex>p_1</tex> и <tex>p_2</tex>. Далее из оставшихся выберем точку <tex>p_3</tex>, которая не лежит на прямой, образованной точками <tex>p_1</tex> и <tex>p_2</tex>. После этого выберем точку <tex>p_4</tex>, которая не лежит на плоскости, образованной точками <tex>p_1, p_2</tex> и <tex>p_3</tex>. Если этого сделать не получилось, то запустим алгоритм для поиска выпуклой оболочки на плоскости. | Выберем любые две точки <tex>p_1</tex> и <tex>p_2</tex>. Далее из оставшихся выберем точку <tex>p_3</tex>, которая не лежит на прямой, образованной точками <tex>p_1</tex> и <tex>p_2</tex>. После этого выберем точку <tex>p_4</tex>, которая не лежит на плоскости, образованной точками <tex>p_1, p_2</tex> и <tex>p_3</tex>. Если этого сделать не получилось, то запустим алгоритм для поиска выпуклой оболочки на плоскости. | ||
− | Так мы получили тетраэдр <tex>p_1 p_2 p_3 p_4</tex>, который является выпуклой оболочкой этих четырёх точек. Сделаем random shuffle оставшихся точек <tex>p_5, ..., p_n</tex> и будем добавлять их по одной в выпуклую оболочку. Если <tex>p_i</tex> внутри или на границах выпуклой оболочки, то выпуклая оболочка не меняется на этом шаге. Иначе из имеющейся выпуклой оболочки надо удалить все видимые из данной точки грани и добавить новые — из точки до каждого ребра, образующего horizon (см. картинки). После этого нужно смержить соседние грани, которые получились копланарными. | + | Так мы получили тетраэдр <tex>p_1 p_2 p_3 p_4</tex>, который является выпуклой оболочкой этих четырёх точек. Сделаем random shuffle оставшихся точек <tex>p_5, ..., p_n</tex> и будем добавлять их по одной в выпуклую оболочку. Если <tex>p_i</tex> внутри или на границах выпуклой оболочки, то выпуклая оболочка не меняется на этом шаге. Иначе из имеющейся выпуклой оболочки надо удалить все видимые из данной точки грани и добавить новые — из точки до каждого ребра, образующего horizon (см. картинки; на них белые грани видны из точки <tex>p_r</tex>). После этого нужно смержить соседние грани, которые получились копланарными. |
[[Файл:3dconvexhullhorizon.png]] [[Файл:3dconvexhulladd.png]] | [[Файл:3dconvexhullhorizon.png]] [[Файл:3dconvexhulladd.png]] | ||
+ | |||
+ | ==Детали реализации== | ||
+ | Будем хранить выпуклую оболочку в виде DCEL. | ||
+ | |||
+ | Для выяснения, какие грани видны из точки, будем хранить двудольный граф <tex>G</tex>, называемый conflict graph, в одной доле которого будут точки, которые ещё не добавлены в выпуклую оболочку, а в другой — имеющиеся на данный момент грани выпуклой оболочки. Ребро между точкой <tex>p</tex> и гранью <tex>f</tex> в этом графе означает, что из <tex>p</tex> видна <tex>f</tex>, то есть они находятся в конфликте (in conflict): они не могут сосуществовать в выпуклой оболочке. | ||
+ | |||
+ | Инициализация графа для тетраэдра тривиальна: для каждой точки определяем, какие грани видны из неё. Далее на каждом шаге после добавления точки <tex>p_r</tex> удалим из графа соответствующие удаляемым из выпуклой оболочки граням вершины и инцидентные им рёбра: просто удаляем все достижимые из <tex>p_r</tex> вершины. Также удалим вершину, соответствующую <tex>p_r</tex>. Далее добавляем новые грани выпуклой оболочки. Необходимо найти их конфликты. Сами грани представляют из себя треугольники, если, конечно, они не были смержены с уже имеющимися гранями. Во втором случае новая грань находится в конфликте с теми же точками, что и старая грань, т.к. смерженные грани копланарны. | ||
+ | |||
+ | Перейдём к первому случаю. Пусть мы добавили точку <tex>p_r</tex> и рассматриваем грань <tex>f</tex>. <tex>e</tex> — ребро, принадлежащее horizon, <tex>f_1, f_2</tex> — грани, пересечение которых образовывало <tex>e</tex> в старой оболочке. |
Версия 11:55, 17 января 2014
Конспект написан не до конца, но основные вещи уже есть. |
Рассмотрим трёхмерный случай.
-мерный сводится к трёхмерному.Суть алгоритма
Выберем любые две точки
и . Далее из оставшихся выберем точку , которая не лежит на прямой, образованной точками и . После этого выберем точку , которая не лежит на плоскости, образованной точками и . Если этого сделать не получилось, то запустим алгоритм для поиска выпуклой оболочки на плоскости.Так мы получили тетраэдр
, который является выпуклой оболочкой этих четырёх точек. Сделаем random shuffle оставшихся точек и будем добавлять их по одной в выпуклую оболочку. Если внутри или на границах выпуклой оболочки, то выпуклая оболочка не меняется на этом шаге. Иначе из имеющейся выпуклой оболочки надо удалить все видимые из данной точки грани и добавить новые — из точки до каждого ребра, образующего horizon (см. картинки; на них белые грани видны из точки ). После этого нужно смержить соседние грани, которые получились копланарными.Детали реализации
Будем хранить выпуклую оболочку в виде DCEL.
Для выяснения, какие грани видны из точки, будем хранить двудольный граф
, называемый conflict graph, в одной доле которого будут точки, которые ещё не добавлены в выпуклую оболочку, а в другой — имеющиеся на данный момент грани выпуклой оболочки. Ребро между точкой и гранью в этом графе означает, что из видна , то есть они находятся в конфликте (in conflict): они не могут сосуществовать в выпуклой оболочке.Инициализация графа для тетраэдра тривиальна: для каждой точки определяем, какие грани видны из неё. Далее на каждом шаге после добавления точки
удалим из графа соответствующие удаляемым из выпуклой оболочки граням вершины и инцидентные им рёбра: просто удаляем все достижимые из вершины. Также удалим вершину, соответствующую . Далее добавляем новые грани выпуклой оболочки. Необходимо найти их конфликты. Сами грани представляют из себя треугольники, если, конечно, они не были смержены с уже имеющимися гранями. Во втором случае новая грань находится в конфликте с теми же точками, что и старая грань, т.к. смерженные грани копланарны.Перейдём к первому случаю. Пусть мы добавили точку
и рассматриваем грань . — ребро, принадлежащее horizon, — грани, пересечение которых образовывало в старой оболочке.