Найти точку на кривой Безье при заданном расстоянии от начальной точки?

Я создал 4-точечную кривую Безье и расстояние. Начиная с начальной точки, как мне найти координаты x, y точки, которая находится на таком расстоянии от начальной точки?

Я просмотрел другие примеры, и, насколько я могу судить, они аппроксимируют значения, разделяя кривую на несколько тысяч точек, а затем находя ближайшую точку. У меня это не сработает. В том, что я делаю, я хотел бы быть точным только до двух десятичных знаков. Ниже приведена простая форма того, что мне нужно для создания кривой Безье. (Значения y произвольны, значения x всегда находятся на расстоянии 352 пикселя). Если важно, я работаю на Java.

path.moveTo(0, 400);
path.curveTo(352, 480, 704, 590, 1056, 550);

Итак, предполагая, что моя начальная точка равна 0,400, как мне найти координаты точки, которая находится на расстоянии 35 расстояний от этой начальной точки (вдоль кривой)? (В идеале что-то, не требующее интенсивного использования процессора. Это может работать 200 раз в секунду)


person Brandon    schedule 18.10.2011    source источник


Ответы (2)


Для всех, кто нашел мой вопрос, я решил свою проблему. Чтобы найти общее расстояние вашей кривой, разбейте ее примерно на 1000 частей (все еще довольно точно), найдите расстояние между каждой точкой, затем сложите их все вместе. (вы должны использовать параметрическую формулу)

Теперь найдите процент пути по вашей кривой. = расстояние / totalLengthOfCurve

Используйте этот процент в качестве нового значения t для x и y, и теперь у вас есть новые позиции x и y.

ВАЖНО: Это странный случай, но используйте абсолютное значение, если ваше значение t когда-либо будет больше 1. Когда вы его кубите, это значение будет отрицательным ... = происходят плохие вещи.

Уродливый, но актуальный код показан ниже.

Разбивая кривую на 1000 частей

    for (double t = 0.00; t < 1.001; t= t + .001) {
         double xValue = Math.pow((1-t), 3) * point1x + 3 * Math.pow((1-t), 2) * t * point2x + 3 * (1-t) * Math.pow(t, 2) * point3x + Math.pow(t, 3) * point4x;
         double yValue = Math.pow((1-t), 3) * point1y + 3 * Math.pow((1-t), 2) * t * point2y + 3 * (1-t) * Math.pow(t, 2) * point3y + Math.pow(t, 3) * point4y;

** Теперь, когда вы рассчитываете расстояние между каждой точкой. Я предлагаю поместить вычисленные выше значения в массив и выполнить цикл.

Расчет положений x и y

    xPos = Math.abs(Math.pow((1 - percenttraveled), 3)) * point1x + 3 * Math.pow((1 - percenttraveled), 2) * percenttraveled * point2x + 3 * Math.abs((1 - percenttraveled)) * Math.pow(percenttraveled, 2) * point3x + Math.abs(Math.pow(percenttraveled, 3)) * point4x;
    yPos = Math.abs(Math.pow((1 - percenttraveled), 3)) * point1y + 3 * Math.pow((1 - percenttraveled), 2) * percenttraveled * point2y + 3 * Math.abs((1 - percenttraveled)) * Math.pow(percenttraveled, 2) * point3y + Math.abs(Math.pow(percenttraveled, 3)) * point4y;
person Brandon    schedule 30.10.2011
comment
для всех, кто также читает комментарии, описанный метод на самом деле не является математически обоснованным, поскольку расстояние вдоль кривой увеличивается линейно вдоль кривой, тогда как значения t увеличиваются полиномиально. На самом деле проще построить LUT, просматривая t значения, и для каждой найденной пары x / y просто записывать их расстояние в {t,x,y,d} четверке. Затем для нахождения x / y для d нужно просмотреть список (отсортированный по d) до d_n ‹= d‹ = d_n + 1 и интерполировать x и y для этих двух записей. - person Mike 'Pomax' Kamermans; 16.05.2014
comment
Вы можете получить очень хорошую оценку кривой Безье с 30-40 точками, используя алгоритм Де Кастельжау , который очень легко понять и реализовать. 1000 очков - это слишком. - person BlueRaja - Danny Pflughoeft; 03.06.2015

В библиотеке javagraphics есть MeasuredShape (https://javagraphics.java.net/doc/com/bric/geom/MeasuredShape.html), который предоставляет для этого getPoint метод. Он также имеет несколько очень удобных методов для получения подпутей и касательных углов. Насколько я могу судить, они «правильно» реализуют логику путей, не прибегая к разбиению путей.

Я использовал эту часть библиотеки в проекте, который требует такого рода геометрических вычислений, и, похоже, он отлично работает.

person Yona Appletree    schedule 17.02.2014