получить точку на кривой Безье без угадывания или грубой силы - PullRequest
1 голос
/ 03 апреля 2019

Изначально я хотел использовать четыре точки (поскольку кривая Безье определяется 4 точками), но это вынуждает меня грубо форсировать позицию, поэтому я попробовал другой подход, и теперь мне нужна помощь:

У меня есть начальная точка P0, конечная точка P1 и наклоны m0 и m1, которые должны дать мне начальный / конечный наклон для вычисления кривой Безье между ними.
Кривая должна быть в форме функции (3-й степени), поскольку мне нужно получить высоту y заданной точки x.

Используя HTML5Canvas я могу без проблем нарисовать кривую Безье и используя эту функцию

enter image description here

, который позволяет мне вычислить любую заданную точку с учетом процента пути, которым я могу получить центральную точку кривой. Но мне это не нужно в зависимости от t, а от y в зависимости от x, поэтому не на полпути кривой, а на половине расстояния x между P0 и P1.

Изображение для визуализации:
enter image description here
Слева - то, что я могу вычислить, справа - то, что мне нужно.

Я пытался вычислить кубическую функцию, учитывая две точки P0, P1, а также наклоны m0, m1, что приводит к четырем уравнениям, которые я не могу решить с помощью только переменных входных данных. Я также пытался использовать вышеупомянутую функцию для вычисления t, используя значение x (которое известно), но там тоже нет кубиков.

Мне нужно избегать использования аппроксимаций или дорогостоящих циклов для этих вычислений, поскольку они выполняются много раз в секунду для многих объектов, поэтому этот ответ для меня неосуществим.

Любая помощь приветствуется.

Ответы [ 3 ]

1 голос
/ 04 апреля 2019

Чтобы решить эту проблему, нужно переписать уравнение Безье в степенной полиномиальной форме

X(t) = t^3 * (P3.X-3*P2.X+3*P1.X-P0.X) + 
       t^2 * (3*P0.X + 6*P1.X+3*P2.X) + 
       t * (3*P1.X - 3P2.X) +
       P0.X 

if X(t) = P0.X*(1-ratio) + P3.X*ratio 
then
let d = ratio * (P0.X - P3.X)

и решить кубическое уравнение для неизвестного t

a*t^3 + b*t^2 + c*t + d = 0

JS код здесь

Затем примените вычисленный параметр t (может быть до трех решений) к Y-компоненту и получите координаты точки. Обратите внимание, что формулы близки (без циклов) и должны работать достаточно быстро

1 голос
/ 03 апреля 2019

Я столкнулся с той же проблемой в проекте, над которым я работаю. Я не знаю формулы для получения координаты y от x, и я подозреваю, что у вас возникнут проблемы с этим маршрутом, потому что кривая Безье может иметь до 3 точек, которые имеют одинаковое значение x.

Я бы рекомендовал использовать библиотеку BezierEasing, которая была разработана для этого варианта использования и использует различные методы повышения производительности, чтобы сделать поиск максимально быстрым: https://github.com/gre/bezier-easing

0 голосов
/ 04 апреля 2019

Спасибо всем, кто ответил ранее, это, как правило, отличные решения.

В моем случае я могу быть на 100% уверен, что смогу преобразовать кривую в кубическую функцию, которая служит приближениемкривая Безье, использующая результат этого вычисления .

Поскольку в моем случае у меня есть контроль над моими точками, я могу заставить P0 быть на x = 0, что упрощает вычисления в линейной системеи, таким образом, позволяет мне вычислить кубическую функцию намного проще, как это:

let startPoint: Utils.Vector2 = new Utils.Vector2(0, 100);
let endPoint: Utils.Vector2 = new Utils.Vector2(100, 100);


let a: number, b: number, c: number, d: number;

function calculateFunction() {
    let m0: number = 0;
    let m1: number = 0;

    a = (-endPoint.x * (m0 + m1) - 2 * startPoint.y + 2 * endPoint.y) / -Math.pow(endPoint.x, 3);
    b = (m1 - m0 - 3 * a * Math.pow(endPoint.x, 2)) / (2 * endPoint.x);
    c = m0;
    d = startPoint.y;
}
...