Недавно я столкнулся с проблемой, когда у меня было четыре круга (средние точки и радиус), и мне нужно было вычислить площадь объединения этих кругов.
Пример изображения:
Для двух кругов это довольно просто,
Я могу просто вычислить долю площади каждого круга, которая не находится внутри треугольников, а затем вычислить площадь треугольников.
Но есть ли хитрый алгоритм, который я могу использовать, когда кругов больше двух?
Ответы:
Найдите все пересечения кругов на внешнем периметре (например, B, D, F, H на следующей диаграмме). Соедините их вместе с центрами соответствующих кругов, чтобы образовать многоугольник. Площадь объединения кругов - это площадь многоугольника + площадь срезов круга, определяемая последовательными точками пересечения и центром круга между ними. Вам также необходимо учитывать любые дыры.
источник
Я уверен, что есть умный алгоритм, но вот глупый, чтобы избавить от необходимости искать его;
Конечно тупо, но:
источник
Ответ Муравья Аасмы дал основную идею, но я хотел сделать ее более конкретной. Взгляните на пять кругов ниже и на то, как они разложены.
Определить эти 3 типа точек несложно. Теперь создайте структуру данных графа, узлами которой являются синие точки и красные точки с белой внутренней частью. Для каждого круга поместите край между серединой круга (синяя точка) и каждым из его пересечений (красные точки с белой внутренней стороной) на его границе.
Это разбивает объединение кругов на набор многоугольников (заштриховано синим) и круглых частей (заштриховано зеленым), которые попарно не пересекаются и покрывают исходное объединение (то есть разбиение). Поскольку здесь каждый кусок представляет собой нечто, площадь которого легко вычислить, вы можете вычислить площадь объединения, суммируя площади частей.
источник
Для решения, отличного от предыдущего, вы можете произвести оценку с произвольной точностью с помощью квадродерева.
Это также работает для любого объединения фигур, если вы можете сказать, находится ли квадрат внутри или снаружи или пересекает форму.
Каждая ячейка имеет одно из состояний: пустая, полная, частичная.
Алгоритм заключается в «рисовании» кругов в квадродереве, начиная с низкого разрешения (например, 4 ячейки помечены как пустые). Каждая ячейка либо:
Когда это будет сделано, вы можете вычислить оценку площади: полные ячейки дают нижнюю границу, пустые ячейки дают верхнюю границу, частичные ячейки дают максимальную ошибку площади.
Если ошибка слишком велика для вас, вы уточняете частичные ячейки, пока не получите нужную точность.
Я думаю, что это будет проще реализовать, чем геометрический метод, который может потребовать обработки множества особых случаев.
источник
Мне нравится подход к случаю двух пересекающихся кругов - вот как я бы использовал небольшую вариацию того же подхода для более сложного примера.
Это могло бы дать лучшее понимание обобщения алгоритма для большего числа частично перекрывающихся кругов.
Разница здесь в том, что я начинаю со связывания центров (так что есть вершина между центрами кругов, а не между местами пересечения кругов). Я думаю, это позволяет лучше обобщить.
(на практике, может быть, стоит метод Монте-Карло)
(источник: secretGeek.net )
источник
Если вам нужен дискретный (а не непрерывный) ответ, вы можете сделать что-то похожее на алгоритм рисования пикселей.
Нарисуйте круги на сетке, а затем раскрасьте каждую ячейку сетки, если она в основном находится внутри круга (т. Е. Не менее 50% ее площади находится внутри одного из кругов). Сделайте это для всей сетки (где сетка охватывает всю область, покрытую кругами), затем подсчитайте количество цветных ячеек в сетке.
источник
Хм, очень интересная проблема. Мой подход, вероятно, будет примерно таким:
(это верно для любой формы, будь то круг или нет)
Где
A ∪ B
означает A объединение B иA ∩ B
означает, что A пересекает B (вы можете решить это с первого шага.(Это то же самое, что и выше, где
A
было заменено наA∪B
)Где
area(A∪B)
мы только что поработали, иarea((A∪B)∩C)
можно найти:Где снова вы можете найти область (A∩B∩C) сверху.
Сложность - последний шаг - чем больше добавляется кругов, тем сложнее становится. Я считаю, что есть расширение для определения площади пересечения с конечным объединением, или, в качестве альтернативы, вы можете рекурсивно вычислить его.
Кроме того, что касается использования Монте-Карло для аппроксимации площади итеративного сечения, я считаю, что можно уменьшить пересечение произвольного количества кругов до пересечения 4 из этих кругов, которые можно точно вычислить (не знаю, как это сделать. тем не мение).
Вероятно, есть лучший способ сделать это, кстати - сложность значительно возрастает (возможно, экспоненциально, но я не уверен) для каждого добавленного круга.
источник
Я работал над проблемой моделирования перекрывающихся звездных полей, пытаясь оценить истинное количество звезд по фактическим областям диска в плотных полях, где более крупные яркие звезды могут маскировать более слабые. Я тоже надеялся, что смогу сделать это с помощью строгого формального анализа, но не смог найти алгоритм для этой задачи. Я решил это, создав звездные поля на синем фоне в виде зеленых дисков, диаметр которых определялся вероятностным алгоритмом. Простая процедура может объединить их в пары, чтобы увидеть, есть ли перекрытие (выделение звездной пары желтым цветом); затем подсчет пикселей цветов создает наблюдаемую область для сравнения с теоретической областью. Затем это генерирует кривую вероятности для истинных подсчетов. Может быть, грубая сила, но вроде работает нормально. (источник: 2from.com )
источник
Вот алгоритм, который легко реализовать на практике и который можно настроить для получения сколь угодно малой ошибки:
Шаги 2 и 3 могут быть выполнены с использованием стандартных, простых для поиска алгоритмов вычислительной геометрии.
Очевидно, что чем больше сторон вы используете для каждого аппроксимирующего многоугольника, тем точнее будет ваш ответ. Вы можете приблизиться, используя вписанные и описанные многоугольники, чтобы получить границы точного ответа.
источник
Есть эффективные решения этой проблемы с использованием так называемых диаграмм мощности. Однако это действительно сложная математика, и я не хотел бы заниматься ею сразу. Для "легкого" решения поищите алгоритмы линейной развертки. Основной принцип здесь состоит в том, что вы делите фигуру на полосы, где вычислить площадь каждой полосы относительно легко.
Итак, на фигуре, содержащей все круги, на которых ничего не стерто, нарисуйте горизонтальную линию в каждой позиции, которая является либо вершиной круга, либо основанием круга, либо пересечением двух кругов. Обратите внимание, что внутри этих полос все области, которые необходимо вычислить, выглядят одинаково: «трапеция» с двумя сторонами, замененными круговыми сегментами. Поэтому, если вы можете придумать, как рассчитать такую форму, вы просто сделаете это для всех отдельных фигур и сложите их вместе. Сложность этого наивного подхода составляет O (N ^ 3), где N - количество кружков на рисунке. С помощью некоторой умной структуры данных вы могли бы улучшить этот метод строчной развертки до O (N ^ 2 * log (N)), но, если вам это действительно не нужно, это, вероятно, не стоит проблем.
источник
Я нашел эту ссылку, которая может быть полезна. Хотя, похоже, нет однозначного ответа. Google отвечает . Еще одна ссылка на три круга - это теорема Харуки . Там же есть бумага.
источник
В зависимости от того, какую проблему вы пытаетесь решить, может быть достаточно получить верхнюю и нижнюю границу. Верхняя граница проста, просто сумма всех кругов. Для нижней границы вы можете выбрать один радиус, чтобы ни один из кругов не перекрывался. Чтобы лучше найти самый большой радиус (вплоть до фактического) для каждого круга, чтобы он не перекрывался. Также должно быть довольно тривиально удалить любые полностью перекрывающиеся круги (все такие круги удовлетворяют | P_a - P_b | <= r_a), где P_a - центр круга A, P_b - центр круга B, а r_a - радиус A ), что улучшает как верхнюю, так и нижнюю границу. Вы также можете получить лучшую верхнюю границу, если будете использовать формулу пар для произвольных пар, а не просто сумму всех кругов. Может быть хороший способ выбрать "лучшее"
Учитывая верхнюю и нижнюю границы, вы могли бы лучше настроить подход Монте-Карло, но в голову не приходит ничего конкретного. Другой вариант (опять же в зависимости от вашего приложения) - растрировать круги и подсчитать пиксели. По сути, это подход Монте-Карло с фиксированным распределением.
источник
Это можно решить с помощью теоремы Грина со сложностью n ^ 2log (n). Если вы не знакомы с теоремой Грина и хотите узнать больше, вот видео и заметки из Академии Хана. Но для нашей проблемы, думаю, моего описания будет достаточно.
Общее уравнение теоремы Грина.
Если я поставлю L и M так , что
Состояние
тогда RHS - это просто область области R и может быть получена путем решения замкнутого интеграла или LHS, и это именно то, что мы собираемся сделать.
Все объединения можно разбить на такие непересекающиеся множества окружностей, которые пересекаются
Таким образом, интегрирование по пути против часовой стрелки дает нам площадь области, а интегрирование по часовой стрелке дает нам отрицательную величину площади . Так
AreaOfUnion = (интегрирование по красным дугам против часовой стрелки + интегрирование по синим дугам по часовой стрелке)
Но крутой трюк состоит в том, если для каждого круга, если мы объединяем дуги, которые не находятся внутри другого круга, мы получаем требуемую площадь, то есть мы получаем интегрирование против часовой стрелки по всем красным дугам и интегрирование по всем синим дугам по часовой стрелке. РАБОТА ВЫПОЛНЕНА!!!
Вот ссылка GitHub на мой код C ++
источник
Подход с рисованием пикселей (предложенный @Loadmaster) превосходит математическое решение во многих отношениях:
Единственным недостатком пиксельной раскраски является конечная точность решения. Но это можно настроить путем простого рендеринга на холсты большего или меньшего размера в зависимости от ситуации. Также обратите внимание, что сглаживание в коде 2D-рендеринга (часто включенное по умолчанию) дает точность лучше, чем на уровне пикселей. Так, например, рендеринг фигуры 100x100 на холст тех же размеров, я думаю, должен дать точность порядка 1 / (100 x 100 x 255) = 0,000039% ... что, вероятно, «достаточно хорошо» для всех, кроме самых сложных проблем.
источник