Совмещенная область перекрывающихся кругов


107

Недавно я столкнулся с проблемой, когда у меня было четыре круга (средние точки и радиус), и мне нужно было вычислить площадь объединения этих кругов.

Пример изображения:

Для двух кругов это довольно просто,

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

Но есть ли хитрый алгоритм, который я могу использовать, когда кругов больше двух?


15
Это действительно интересная проблема, я помню, как видел ее на уроках геометрии в средней школе, но так и не нашел решения. Если вы не можете найти здесь ответ, попробуйте опубликовать его на mathoverflow.net, и пусть математики попробуют его: P
Charles Ma

25
иногда настоящим программистам нужна настоящая математика
фа.

1
Как насчет того, чтобы выработать ответ на этот вопрос: «У нас есть торговые представители, живущие в этих 4 точках, каждый из которых обслуживает территорию с этими 4 радиусами. Какую часть страны мы покрываем?» Если у вас была изменяющаяся база данных торговых представителей, это становится вопросом программирования!
Крис Робертс

5
Собственно, настоящие программисты любят думать об этом.
MAK

2
@zvolkov: печатные платы описываются языком, который складывает квадраты и круги вниз и, возможно, перетаскивает их. «Рассчитайте площадь меди». (Это может потребоваться для расчета времени травления, определения необходимости добавления рисунков для очистки и других вещей.)
DigitalRoss

Ответы:


97

Найдите все пересечения кругов на внешнем периметре (например, B, D, F, H на следующей диаграмме). Соедините их вместе с центрами соответствующих кругов, чтобы образовать многоугольник. Площадь объединения кругов - это площадь многоугольника + площадь срезов круга, определяемая последовательными точками пересечения и центром круга между ними. Вам также необходимо учитывать любые дыры.

перекрытие круга


17
Что происходит, когда в центре есть дыра?
Джон Гитцен

3
Вам нужно будет вычесть центральный соединенный многоугольник для отверстия из общего количества и добавить срезы круга для этого многоугольника к итогу.
Ants Aasma

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

1
Особые случаи довольно просты. Круги внутри других отбрасываются, так как не имеют пересечений по периметру. Один точечный контакт фактически означает два пересечения с нулевым расстоянием. Разъединенные формы могут быть найдены с помощью алгоритма связанных компонентов на графике, где две окружности соединены, если расстояние между центрами меньше суммы радиусов. Отверстия - это все многоугольники, кроме самого большого по площади. Все пересечения периметра не находятся строго внутри круга.
Ants Aasma

4
да, но границы отверстий тоже (маленькие) дуги. Я все еще думаю, что для хорошей работы требуется много кода.
фа.

32

Я уверен, что есть умный алгоритм, но вот глупый, чтобы избавить от необходимости искать его;

  • обведите круги рамкой;
  • генерировать случайные точки внутри ограничивающей рамки;
  • выяснить, находится ли случайная точка внутри одного из кругов;
  • вычислить площадь простым сложением и делением (ratio_of_points_inside * area_of_bounding_box).

Конечно тупо, но:

  • вы можете получить настолько точный ответ, насколько захотите, просто наберите больше очков;
  • он будет работать для любых форм, для которых вы можете рассчитать различие внутри / снаружи;
  • он прекрасно распараллеливается, так что вы можете использовать все свои ядра.

2
Это будет работать, но такие методы Монте-Карло, как этот, основанные просто на равномерной выборке, обычно не имеют наилучшей скорости сходимости.
ShreevatsaR

2
Извините, но даже несмотря на то, что я ценю ваши усилия и считаю, что ваше решение «практически применимо», я считаю ваш подход очень неправильным. Это проблема, которую можно и нужно решать с помощью математики, а не грубой силы. Тратить энергию и силы на подобные проблемы расточительно и расточительно.
mafu

5
Вы правы, мне стыдно, но у меня кластер на 12000 ядер, я могу позволить себе расточительство. И я не могу понять, как сделать это элегантное математическое решение масштабируемым для такого количества процессоров.
High Performance Mark

8
Нет ничего принципиально неправильного в методе Монте-Карло (или любом рандомизированном) подходе при условии, что он дает требуемую степень точности и делает это в разумные сроки.
MAK

@mafutrct, ты определенно прав. Однако в математике легко сделать небольшие ошибки. Это решение обеспечивает простой способ проверки правильности.
Ричард

18

Ответ Муравья Аасмы дал основную идею, но я хотел сделать ее более конкретной. Взгляните на пять кругов ниже и на то, как они разложены.

пример

  • Синие точки - центры окружностей.
  • Красные точки - это пересечения границ круга.
  • Красные точки с белым внутренним элементом - это пересечения границ окружностей, которых нет ни в каких других кругах .

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

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


Я думаю, что могу довольно легко вычислить набор красных / белых точек, однако моя теория графов не слишком хороша: алгоритмически, как вы можете перейти от списка узлов + ребер к вычисленной области?
user999305

1
Алгоритм можно упростить, используя набор неперекрывающихся треугольников вместо многоугольников. Дуги (зеленые зоны) - это области, содержащиеся только в одном круге. Увеличивайте размер многоугольника по мере добавления кругов. (в конце концов, вы можете забыть, что говорите даже о многоугольниках). Это делает логические свойства, а также упрощает вычисление площадей. Когда пустая красная точка становится сплошной красной точкой, вы просто добавляете больше треугольников в свой набор и настраиваете дугу, которая «съедается» все большим и большим количеством пересекающихся кругов.
Стив

16

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

Это также работает для любого объединения фигур, если вы можете сказать, находится ли квадрат внутри или снаружи или пересекает форму.

Каждая ячейка имеет одно из состояний: пустая, полная, частичная.

Алгоритм заключается в «рисовании» кругов в квадродереве, начиная с низкого разрешения (например, 4 ячейки помечены как пустые). Каждая ячейка либо:

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

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

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

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


3
Я предполагаю , что это будет сходиться быстрее, чем алгоритм внутренней / внешней точки Монте-Карло.
Франк Крюгер

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

грубая сила здесь называется теоремой сжатия
фа.

Такой алгоритм вы используете в интервальной арифметике. en.wikipedia.org/wiki/Interval_arithmetic
rjmunro

13

Мне нравится подход к случаю двух пересекающихся кругов - вот как я бы использовал небольшую вариацию того же подхода для более сложного примера.

Это могло бы дать лучшее понимание обобщения алгоритма для большего числа частично перекрывающихся кругов.

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

(на практике, может быть, стоит метод Монте-Карло)

альтернативный текст
(источник: secretGeek.net )


1
Я думаю, что деление на многоугольники, предложенное вашим изображением, вероятно, будет очень хорошим подходом. Нужно проработать множество деталей, чтобы кодировать это. Как бы он справился с цепочкой из двадцати кругов, каждый из которых перекрывает только последний и следующий в цепочке? Легко разобраться вручную, но каков ваш алгоритм?
PeterAllenWebb

4

Если вам нужен дискретный (а не непрерывный) ответ, вы можете сделать что-то похожее на алгоритм рисования пикселей.

Нарисуйте круги на сетке, а затем раскрасьте каждую ячейку сетки, если она в основном находится внутри круга (т. Е. Не менее 50% ее площади находится внутри одного из кругов). Сделайте это для всей сетки (где сетка охватывает всю область, покрытую кругами), затем подсчитайте количество цветных ячеек в сетке.


3

Хм, очень интересная проблема. Мой подход, вероятно, будет примерно таким:

  • Разработайте способ определения областей пересечения между произвольным количеством кругов, т.е. если у меня есть 3 круга, мне нужно уметь вычислить, каково пересечение между этими кругами. Метод «Монте-Карло» был бы хорошим способом приблизиться к этому ( http://local.wasp.uwa.edu.au/~pbourke/geometry/circlearea/ ).
  • Удалите все круги, которые полностью содержатся в другом большом круге (посмотрите на радиус и модуль расстояния между центрами двух кругов), я не считаю это обязательным.
  • Выберите 2 круга (назовите их A и B) и определите общую площадь, используя эту формулу:

(это верно для любой формы, будь то круг или нет)

area(A∪B) = area(A) + area(B) - area(A∩B)

Где A ∪ Bозначает A объединение B и A ∩ Bозначает, что A пересекает B (вы можете решить это с первого шага.

  • Теперь продолжайте добавлять круги и продолжайте прорабатывать область, добавленную как сумму / вычитание областей кругов и областей пересечений между кругами. Например, для 3 кругов (назовите дополнительный круг C) мы прорабатываем площадь по следующей формуле:

(Это то же самое, что и выше, где Aбыло заменено на A∪B)

area((A∪B)∪C) = area(A∪B) + area(C) - area((A∪B)∩C)

Где area(A∪B)мы только что поработали, и area((A∪B)∩C)можно найти:

area((A∪B)nC) = area((A∩C)∪(B∩C)) = area(A∩C) + area(A∩B) - area((A∩C)∩(B∩C)) = area(A∩C) + area(A∩B) - area(A∩B∩C)

Где снова вы можете найти область (A∩B∩C) сверху.

Сложность - последний шаг - чем больше добавляется кругов, тем сложнее становится. Я считаю, что есть расширение для определения площади пересечения с конечным объединением, или, в качестве альтернативы, вы можете рекурсивно вычислить его.

Кроме того, что касается использования Монте-Карло для аппроксимации площади итеративного сечения, я считаю, что можно уменьшить пересечение произвольного количества кругов до пересечения 4 из этих кругов, которые можно точно вычислить (не знаю, как это сделать. тем не мение).

Вероятно, есть лучший способ сделать это, кстати - сложность значительно возрастает (возможно, экспоненциально, но я не уверен) для каждого добавленного круга.


Что с форматированием? Также извините за использование n и u для пересечения и объединения, вероятно, есть способ получше ...
Джастин

1
добавлены знаки объединения Юникода (∪) и пересечения (∩). надеюсь, они работают.
Spoike

3

Я работал над проблемой моделирования перекрывающихся звездных полей, пытаясь оценить истинное количество звезд по фактическим областям диска в плотных полях, где более крупные яркие звезды могут маскировать более слабые. Я тоже надеялся, что смогу сделать это с помощью строгого формального анализа, но не смог найти алгоритм для этой задачи. Я решил это, создав звездные поля на синем фоне в виде зеленых дисков, диаметр которых определялся вероятностным алгоритмом. Простая процедура может объединить их в пары, чтобы увидеть, есть ли перекрытие (выделение звездной пары желтым цветом); затем подсчет пикселей цветов создает наблюдаемую область для сравнения с теоретической областью. Затем это генерирует кривую вероятности для истинных подсчетов. Может быть, грубая сила, но вроде работает нормально. (источник: 2from.com )


2

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

  1. Аппроксимируйте каждый круг правильным многоугольником с центром в той же точке.
  2. Вычислить многоугольник, который является объединением приближенных окружностей
  3. Вычислить площадь объединенного многоугольника

Шаги 2 и 3 могут быть выполнены с использованием стандартных, простых для поиска алгоритмов вычислительной геометрии.

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


2

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

Итак, на фигуре, содержащей все круги, на которых ничего не стерто, нарисуйте горизонтальную линию в каждой позиции, которая является либо вершиной круга, либо основанием круга, либо пересечением двух кругов. Обратите внимание, что внутри этих полос все области, которые необходимо вычислить, выглядят одинаково: «трапеция» с двумя сторонами, замененными круговыми сегментами. Поэтому, если вы можете придумать, как рассчитать такую ​​форму, вы просто сделаете это для всех отдельных фигур и сложите их вместе. Сложность этого наивного подхода составляет O (N ^ 3), где N - количество кружков на рисунке. С помощью некоторой умной структуры данных вы могли бы улучшить этот метод строчной развертки до O (N ^ 2 * log (N)), но, если вам это действительно не нужно, это, вероятно, не стоит проблем.



1

В зависимости от того, какую проблему вы пытаетесь решить, может быть достаточно получить верхнюю и нижнюю границу. Верхняя граница проста, просто сумма всех кругов. Для нижней границы вы можете выбрать один радиус, чтобы ни один из кругов не перекрывался. Чтобы лучше найти самый большой радиус (вплоть до фактического) для каждого круга, чтобы он не перекрывался. Также должно быть довольно тривиально удалить любые полностью перекрывающиеся круги (все такие круги удовлетворяют | P_a - P_b | <= r_a), где P_a - центр круга A, P_b - центр круга B, а r_a - радиус A ), что улучшает как верхнюю, так и нижнюю границу. Вы также можете получить лучшую верхнюю границу, если будете использовать формулу пар для произвольных пар, а не просто сумму всех кругов. Может быть хороший способ выбрать "лучшее"

Учитывая верхнюю и нижнюю границы, вы могли бы лучше настроить подход Монте-Карло, но в голову не приходит ничего конкретного. Другой вариант (опять же в зависимости от вашего приложения) - растрировать круги и подсчитать пиксели. По сути, это подход Монте-Карло с фиксированным распределением.


0

Это можно решить с помощью теоремы Грина со сложностью n ^ 2log (n). Если вы не знакомы с теоремой Грина и хотите узнать больше, вот видео и заметки из Академии Хана. Но для нашей проблемы, думаю, моего описания будет достаточно.

Извините за ссылки на фотографии, так как я не могу публиковать изображения (недостаточно очков репутации)

Общее уравнение теоремы Грина.

Если я поставлю L и M так , что

Состояние

тогда RHS - это просто область области R и может быть получена путем решения замкнутого интеграла или LHS, и это именно то, что мы собираемся сделать.

Все объединения можно разбить на такие непересекающиеся множества окружностей, которые пересекаются

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

AreaOfUnion = (интегрирование по красным дугам против часовой стрелки + интегрирование по синим дугам по часовой стрелке)

Но крутой трюк состоит в том, если для каждого круга, если мы объединяем дуги, которые не находятся внутри другого круга, мы получаем требуемую площадь, то есть мы получаем интегрирование против часовой стрелки по всем красным дугам и интегрирование по всем синим дугам по часовой стрелке. РАБОТА ВЫПОЛНЕНА!!!

Предусмотрены даже случаи, когда круг не пересекается ни с одним другим.

Вот ссылка GitHub на мой код C ++


-1

Подход с рисованием пикселей (предложенный @Loadmaster) превосходит математическое решение во многих отношениях:

  1. Реализация намного проще. Вышеупомянутая проблема может быть решена менее чем за 100 строк кода, поскольку это решение JSFiddle демонстрирует (в основном потому, что оно концептуально намного проще и не имеет крайних случаев или исключений, с нужно иметь дело).
  2. Он легко адаптируется к более общим задачам. Он работает с любой формой, независимо от морфологии, при условии, что ее можно визуализировать с помощью библиотек 2D-чертежей (то есть «всех из них!») - кругов, эллипсов, сплайнов, многоугольников и т. Д. Черт возьми, даже растровые изображения.
  3. Сложность решения по рисованию пикселей составляет ~ O [n], по сравнению с ~ O [n * n] для математического решения. Это означает, что он будет работать лучше по мере увеличения количества форм.
  4. Говоря о производительности, вы часто получаете аппаратное ускорение бесплатно, поскольку большинство современных 2D-библиотек (как я полагаю, вроде холста HTML5) перекладывают рендеринг на графические ускорители.

Единственным недостатком пиксельной раскраски является конечная точность решения. Но это можно настроить путем простого рендеринга на холсты большего или меньшего размера в зависимости от ситуации. Также обратите внимание, что сглаживание в коде 2D-рендеринга (часто включенное по умолчанию) дает точность лучше, чем на уровне пикселей. Так, например, рендеринг фигуры 100x100 на холст тех же размеров, я думаю, должен дать точность порядка 1 / (100 x 100 x 255) = 0,000039% ... что, вероятно, «достаточно хорошо» для всех, кроме самых сложных проблем.

<p>Area computation of arbitrary figures as done thru pixel-painting, in which a complex shape is drawn into an HTML5 canvas and the area determined by comparing the number of white pixels found in the resulting bitmap.  See javascript source for details.</p>

<canvas id="canvas" width="80" height="100"></canvas>

<p>Area = <span id="result"></span></p>
// Get HTML canvas element (and context) to draw into
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Lil' circle drawing utility
function circle(x,y,r) {
  ctx.beginPath();
  ctx.arc(x, y, r, 0, Math.PI*2);
  ctx.fill();
}

// Clear canvas (to black)
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Fill shape (in white)
ctx.fillStyle = 'white';
circle(40, 50, 40);
circle(40, 10, 10);
circle(25, 15, 12);
circle(35, 90, 10);

// Get bitmap data
var id = ctx.getImageData(0, 0, canvas.width, canvas.height);
var pixels = id.data; // Flat array of RGBA bytes

// Determine area by counting the white pixels
for (var i = 0, area = 0; i < pixels.length; i += 4) {
  area += pixels[i]; // Red channel (same as green and blue channels)
}

// Normalize by the max white value of 255
area /= 255;

// Output result
document.getElementById('result').innerHTML = area.toFixed(2);

Это решение не учитывает математические вычисления с площадями окружностей. Он упускает из виду суть вопроса OP. Очень часто геометрия рендеринга - это только половина дела при работе с геометрическими фигурами
Стив
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.