Відповіді:
Ось моя спроба. Наступні алгоритми далеко не ідеальні , але вони прості, і я вважаю, що ви повинні почати з цього, перевірити, чи працюють вони у вашій ситуації, і пізніше перейти на щось швидше та / або точніше.
Ідея така:
Крива Безьє параметризується функцією, що F(t)
використовує набір контрольних точок і змінний параметрt
. Кількість генеруючих точок неважлива.
Рядок параметризований на дві точки A
і B
.
Нехай, SAMPLES = 10
наприклад
Почніть з t0 = 0
іt1 = 1
Дозволяти dt = (t1 - t0) / SAMPLES
Якщо dt < 1e-10
(або будь-який інший стан точності, який ви вважаєте за потрібне), алгоритм закінчений, і відповідь єF(t0)
.
Обчисліть список SAMPLES + 1
точок на кривій Безьє:
L[0] = F(t0)
L[1] = F(t0 + dt)
L[2] = F(t0 + 2 * dt)
L[SAMPLES] = F(t0 + SAMPLES * dt)
Знайдіть, який пункт L
із індексом i
є найближчим до рядка. Використовуйте будь- який відомий вам метод відстані точки / лінії , наприклад квадратну відстань, ||AB^L[i]A||² / ||AB||²
де ^
позначають поперечний добуток, і ||…||
це відстань.
Якщо i == 0
, встановити i = 1
; якщо i == SAMPLES
, встановитиi = SAMPLES - 1
Нехай t1 = t0 + (i + 1) * dt
іt0 = t0 + (i - 1) * dt
Поверніться до кроку 3.
На цей раз у нас є дві криві Безьє, параметризовані по F(t)
та G(t)
.
Нехай, SAMPLES = 10
наприклад
Почніть з t0 = 0
, t1 = 1
, s0 = 0
іs1 = 1
Дозволяти dt = (t1 - t0) / SAMPLES
Дозволяти ds = (s1 - s0) / SAMPLES
Якщо dt < 1e-10
(або будь-який інший стан точності, який ви вважаєте за потрібне), алгоритм закінчений, і відповідь єF(t0)
.
ЯКЩО це перший запуск циклу:
6.1. Обчисліть список SAMPLES + 1
пунктів F
( див. Вище ).
6.2. Обчисліть список SAMPLES + 1
пунктів на G
.
6.3. Знайдіть, яка пара точок є найближчою одна до одної.
6.4. Оновлення t0
, t1
, s0
, s1
як показано вище.
ELSE : альтернативно обчислити список точок на F
АБО списку пунктів G
, потім знайти, яка точка F
наближається до G(s0)
оновлення t0
та t1
, АБО, яка точка G
є найближчою до F(t0)
оновлення s0
та s1
.
Поверніться до кроку 3.
За задумом ці алгоритми завжди збігаються до локального мінімуму. Однак немає гарантії, що вони сходиться до найкращого рішення. Зокрема, алгоритм кривої Безьє зовсім не дуже хороший, і якщо дві криві знаходяться близько один до одного в багатьох місцях, ви, на жаль, можете пропустити рішення довгим пострілом.
Але, як я вже сказав, перш ніж почати думати про більш надійні рішення, спершу слід експериментувати з тими простими.
1) Перекладіть все на одну вісь, тож замість того, щоб обчислювати довжину однієї точки до 'лінії', 'лінія' - це, скажімо, вісь Y.
Тоді, е-е, з урахуванням кривої Безьє, я б сказав, що це відповідає кількості контрольних точок.
Якщо їх є три (початок, "контроль" і кінець), я б здійснив певну перевірку (скажіть кожен на пару відсотків, а потім уточнити між найближчими (скажімо, "двійковий" підхід).
Більше балів, я б спробував пару, яка була найближче до (перекладено Y-Axis).
Я впевнений, що математик може дати вам точне рішення (з математики), але якщо ви хочете знайти / рішення у відеоігри, вам може бути краще злегка рішення, оскільки реальне рішення може містити кілька відповідей ( Я навіть не кажу про потужність обробки).
Деякі відповіді зі сторінки блогу Algorithmist , яка правильно знаходить найближчу точку на заданій квадратичній кривій Безьє.
Демо .
Для кривої Безьє - прямолінійного випадку, найбільш точним способом знайти відповідь є наступне: