Квикхалл
Quickhull — это метод вычисления выпуклой оболочки конечного набора точек в n -мерном пространстве. Он использует подход «разделяй и властвуй» , аналогичный подходу быстрой сортировки , от которого и произошло его название. Его временная сложность в худшем случае для 2-мерного и 3-мерного пространства равна , но когда точность ввода ограничена бит, предполагается, что его временная сложность в худшем случае составит , где количество входных точек и – количество обработанных точек (до ). [1]
N-мерный Quickhull был изобретен в 1996 году К. Брэдфордом Барбером, Дэвидом П. Добкиным и Ханну Хухданпаа. [1] Это было расширение планарного алгоритма Quickhull Джонатана Скотта Гринфилда 1990 года, хотя авторы 1996 года не знали о его методах. [2] Вместо этого Барбер и др. описывают его как детерминированный вариант алгоритма Кларксона и Шора 1989 года. [1]
Алгоритм [ править ]
Двумерный алгоритм можно разбить на следующие этапы: [2]
- Найдите точки с минимальными и максимальными координатами x, поскольку они всегда будут частью выпуклой оболочки. Если существует много точек с одинаковым минимумом/максимумом x, используйте точки с минимумом/максимумом y соответственно.
- Используйте линию, образованную двумя точками, чтобы разделить набор на два подмножества точек, которые будут обрабатываться рекурсивно. Далее мы опишем, как определить часть корпуса над линией; часть корпуса ниже линии можно определить аналогично.
- Определите точку над линией с максимальным расстоянием от линии. Эта точка образует треугольник с двумя точками на линии.
- Точки, лежащие внутри этого треугольника, не могут быть частью выпуклой оболочки и поэтому их можно игнорировать на следующих шагах.
- Рекурсивно повторите два предыдущих шага на двух линиях, образованных двумя новыми сторонами треугольника.
- Продолжайте до тех пор, пока не останется точек, рекурсия не завершится и выбранные точки не составят выпуклую оболочку.
Проблема более сложна в случае более высокой размерности, поскольку корпус состоит из многих граней; структура данных должна учитывать это и записывать линию/плоскость/гиперплоскость (гребень), общую для соседних граней. Для размеров d : [1]
- Выберите d + 1 точку из набора, не имеющую общей плоскости или гиперплоскости. Это формирует начальную оболочку с гранями Fs[] .
- Для каждого F в Fs[] найдите все неназначенные точки, находящиеся «над» ним; т. е. указывая от центра корпуса, и присваивать их «внешнему» набору FO, связанному с F . Алгоритм сохраняет инвариант, согласно которому каждая точка, которая не была добавлена в оболочку, но потенциально могла бы быть ее вершиной, присваивается ровно одному внешнему множеству.
- Для каждого F с непустым FO :
- Найдите точку p в FO, находящуюся на максимальном расстоянии от F, и добавьте ее к оболочке. Обратите внимание, что p не обязательно будет вершиной конечной оболочки, поскольку позже ее можно будет удалить.
- Создайте видимый набор V и инициализируйте его F. значением Расширьте V во всех направлениях для соседних фасетов Fv не перестанут быть видимыми фасеты до тех пор, пока из p . То, что Fv видно из p, означает, что p выше Fv.
- Тогда граница V образует набор гребней горизонта H .
- Пусть Fnew[] будет набором фасетов, созданных из p и всех гребней в H .
- Отмените назначение всех точек во внешних наборах фасетов в V. Для каждого нового фасета в Fnew[] выполните шаг (2), рассматривая только эти недавно неназначенные точки, чтобы инициализировать его внешний набор. Обратите внимание, что каждая точка, которая остается неназначенной в конце этого процесса, находится внутри текущей оболочки.
- Удалите теперь внутренние фасеты в V из Fs[] . Добавьте новые фасеты из Fnew[] в Fs[] и продолжите итерацию.
Псевдокод для 2D набора точек [ править ]
Input = a set S of n points Assume that there are at least 2 points in the input set S of points function QuickHull(S) is // Find convex hull from the set S of n points Convex Hull := {} Find left and right most points, say A & B, and add A & B to convex hull Segment AB divides the remaining (n − 2) points into 2 groups S1 and S2 where S1 are points in S that are on the right side of the oriented line from A to B, and S2 are points in S that are on the right side of the oriented line from B to A FindHull(S1, A, B) FindHull(S2, B, A) Output := Convex Hull end function function FindHull(Sk, P, Q) is // Find points on convex hull from the set Sk of points // that are on the right side of the oriented line from P to Q if Sk has no point then return From the given set of points in Sk, find farthest point, say C, from segment PQ Add point C to convex hull at the location between P and Q Three points P, Q, and C partition the remaining points of Sk into 3 subsets: S0, S1, and S2 where S0 are points inside triangle PCQ, S1 are points on the right side of the oriented line from P to C, and S2 are points on the right side of the oriented line from C to Q. FindHull(S1, P, C) FindHull(S2, C, Q) end function
Псевдокод, специализированный для 3D-случая, можно получить у Джордана Смита. Он включает в себя аналогичную стратегию «максимальной точки» для выбора стартового корпуса. Если эти максимальные точки вырождены, то и все облако точек тоже. [3]
См. также [ править ]
Ссылки [ править ]
- ^ Jump up to: а б с д Барбер, К. Брэдфорд; Добкин, Дэвид П.; Хухданпаа, Ханну (1 декабря 1996 г.). «Алгоритм Quickhull для выпуклых оболочек» (PDF) . Транзакции ACM в математическом программном обеспечении . 22 (4): 469–483. дои : 10.1145/235815.235821 .
- ^ Jump up to: а б Гринфилд, Джонатан С. (1 апреля 1990 г.). «Доказательство алгоритма QuickHull» . Электротехника и информатика - Технические отчеты .
- ^ Смит, Джордан. «КвикХалл 3D» . Algolist.ru . Проверено 22 октября 2019 г.
- Дэйв Маунт. «Лекция 3: Дополнительные алгоритмы выпуклой оболочки» . Архивировано из оригинала 11 апреля 2001 года.
Внешние ссылки [ править ]
- Реализация QuickHull (GDC 2014) — презентация алгоритма с подробностями реализации в 3D.