Як обчислити найближчу точку на 2 кривих?


15

З огляду на точки прямої та квадратичну криву Безьє, як обчислюють їх найближчу точку? .... Аналогічно, з огляду на точки 2 кривих, як отримати найближчу точку?

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


2
Я вважаю, що це питання є гарним початком.
sam hocevar

Відповіді:


3

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

Ідея така:

  • Зразки кривої Безьє, знайдіть найближчу точку на цьому зразку
  • Зробіть пробірку навколо знайденої точки, знайдіть нову найближчу точку
  • Продовжуйте, поки точка більше не сильно зміниться

Алгоритм відстані від кривої Безьє до лінії

Крива Безьє параметризується функцією, що F(t)використовує набір контрольних точок і змінний параметрt . Кількість генеруючих точок неважлива.

Рядок параметризований на дві точки Aі B.

  1. Нехай, SAMPLES = 10наприклад

  2. Почніть з t0 = 0іt1 = 1

  3. Дозволяти dt = (t1 - t0) / SAMPLES

  4. Якщо dt < 1e-10(або будь-який інший стан точності, який ви вважаєте за потрібне), алгоритм закінчений, і відповідь єF(t0) .

  5. Обчисліть список SAMPLES + 1точок на кривій Безьє:

    • L[0] = F(t0)
    • L[1] = F(t0 + dt)
    • L[2] = F(t0 + 2 * dt)
    • L[SAMPLES] = F(t0 + SAMPLES * dt)
  6. Знайдіть, який пункт Lіз індексом iє найближчим до рядка. Використовуйте будь- який відомий вам метод відстані точки / лінії , наприклад квадратну відстань, ||AB^L[i]A||² / ||AB||²де ^позначають поперечний добуток, і ||…||це відстань.

  7. Якщо i == 0, встановити i = 1; якщо i == SAMPLES, встановитиi = SAMPLES - 1

  8. Нехай t1 = t0 + (i + 1) * dtіt0 = t0 + (i - 1) * dt

  9. Поверніться до кроку 3.

Алгоритм відстані від кривої Безьє до кривої Безьє

На цей раз у нас є дві криві Безьє, параметризовані по F(t)та G(t).

  1. Нехай, SAMPLES = 10наприклад

  2. Почніть з t0 = 0, t1 = 1, s0 = 0іs1 = 1

  3. Дозволяти dt = (t1 - t0) / SAMPLES

  4. Дозволяти ds = (s1 - s0) / SAMPLES

  5. Якщо dt < 1e-10(або будь-який інший стан точності, який ви вважаєте за потрібне), алгоритм закінчений, і відповідь єF(t0) .

  6. ЯКЩО це перший запуск циклу:

    6.1. Обчисліть список SAMPLES + 1пунктів F( див. Вище ).

    6.2. Обчисліть список SAMPLES + 1пунктів на G.

    6.3. Знайдіть, яка пара точок є найближчою одна до одної.

    6.4. Оновлення t0, t1, s0, s1як показано вище.

  7. ELSE : альтернативно обчислити список точок на F АБО списку пунктів G, потім знайти, яка точка Fнаближається до G(s0)оновлення t0та t1, АБО, яка точка Gє найближчою до F(t0)оновлення s0та s1.

  8. Поверніться до кроку 3.

Випуски

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

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


0

1) Перекладіть все на одну вісь, тож замість того, щоб обчислювати довжину однієї точки до 'лінії', 'лінія' - це, скажімо, вісь Y.

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

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

Більше балів, я б спробував пару, яка була найближче до (перекладено Y-Axis).

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


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

0

Деякі відповіді зі сторінки блогу Algorithmist , яка правильно знаходить найближчу точку на заданій квадратичній кривій Безьє.

Демо .

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


Так, приємна демонстрація. Де відповідь?
Анко

1
Я припускаю , що він хотів , щоб подивитися на демо джерело: algorithmist.net/DegrafaClosestToQuad/srcview/index.html
Mutoh

0

Для кривої Безьє - прямолінійного випадку, найбільш точним способом знайти відповідь є наступне:

  1. Перетворіть задачу так, щоб пряма завжди була горизонтальною при Y = 0. Це робиться шляхом множення всіх контрольних точок на відповідну афінну матрицю. (Я припускаю, що ви знайомі із зображенням афінних перетворень площини з 3x3 матрицями з 3 фіксованими записами.)
  2. Огляньте координати Y контрольних точок. Якщо вони не мають однакового знаку, то може бути перетин з лінією. Обчисліть коріння Y частини кривої Безьє. Для поліномів можна використовувати будь-який метод кореневого пошуку, їх в літературі багато. Наприклад, google "опуклим корпусом марширує" - це досить хороший метод для поліномів, які використовуються в кривих Безьє. Кожен корінь, який ви знайдете, - значення часу перетину з лінією, де відстань дорівнює нулю - ваша робота виконана.
  3. Якщо всі Y-координати мають однаковий знак, обчисліть похідну Y-частини кривої Безьє. Ви можете ігнорувати X координати точок, оскільки вони не мають різниці - цільова лінія горизонтальна. Знайдіть корені цієї похідної. Це значення часу, за яких крива локально знаходиться найближче до лінії.
  4. Явно оцініть криву Безьє для всіх коренів, які ви знайшли на попередньому кроці, і повідомте про корінь, який дає найменшу відстань від рядка. Також потрібно перевірити кінцеві точки - вони можуть давати меншу відстань, ніж будь-який корінь.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.