Перетин кола з алгоритмом лінії зміщення


15

На жаль, я все ще не такий сильний у розумінні алгоритму Sweep Line . Усі статті та підручники з цієї теми вже прочитані, однак до розуміння ще далеко. Просто для того, щоб було зрозуміліше, я намагаюся вирішити якомога більше вправ. Але, дійсно цікаві та важливі завдання все ще залишаються для мене викликом.

Наступну вправу я знайшов у конспектах лекцій про перетин сегмента лінії всемогутнього Джеффа Еріксона.

Вправа 2. Охарактеризуйте та проаналізуйте алгоритм швидкої лінії, щоб визначити, чи задано кружків у площині, чи є два пересікання, за час O ( n log n ) . Кожне коло визначається його центром та його радіусом, тому вхід складається з трьох масивів X [ 1 .. n ] , Y [ 1 .. n ] та R [ 1 .. n ] . Будьте обережні, щоб правильно здійснити примітиви низького рівня.нО(нжурналн)Х[1.н],Y[1.н]R[1.н]

Спробуємо полегшити складну річ. Що ми знаємо про перетин кіл? Який аналог можна знайти при перетині ліній. Дві лінії можуть перетинатися, якщо вони суміжні, яке властивість має мати два кола, щоб перетинатися? Нехай - відстань між центром кіл, r 0 та r 1 центрами кіл. Розглянемо кілька випадків:гr0r1

  • Випадок 1: Якщо то розв’язків немає, кола відокремлюються.г>r0+r1

  • Випадок 2: Якщо то рішення немає, тому що одне коло міститься в іншому.г<|r0-r1|

  • Випадок 3: Якщо і r 0 = r 1, то кола збігаються і існує нескінченна кількість розв’язків.г=0r0=r1

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

Алгоритм. Тепер нам потрібно знайти щось спільне між двома пересічними колами. З аналоговим переходом лінії нам потрібно мати умову вставки та видалити умову до черги подій. Скажімо, точка події - це х координата першої та останньої точок, до яких торкається вертикальна лінія розгортки. На першій точці ми вставляємо коло в статус і перевіряємо на перехрестя (3 випадки для перевірки згадуються вище) з найближчими колами, на останній точці видаляємо коло зі статусу .

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

Додаток :

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


4
всесильний [потрібна цитата]
JeffE

@com, що ви маєте на увазі під «найближчим попереднім колом»?
Джо

1
Я припускаю, що statusпідтримує кола, що перетинають лінію розгортки? Припустимо, у вас зараз є 100 кіл status, і ви обробляєте подію вставки та вставляєте 101-е коло. Скільки кіл ви порівняєте, щоб перевірити на перехрестя? Як ви вибираєте, які кола для порівняння?
Джо

уууууу

Відповіді:


5

Ви точно на правильному шляху. Велике питання: коли ви вставляєте коло, які інші кола ви перевіряєте на перетин? Як ви виконуєте цю перевірку?

У випадку перетину відрізка ліній відрізки ліній у будь-якій заданій координаті x повністю упорядковані. (Ви можете перелічити їх від найнижчої до найвищої координати Y). Таким чином, ви можете підтримувати сегменти рядків у двійковому дереві пошуку, а коли ви додаєте новий сегмент, вам потрібно лише з’ясувати, куди він належить у двійковому дереві пошуку, і перевірити його сусідів на події перетину.

У випадку з колами не відразу зрозуміло, які кола перевірити. Якщо ваша відповідь "всі вони", то ваш алгоритм потребує певної роботи.

Чи можете ви знайти спосіб представлення кіл так, щоб вони були впорядковані, як і сегменти рядків?

Спробуйте представити кола як два півкруги. Кожна подія вставки - це фактично дві події: вставити верхню половину та вставити нижню половину.


На жаль, я не розумію півкола, можливо, ви розглядаєте півколо як мінімальну одиницю кола, яку можна перетинати (3 випадки перетину: перетин знаходиться на верхньому півколо, або на нижньому, або на обох). На початку випробовування всі кола упорядковуються по х координатах їх лівої та правої меж. Тому ми не повинні вважати х координованими за статусом , оскільки всі кола вже входять у х координатний порядок. Тому більш логічним вважається координата y центру (півкола) або будь-яка комбінація у та радіусів. Ваша думка?
com

@com Вам потрібна центральна точка та радіус, щоб визначити, чи перетинаються два кола, як ви це робили у власних перевірках. Просто координата y і радіус самі по собі не повністю визначають межу кола. Здається, є щось принципове в алгоритмах розгортки ліній, які ви не розумієте, але мені важко сказати, що це таке.
Джо

0

Я міг би придумати цей підхід, аналогічний розгортці Bentley Ottmann, що працює в O ((n + k) logn) час.

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

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

Оскільки задачу перетину ліній можна вирішити за час O ((n + k) logn), для перетину кола слід також те саме обмеження.

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

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