Как найти выпуклую оболочку в трехмерном пространстве

Дан набор очков S (x, y, z). Как найти convex hull этих точек?

Я попытался понять алгоритм из здесь, но не смог.

Он говорит:

Сначала спроецируйте все точки на плоскость xy и найдите край, который определенно находится на корпусе, выбрав точку с наивысшей координатой y, а затем выполнив одну итерацию упаковки подарка, чтобы определить другую конечную точку края. Это первая часть незавершенного корпуса. Затем мы итеративно строим корпус. Рассмотрим это первое ребро; Теперь найдите другую точку, чтобы сформировать первую треугольную грань корпуса. Мы делаем это, выбирая точку таким образом, чтобы все остальные точки лежали справа от этого треугольника, если смотреть должным образом (точно так же, как в алгоритме упаковки подарков, в котором мы выбрали такое ребро, что все остальные точки лежали справа от него). этот край). Теперь в корпусе три ребра; чтобы продолжить, мы выбираем одну из них произвольно и снова просматриваем все точки, чтобы найти другую точку, чтобы построить новый треугольник с этим ребром, и повторяем это до тех пор, пока не останется никаких ребер. (Когда мы создаем новую треугольную грань, мы добавляем два ребра в пул; однако мы должны сначала проверить, были ли они уже добавлены к корпусу, и в этом случае мы их игнорируем.) Есть O (n) граней, и каждая итерация занимает O (n) времени, так как мы должны сканировать все оставшиеся точки, давая O (n2).

Может ли кто-нибудь объяснить это более четко или предложить более простой альтернативный подход.


person Ninja420    schedule 24.08.2013    source источник


Ответы (3)


Реализовать трехмерную выпуклую оболочку непросто, но было реализовано множество алгоритмов, и код широко доступен. Лучшее из качественных и временных затрат на использование - это CGAL. В нижней части обоих показателей находится мой собственный код C:
DCG Cover
Между ними есть код по всему Интернету, включая эта реализация QuickHull.

person Joseph O'Rourke    schedule 25.08.2013
comment
Эта реализация сайта QuickHull, похоже, исчезла. Архив здесь: https://web.archive.org/web/20180106161310/http://thomasdiewald.com/blog/?p=1888 - person Alec Jacobson; 05.12.2020

Я бы посоветовал сначала попробовать более простой подход, например, быстрый корпус. (Кстати, порядок упаковки подарков - O (nh), а не O (n2), где h - количество очков на корпусе, а порядок быстрой упаковки - O (n log n)).

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

  1. Найдите точки с минимальными и максимальными координатами x, которые обязательно должны быть частью выпуклости.

  2. Используйте линию, образованную двумя точками, чтобы разделить набор на два подмножества точек, которые будут обрабатываться рекурсивно. введите описание изображения здесь

  3. Определите точку на одной стороне линии, на максимальном расстоянии от нее. Две точки, найденные ранее, вместе с этой образуют треугольник.

  4. Точки, лежащие внутри этого треугольника, не могут быть частью выпуклой оболочки и поэтому могут быть проигнорированы на следующих шагах.

  5. Повторите предыдущие два шага на двух линиях, образованных треугольником (не исходной линией). введите описание изображения здесь

  6. Продолжайте делать это до тех пор, пока не кончатся точки, рекурсия не закончится и выбранные точки не образуют выпуклую оболочку. введите описание изображения здесь

См. это имплементацию и объяснение трехмерной выпуклой оболочки с использованием алгоритма быстрой оболочки.

Алгоритм упаковки подарков:

Алгоритм сопоставления Джарвиса похож на обвязывание точек отрезком веревки. Он начинается с вычисления самой левой точки l, поскольку мы знаем, что самая левая точка должна быть вершиной выпуклой оболочки. Этот процесс займет линейное время. Затем алгоритм выполняет серию поворотных шагов, чтобы найти каждую последующую вершину выпуклой оболочки до следующей. вершина снова является исходной крайней левой точкой.

Алгоритм находит следующую вершину выпуклой оболочки следующим образом: вершина, следующая сразу за точкой p, - это точка, которая кажется наиболее удаленной справа от человека, стоящего в p и смотрящего на другие точки. Другими словами, если q - вершина, следующая за p, а r - любая другая входная точка, то тройка p, q, r находится в порядке против часовой стрелки. Мы можем найти каждую последующую вершину за линейное время, выполнив серию O (n) тестов против часовой стрелки.

Поскольку алгоритм тратит O (n) времени на каждую вершину выпуклой оболочки, время работы в наихудшем случае составляет O (n2). Однако, если у выпуклой оболочки очень мало вершин, марш Джарвиса будет чрезвычайно быстрым. Лучше всего записать время выполнения O (nh), где h - количество вершин выпуклой оболочки. В худшем случае h = n, и мы получаем нашу старую временную границу O (n2), но в лучшем случае h = 3, и алгоритму требуется только время O (n). Это так называемый алгоритм, чувствительный к выходу: чем меньше выход, тем быстрее алгоритм.

Следующее изображение должно дать вам больше информации введите описание изображения здесь

person Aditya    schedule 24.08.2013
comment
Кажется, что OP ищет помощь для 3D-корпусов, но ваши (хорошие!) Описания предназначены для 2D-корпусов ... - person Joseph O'Rourke; 25.08.2013
comment
Что ж, если вы понимаете 2d, 3d - очень простое обобщение;) - person Aditya; 26.08.2013
comment
;) Реализовав и то, и другое, я бы оценил их как ... ну, в разных измерениях! :-) - person Joseph O'Rourke; 26.08.2013

Код GPL C ++ для поиска трехмерных выпуклых оболочек доступен по адресу http://www.newtonapples.net/code/NewtonAppleWrapper_11Feb2016.tar.gz и описание алгоритма O (n log (n)) на http://www.newtonapples.net/NewtonAppleWrapper.html

person David    schedule 15.02.2016