Надійний тест на перетин двох кривих Безьє


9

Як надійно з’ясувати, чи перетинаються дві плоскі криві Безьє? Під "надійно" я маю на увазі тест відповість "так" лише тоді, коли криві перетинаються, а "ні" - лише тоді, коли вони не перетинаються. Мені не потрібно знати, за якими параметрами було знайдено перетин. Я також хотів би використати номери з плаваючою комою у реалізації.

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

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


Я не впевнений, що він існує як такий, визначаючи, що wetehr або theres можливість для 0-1 або 2 або більше є досить тривіальною, але рецептура насправді не робить її простою, щоб переконатися, що її 0 або 1 без фактичної перевірки.
joojaa

Які вимоги до виконання? Рішенням, яке могло б дати досить точні результати, було б наближення обох кривих великою кількістю коротких прямих відрізків, а потім їх перетинання попарно. Але це коштує багато часу і пам’яті.
Dragonseel

@Dragonseel Добре, я був би радий будь-якого рішення, справді, але так як ви запитали O (1), було б добре. Але наближення кривих до відрізків ліній призводить до тих самих проблем, що і тест на перекриття обмежувальної коробки ...
Ecir Hana

Цікава проблема. Я не думаю, що відповідь проста, але я хотів би помилитися. Чи є у вас посилання на папір Седерберг і Майєрс?
Даніель М Гессел

@DanielMGessel Так, дивіться редагування вище.
Ecir Hana

Відповіді:


6

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

Щоб бути явним, задано пару двовимірних кривих, визначених c1,c2:[0,1]R2, визначте відстань у квадраті як

f(u,v):[0,1]2R0|c2(v)c1(u)|2

Для кубічних кривих функція fто є поліном шостого ступеня у двох змінних. Потім можна застосувати чисельні методи оптимізації, такі як симплексний метод або спряжений градієнтний спуск . На жаль, функція може мати кілька локальних мінімумів (вона не опукла), тому оптимізація не проста. Можливо, існують більш спеціалізовані методи оптимізації для поліномів, але це не для мене сфера досвіду.


Чому це поліном 6-го ступеня, а не 3-й, якщо ми говоримо про кубічні Безьє? І два способи, з якими ви пов’язані, чи підходять вони до пошуку рішень лише в[0,1]2, на відміну від цілого R2?
Ecir Hana

1
@EcirHana Це 6-й ступінь, тому що це відстань у квадраті. (Ви можете вивести його на квадратний корінь, але тоді він більше не буде многочленом і буде нульовим у нулях.) Зауважте, що[0,1]це простір параметрів, а не простір, у якому живуть сплайни, тобто це сплайни з кінцевими точками. У будь-якому випадку методи прекрасно спрацюютьR2, але вони лише "подорожують під гору" від початкової здогадки і знаходять місцевий мінімум; потрібно щось більше, щоб вивчити всю область параметрів і знайти глобальний мінімум. Там, мабуть, корисно обмеження простору параметрів.
Натан Рід

1
Натан - приємна рецептура! Я іржавий, але: я думаю, ви можете розділити кожну криву Безьє на щонайбільше 5 сегментів, кудих або у змінити напрямок у кривій. х, як функція ci змінює напрям максимум удвічі (коріння похідної), розбиваючи криву на 3 відрізки, 2 з яких можна розділити знову за зміною напрямку у. Тепер у вас є не прямі сегменти, а сегменти, які "не надто криво". Я думаю, якщо ви розпочнете пошук у 25 пунктах, вибраних парами сегментів, ви завжди зможете знайти глобальні мінімуми, але я не можу зовсім зрозуміти, як довести (або спростувати) це.
Даніель М Гессел

@Nathan: Я вважав це, але, витративши багато часу на написання коду, щоб знайти мінімуми у форматах стиснення текстур, все це здавалося трохи огидним.
Simon F

5

[Відмова від відповідальності: Я думаю, що наступне має працювати, але насправді не кодував це сам]

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

Припустимо, наші криві A (s) і B (t) з контрольними точками { A0, A1..An } і { B0, .. Bm } відповідно.

Мені здається, що, зважаючи на пару 2D Beziers, для яких ми хочемо визначити, чи не перетинаються, слід розглянути шість випадків:

  1. Випадок, коли ми можемо «тривіально» визначити, вони не перетинаються.

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

  3. Один з Безьє є виродженим, тобто точкою (яка відбудеться, якщо всі контрольні точки однакові). Можна припустити, що ми вже розглядали випадок, коли обидва є очками.

  4. Одна або кілька кривих закриті, наприклад. A0 == An. Щоб полегшити життя, ми поділимо такі криві і почнемо заново.

  5. Існує нескінченна кількість точок перетину, оскільки кожна є підмножиною "батьківського" Безьє, і вони перетинаються.

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

На даний момент ми проігноруємо 3 і 4, але повернемося до них пізніше.

Випадок 1

Як ви натякаєте у своєму запитанні, якщо відповідні обмежувальні поля контрольних точок A і B ) не перетинаються, криві не можуть перетинатися. Очевидно, це швидкий тест на відхилення, але він надто консервативний. Як ви, напевно, знаєте, при кривій Безьє опуклий корпус його контрольних точок утворює (більш жорсткий) зв'язаний на кривій. Таким чином, ми можемо використовувати техніку роздільної осі, щоб вирішити, чи не перетинаються корпуси A і B. (наприклад, як показано у Вікіпедії :)

введіть тут опис зображення

Випадок 2

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

Розглянемо просто криву A:

"Товста лінія" межі Безьє

Ми знаємо, що крива починається з А0, закінчується в Ан, і буде лежати всередині опуклого корпусу. Для простоти обчислимо напрямок відрізка лініїА0Ан¯ і обчислити межі з обох сторін (тобто візьміть крапки добутку решти контрольних точок проти перпендикуляра до А0Ан¯).

Якщо ми зробимо те саме з кривою B, отримаємо такий (можливий) випадок: введіть тут опис зображення

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

Справа 6

Якщо ми не можемо одразу показати жоден із перерахованих вище випадків, то розділимо кожного з Безьє на дві "половинки", тобто А1,А2,Б1,Б2. Це досить просто (залишається читачем як вправа), але особливо тривіально для квадратичних Безьє :

Рекурсивно порівнюйте 4 комбінації: (А1,Б1),(А2,Б1)...(А2,Б2). Зрозуміло, що якщо всі проходять справа 1, то перетину немає. Якщо якась помилка 1, продовжуйте решту тестів із зменшеним набором.

Випадок 3 та 5

Це стає дещо більш виснажливим.

Якщо "випадок 3" проходить тест "випадок 1", мені здається, що вам потрібно вирішити фактичне перехрестя. З огляду на те, що існує простий процес для зіставлення N контрольних точок Безьє, A (s), до N-1 точок Безьє, A '(s), що представляють його 1-е похідне, тоді (за умови догляду за відносно рідкісні, так звані "вироджені" ситуації, коли 1-я похідна робить нульову), тоді ітерація Ньютона (за одним виміром) може бути використана для пошуку потенційних рішень.
Зауважимо також, що, оскільки контрольні точки A '(s) пов'язані з похідними значеннями, існує можливість зробити раннє усунення деяких випадків.

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


Так, але мене особисто більше цікавить випадок, коли про випадок, коли Bm та / або B0 знаходяться в межах обсягу максимуму A і min, але не пронизує його, тоді вам потрібно розділити і, в гіршому випадку, обчислити перетин бал. Кращими способами було б використання мінімального обмежувального поля, також відомого як наближення товстої лінії.
joojaa

З огляду на те, що з кожним двійковим підрозділом різниця між кривою та відрізком, що з'єднує кінцеві точки, зменшується за розумним коефіцієнтом (і, вгорі голови, я думаю, це може бути чотири рази для квадратики), безумовно, межі йдуть щоб досить швидко сходитися до «тонкої» стрічки.
Саймон Ф

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

Ви маєте на увазі, наприклад, An == B0 . Ви визначаєте це як перехрестя чи ні?
Саймон Ф

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