Как определить длину пути?

11

У меня есть игра, в которой каждый игрок должен пройти по указанному пути. Я рисую путь, используя кривые Безье. Как я могу определить общую реальную (не линейную) длину пути и расстояние, пройденное каждым игроком? (Расстояние между начальной точкой и указанной точкой на пути.)

ОБНОВИТЬ:

Путь представлен в декартовой плоскости (2D).

Валентин Раду
источник
На ваш вопрос ответили в нижней части этого ответа
BlueRaja - Дэнни Pflughoeft

Ответы:

7

Как говорилось в предыдущих ответах, вычислить длину кривой Безье сложно ( невозможно ?). Я бы сказал, что в 100% игр используется приблизительная длина, которая почти всегда достаточно точна.

Несколько месяцев назад я реализовал это, используя предложенный подход, разбивая кривую на «маленькие» сегменты и добавляя их длину. Там пример реализации C ++ здесь .

Дэн
источник
11

Измерение длины кривой Безье сложно. Если вы не возражаете против небольшой неточности, простым решением было бы приблизить кривые Безье прямыми линиями и вычислить сумму длин линий. Чем больше сегментов вы создаете, тем лучше приближение.

bummzack
источник
Я мог бы подумать об этом, но как я могу определить, сколько сегментов у меня должно быть, и как я могу отобразить сегменты, чтобы их начальная и конечная точки были на моем пути? У этой техники есть имя? (поэтому я ищу его в Google)
Валентин Раду
Простой подход состоит в том, чтобы просто использовать линейное распределение точек от B (0) до B (1) ... очень похоже на то, что вы бы использовали для построения кривой. Посмотрите на исходный код в ответе Дэна.
Bummzack
Я был бы признателен за объяснение
отрицательного
7

Параметрирование длины сплайна более высокого порядка (т.е. более 1-го порядка) должно быть аппроксимировано; оно не может быть представлено напрямую, отсюда тот факт, что не так просто найти прямые решения для этого.

Некоторые существующие реализации (копирование-вставка кода):

Используя чебышевские приближения , по мнению авторов, точность возрастает с увеличением размера кривой. Посмотрите на псевдокод на стр. 7-8, остальное - описание других алгоритмов, на которых они основывают свой подход, которые вы можете игнорировать. Ряд ссылок в Интернете называют этот метод хорошим.

Смотрите также эти краткие подходы.

инженер
источник
5

Это началось как комментарий к комментарию к ответу @ bummzack, но вырос слишком долго.

как я могу определить, сколько сегментов я должен иметь

Есть два подхода. Первый - это просто стандартный алгоритм рендеринга кривой Безье: контрольные точки образуют ограничивающую рамку кривой, поэтому, если все контрольные точки находятся в эпсилоне от отрезка линии от начальной точки до конечной точки, вы приближаетесь к линии; в противном случае вы подразделяете, используя алгоритм де Кастеляу. Эпсилон выбирается в соответствии с ошибкой, которую вы хотите в конечном результате. (Для рендеринга обычно это 0,5 пикселя).

Другой подход - это уточнение с использованием интервальной арифметики. В качестве нижней границы берется длина линии от начала до конца, а в качестве верхней границы - сумма длин линий через контрольные точки. Опять же, подразделите в соответствии с вашими требованиями к окончательной ошибке.

Обычно делится на t = 0.5, но алгоритм де Кастельхау позволяет расщеплять в любой точке, поэтому, если у вас кубический Безье с контрольными точками от C_0 до C_3 и C_2 гораздо ближе к отрезку линии между конечными точками, чем C_1, вы можете обнаружить, что расщепление в одна из 1/3 или 2/3 дает более жесткие границы. Я не работал с алгеброй, чтобы обосновать, что было бы лучше, но вы можете поэкспериментировать и сообщить, если хотите. Если ничего другого, я хотел бы указать, что вариант есть.

Питер Тейлор
источник
3

Вычислить длину параметризованной кривой можно, взяв интеграл от sqrt ((dx / dt) ² + (dy / dt) ²), где dx / dt - производная от x-компонента кривой, а dy / dt является производной от y-компонента кривой. В случае сплайна Безье эти два одинаковы, поскольку уравнение можно распространить на любое измерение.

Формула для кубического сплайна Безье следующая: B (t) = (1 - t³) * P0 + 3 (1 - t) ²t * P1 + 3 (1 - t) t² * P2 + t³ P3, где P0 через P3 контрольные точки.

Согласно Wolfram | Alpha, производная этой формулы имеет вид: d (B (t)) / dt = 3 (t (t (P3 - P0) + P2 (2 - 3t) + P1 (3t² - 4t + 1))

Теперь вы можете поместить это обратно в уравнение для длины кривой и вычислить интеграл от t = 0 до t = 1. К сожалению, Wolfram | Alpha истекает, когда я пытаюсь это сделать. Вы можете сделать числовую интеграцию, однако.

Рууд
источник