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

Учитывая множество точек S (x, y, z). Как найти convex hull этих точек?

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

В нем говорится:

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

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

Ответ 1

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

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

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

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

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

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

  • Повторите предыдущие два шага по двум строкам, образованным треугольник (не исходная строка). enter image description here

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

См. this impementaion и объяснение для 3d выпуклой оболочки с использованием алгоритма быстрой оболочки.

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

Алгоритм соответствия Jarvis похож на обертывание фрагмента строки вокруг точек. Он начинается с вычисления самой левой точки 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). Это так называемый чувствительный к выходу алгоритм, чем меньше результат, тем быстрее алгоритм.

Следующее изображение должно дать вам больше идей enter image description here

Ответ 2

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