Об'єднана площа колів, що перекриваються


107

Нещодавно я зіткнувся з проблемою, коли у мене було чотири кола (середні точки і радіус) і мені довелося обчислити площу об'єднання цих кіл.

Приклад зображення:

Для двох кіл це досить просто,

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

Але чи є розумний алгоритм, який я можу використовувати, коли є більше двох кіл?


15
Це дійсно цікава проблема, я пам’ятаю, що це бачив у середній школі з геометрії, але так і не знайшов рішення. Якщо ви не можете знайти відповідь тут, спробуйте опублікувати її на mathoverflow.net і дозвольте математикам зламати це: P
Чарльз Ма

25
інколи справжнім програмістам потрібна реальна математика
фа.

1
Як щодо опрацювання відповіді на це питання - "У нас є представники продажів у цих 4 місцях, кожен з яких обслуговує площу з цими 4 радіусами. Яку частину країни ми охоплюємо?" Якщо у вас була зміна бази даних представників продажів, це стає питанням програмування!
Кріс Робертс

5
Власне, саме таку проблему люблять думати справжні програмісти.
МАК

2
@zvolkov: плати описуються мовою, яка розбиває квадрати та кола вниз і, за бажанням, перетягує їх. "Обчислити площу міді". (Це може знадобитися для обчислення часу травлення, знайте, чи слід додавати вишукані твори мистецтва, різні речі.)
DigitalRoss

Відповіді:


97

Знайдіть усі перетини кола по зовнішньому периметру (наприклад, B, D, F, H на наступній схемі). З’єднайте їх разом з центрами відповідних кіл, щоб утворився многокутник. Площа об’єднання кіл - площа багатокутника + площа кружових зрізів, визначена послідовними точками перетину та центром кола між ними. Вам також потрібно буде врахувати будь-які отвори.

коло перекриття


17
Що відбувається, коли в центрі є отвір?
Джон Гітцен

3
Вам потрібно буде відняти центральний багатокутник для отвору від загальної кількості і додати кругові фрагменти для цього багатокутника до загальної.
Мурахи Аасма

3
приємно, але, мабуть, для цього знадобиться багато деталей реалізації, щоб обробити всі особливі випадки (коло всередині іншого, немає перехрестя, отвори, контакт один точка ...)
фа.

1
Особливі випадки досить легкі. Кола всередині інших відкидаються, не перетинаючи периметр. Один точковий контакт - це два перехрестя з нульовою відстані. Від'єднані фігури можна знайти за допомогою алгоритму підключених компонентів на графіку, де з'єднано два кола, якщо відстань центрів менше суми радіусів. Отвори - це всі багатокутники, крім одного з найбільшою площею. Перехрестя по периметру - це всі перетини, які не розташовані строго в жодному колі.
Мурахи Аасма

4
так, але межі отворів - це також (маленькі) дуги. Я все ще думаю, що для того, щоб добре працювати, для цього потрібно багато коду.
фа.

32

Я впевнений, що є розумний алгоритм, але ось такий німий, щоб врятувати, шукаючи його;

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

Звичайно, це німо, але:

  • ви можете отримати таку точну відповідь, скільки хочете, просто генеруйте більше балів;
  • він буде працювати для будь-яких фігур, за якими можна обчислити відмінність всередині / зовні;
  • вона прекрасно паралелізується, так що ви можете використовувати всі свої сердечники.

2
Це спрацює, але методи Монте-Карло на кшталт цього, засновані просто на рівномірному відборі, зазвичай не мають найкращих показників конвергенції.
ShreevatsaR

2
Вибачте, але, хоча я ціную ваші зусилля і вважаю, що ваше рішення "практично застосовне", я вважаю ваш підхід дуже неправильним. Це проблема, ніж можна і потрібно вирішувати за допомогою математики, а не грубої сили. Витрачати енергію та сердечники на подібні проблеми - марно і рясно.
mafu

5
Ви маєте рацію, мені соромно за себе, але у мене є скупчення з 12 000 ядер, я можу дозволити собі бути щедрими. І я не можу зрозуміти, як зробити елегантну шкалу математичного рішення для багатьох процесорів.
Марка високої продуктивності

8
З Монте-Карло (або з будь-яким рандомізованим) підходом немає нічого поганого за умови, що він надає необхідну ступінь точності та робить це за розумну кількість часу.
МАК

@mafutrct, ти, звичайно, маєш рацію. Однак зробити невеликі помилки в математиці легко. Це рішення забезпечує простий спосіб перевірити правильність.
Річард

18

Відповідь мурашок Аасма дала основну думку, але я хотів зробити це трохи більш конкретним. Подивіться на п’ять кіл нижче та спосіб їх розкладання.

Приклад

  • Сині точки - це центри кола.
  • Червоні точки - це межі перетину кола.
  • Червоні точки з білим інтер’єром - це межі перетину колу, які не містяться в жодному іншому колі .

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

Це розкладає коло об'єднання на набір багатокутників (затіненим синім кольором) та кругових шматочків пирога (заштрихованого зеленого кольору), які попарно роз'єднуються та охоплюють початковий союз (тобто перегородку). Оскільки кожен фрагмент тут - це те, що легко обчислити площу, ви можете обчислити область об’єднання, підсумовуючи площі частин.


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

1
Алгоритм може бути спрощений за допомогою набору трикутників, що не перекриваються, замість полігонів. Дуги (зелені зони) - це ділянки, що містяться лише в одному колі. Розширюйте розмір багатокутника, додаючи більше кіл. (врешті-решт, ви можете забути, що навіть говорите про багатокутники). Це робить булі властивості, і області також простіше обчислити. Коли порожниста червона крапка стає суцільною червоною крапкою, ви просто додаєте в свій набір більше трикутників, і ви регулюєте дугу, яку вона «з’їдає» все більше і більше пересічних кіл.
Стів

16

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

Це також працює для будь-якого об'єднання фігур, якщо ви можете визначити, чи знаходиться квадрат всередині або зовні або перетинає фігуру.

Кожна клітина має один із станів: порожній, повний, частковий

Алгоритм полягає у "малюванні" кіл у квадраті, починаючи з низької роздільної здатності (4 комірки, наприклад, позначені як порожні). Кожна комірка є або:

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

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

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

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


3
Я здогадуюсь , що це також сходиться швидше, ніж алгоритм точки монто Карло всередині та поза.
Френк Крюгер

Це здається набагато простішим у виконанні. Однозначно запропонований найкращий метод грубої сили. Дякую!
Антон Ханссон

груба сила тут називається теоремою віджимання
fa.

Це такий алгоритм, який ви використовуєте в інтервальній арифметиці. en.wikipedia.org/wiki/Interval_arithmetic
rjmunro

13

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

Це може дати кращі уявлення про загальне узагальнення алгоритму для більшої кількості кіл, що перекриваються.

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

(на практиці, можливо, метод Монте-Карло вартий)

alt текст
(джерело: 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означає об'єднання B і A ∩ Bозначає пересічення B (ви можете це зробити з першого кроку.

  • Тепер продовжуйте додавати кола та продовжуйте розробляти додану область як суму / віднімання областей кіл та областей перетинів між колами. Наприклад, для 3-х кіл (називаємо зайве коло С) ми обробляємо область за такою формулою:

(Це те саме, що вище, де 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 тих кіл, які можна точно обчислити (не маю уявлення, як це зробити проте).

Мабуть, є кращий спосіб зробити цей btw - складність значно зростає (можливо, експоненціально, але я не впевнений) для кожного доданого додаткового кола.


Що з форматуванням? Також вибачте за використання n і u для перетину та союзу, мабуть, кращий спосіб ...
Justin

1
додано кілька знаків з'єднання unicode (∪) та перетину (∩). сподіваємось, вони працюють.
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 такі, що

Хвороба

тоді РЗС - просто область області R, і її можна отримати, вирішивши закритий інтеграл або LHS, і саме це ми і будемо робити.

Усі союзи можуть бути розбиті на такі непересічні набори кіл, які перетинаються

Так Інтегрування по шляху в проти годинникової стрілки дає нам Площа регіону та інтегрування за годинниковою стрілкою дає нам негатив Району . Так

AreaOfUnion = (Інтеграція по червоних дугах у напрямку проти годинникової стрілки + Інтеграція по синіх дугах за годинниковою стрілкою)

Але крута хитрість полягає в тому, що для кожного кола, якщо ми інтегруємо дуги, які не знаходяться ні в одному іншому колі, ми отримаємо потрібну нам площу, тобто ми отримаємо інтеграцію в напрямку проти годинникової стрілки по всіх червоних дугах і інтеграцію по всіх синіх дугах по напрямку за годинниковою стрілкою. РОБОТА Зроблена !!!

Навіть випадки, коли коло не перетинається з будь-яким іншим, опікується.

Ось посилання GitHub на мій код C ++


-1

Підхід до малювання пікселів (як запропонував @Loadmaster) різними способами перевершує математичне рішення:

  1. Реалізація набагато простіша. Вищезазначена проблема може бути вирішена менш ніж в 100 рядках коду, як це демонструє рішення JSFiddle (здебільшого тому, що це концептуально набагато простіше і не має жодних крайових випадків чи винятків для вирішення).
  2. Він легко адаптується до більш загальних проблем. Він працює з будь-якою формою, незалежно від морфології, якщо це можливо з двовимірними бібліотеками малювання (тобто "всі вони!") - кружечками, еліпсами, сплайнами, багатокутниками, яку ви називаєте. Чорт, навіть растрові зображення.
  3. Складність рішення для малювання пікселів становить ~ O [n] порівняно з ~ O [n * n] для математичного рішення. Це означає, що вона буде працювати краще, оскільки кількість фігур збільшується.
  4. А якщо говорити про продуктивність, то ви часто отримуєте апаратне прискорення безкоштовно, оскільки більшість сучасних 2D-бібліотек (як-от полотно HTML5, я вважаю) вивантажать рендеринг роботи на графічні прискорювачі.

Недоліком піксельної картини є кінцева точність рішення. Але це налаштовується просто рендерінгом на великі чи менші полотна, як цього вимагає ситуація. Зауважте також, що антизбудження в коді 2D-рендерінгу (часто його включають за замовчуванням) забезпечить кращу точність на рівні пікселя. Наприклад, наприклад, виведення фігури розміром 100х100 на полотно тих самих розмірів, я думаю, має дати точність у порядку 1 / (100 x 100 x 255) = .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);

Це рішення не враховує проведення математичних обчислень з областями кіл. Він пропускає суть питання щодо ОП. Дуже часто геометрия візуалізації - це лише половина битви при роботі з геометричними фігурами
Стів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.