Pull to refresh

Comments 32

А где используется этот алгоритм?
https://en.wikipedia.org/wiki/Voronoi_diagram#Applications
Вот довольно подробный список.


Я использую для быстрой генерации карт в игрушках. Картинка построена на 28 городах Италии, координаты гео-позиций взяты из открытого источника.
Ранее, в опубликованных здесь другими авторами статьях ((1), (2), (3)), уже было приведено описание алгоритма Форчуна и некоторых структур данных, которые используются для его реализации

Вы, к слову, указываете третьей ссылкой на одну из моих статей, но она не посвящена алгоритму Форчуна или его реализации. В статье рассказываю о совершенно ином алгоритме, но с той же асимптотикой — O(n*logN)

Сложности нужных операций для этих контейнеров(std::map, std::set) те же самые, что и для std::priority_queue, но они позволяют удалить не только наибольший/наименьший элемент, но и любой другой (по итератору — за O(1) времени)

А разве удаление и вставка именно в эти контейнеры осуществляется не за O(logN), это ведь самобалансирующиеся деревья?
Говоря о погрешностях вычислений, порекомендую почитать вот эту статью на Хабрахабре:
https://habrahabr.ru/post/266023/
Я, правда, данный метод встречал уже где-то — но ссылку так просто не найду.
Говоря о статье в целом, было бы интересно узнать о том, на сколько хорошо параллелится данный алгоритм(вот 'разделяй и властвуй' о котором писал я, делает это на все 100% отлично). Ну и так далее, если коротко, то было бы интереснее читать о том, о чем еще не писали: о том, что имеет некий сверх интерес.
В целом, статья хорошая, да и труд был большой вложен, за что вам и спасибо :)

Удалил ссылку.


Так и написал, что "те же самые" сложности, то есть везде логарифмические. Однако позволяют удалять элементы и из середины. Причём удаление по итератору — за константное время.


Не вижу вообще точки, где его можно распараллелить. Ни единой. Если конечно не иметь в арсенале операцию сшивки из алгоритма разделяй и властвуй.


И вам спасибо за доброе слово.

Реализую алгоритм "разделяй и властвуй" — сравню по скорости. Пока нет референтной имплементации на руках.

Сначала прочитал «алгоритм Форчана», много думал.
Проблемы с точностью вычислений решаются так: https://habrahabr.ru/post/138168/

Вообще, я удивился, увидев у вас реализацию Форчуна: вы же писали выпуклую оболочку, а диаграмма Вороного линейно сводима к выпуклой оболочке через триангуляцию Делоне. Кажется, было бы проще использовать именно выпуклую оболочку :)

Как раз только что прочитал вашу статью. Я не уверен, что для плоского случая быстрее будет делать преобразования стартуя с выпуклой оболочки (проекция с D3 параболоида, потом пересекать серединные перпендикуляры и т.п.).

Будет-будет ;) Проекция с параболоида — это звучит слишком торжественно для простого отбрасывания координаты z. Серединные перпендикуляры можно не пересекать — вершины ДВ будут центрами описанных окружностей треугольников Делоне (они, конечно, являются пересечениями соответствующих серединных перпендикуляров, я лишь обращаю внимание на то, что двойственность там действительно халявная). Ну и самый большой бонус — такая диаграмма будет работать в пространстве любой размерности.

То, что будет работать в пространстве любой размерности, звучит привлекательно.

Да, все библиотечные реализации статической ДВ, которые я видел, работают именно через qhull
Вообще, конечно, не хочу спойлеров, но я через две недели буду читать лекцию в cs-клубе как раз на эту тему: http://compsciclub.ru/courses/csseminar/2016-autumn/
Я готовлю для этой лекции python-notebook, он, конечно, сырой пока, но основные идеи уловить, думаю, можно: https://github.com/mcquay239/cg-lectures/blob/master/convex_hull.ipynb

С интересом ознакомлюсь.

Подскажите, как будет корень квадратный влиять на эпсилон?

Короткий ответ — от корней можно и нужно избавиться тождественными преобразованиями (в вашем случае это сделать довольно просто). Если чуть длиннее, то первые два фильтра, описанные в статье (floating-point и interval arithmetic), спокойно переживут корень. Однако уже из рациональных чисел корень не извлечь. Есть библиотека LEDA для работы с алгебраическими числами, она используется, например, в straight skeleton (для определения радиуса вписанной окружности, в отличие от описанной, невозможно избавиться от корней). Её, теоретически, можно использовать вместо gmp. Но, повторюсь, для вашей задачи достаточно gmp.

Я настоял на эпсилон именно потому, что не имею возможности сделать такую цепочку из фильтров. Именно корректность существующего подхода хотел бы "улучшить".

Действительно не имеете? :) Есть вариант, предложенный Шевчуком (J. R. Shewchuk, статья). Если эта статья вам покажется привлекательной для реализации, то помните о том, что сопроцессор иногда считает в 10-байтной арифметике и это сделает алгоритм некорректным. Здесь я его описываю и комментирую, возможно, так будет проще: запись лекции.

Можно все промежуточные результаты сохранять в volatile double, кстати.

Кстати, это, возможно, портабельный вариант. Нужно почитать стандарт насчет оптимизаций, но на первый взгляд это должно заработать. Спасибо!

В CGAL видел классы алгебраических чисел (на сколько я понимаю, это сочетание символьных вычислений и интервальных). Так вот там были классы с корнями и не более того. Если мне нужны логарифмы, экспоненты и вообще трансцендентные числа, то не помогут мне алгебраические таких классов? Хотя вряд ли в геометрических приложениях такое встречается.

В boost есть алгоритм построения диаграмм Вороного не только для точек, но и для отрезков.

Есть обобщения понятия "диаграмма Вороного". Необходимо лишь определение расстояния до точки. Здесь я рассматривал самое классическое определение, которое оперирует понятиями: плоскость, точки, Евклидова метрика.

А как строится диаграмма для более сложной поверхности? В предыдущем посте на эту тему были примеры, когда она строится для поверхности 3х-мерного тела. Возникла необходимость строить для поверхности тора. Пока не придумал ничего умнее чем строить на плоскости с перехлёстом одинаковых тайлов, а потом выкидывать лишние точки перестраивая связи. Но это как-то коряво. :(

Если вопрос ко мне, то я не интересовался подобными вопросами и не могу проконсультировать.

Ко всем. Вдруг кто-нибудь хоть краем глаза видел…
Sign up to leave a comment.

Articles