Найти Y с учетом X на кубической кривой Безье?

Мне нужен метод, который позволяет мне найти Y-координату на кубической кривой Безье, заданную X-координату.

Я сталкивался с множеством мест, где мне говорили, что нужно рассматривать это как кубическую функцию, а затем пытаться найти корни, что я понимаю. ОДНАКО уравнение для кубической кривой Безье имеет вид (для x-координат):

X(t) = (1-t)^3 * X0 + 3*(1-t)^2 * t * X1 + 3*(1-t) * t^2 * X2 + t^3 * X3

Что меня смущает, так это добавление (1-t) ценности. Например, если я заполню значения X некоторыми случайными числами:

400 = (1-t)^3 * 100 + 3*(1-t)^2 * t * 600 + 3*(1-t) * t^2 * 800 + t^3 * 800

тогда переставь это:

800t^3 + 3*(1-t)*800t^2 + 3*(1-t)^2*600t + (1-t)^3*100 -400 = 0

Я до сих пор не знаю значение (1-t) коэффициенты. Как я должен решить уравнение, когда (1-t) еще неизвестно?

5 ответов

Существует три распространенных способа выражения кубической кривой Безье.

Первый х в зависимости от т

x(t) = sum( f_i(t) a_i )
     = (1-t)^3 * x0 + 3*(1-t)^2 * t * x1 + 3*(1-t) * t^2 * x2 + t^3 * x3

Во-вторых, у как функция х

y(x) = sum( f_i(x) a_i )
     = (1-x)^3 * y0 + 3*(1-x)^2 * x * y1 + 3*(1-x) * x^2 * y2 + x^3 * y3

Эти первые два математически одинаковы, просто используют разные имена для переменных.

Судя по твоему описанию "найди Y-координату на кубической кривой Безье, учитывая x-координату на ней". Я предполагаю, что у вас есть вопрос, используя второе уравнение: вы пытаетесь переставить первое уравнение, чтобы помочь вам решить его, где, как вам следует использовать второе уравнение. Если это так, то перестановка или решение не требуются - просто подключите свое значение x, и у вас есть решение.

Вполне возможно, что у вас есть уравнение третьего типа, который является уродливым и сложным случаем. Это и параметры x, и y являются кубическими кривыми Безье третьей переменной t.

x(t) = sum( f_i(t) x_i )
y(t) = sum( f_i(t) y_i )

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

Я думаю, что это честный вопрос CS, поэтому я попытаюсь показать, как я решил это. Обратите внимание, что данный x может иметь более 1 значения y, связанного с ним. В случае, когда мне это нужно, это гарантированно не так, поэтому вам придется выяснить, как определить, какой из них вы хотите.

Я перебрал t, создав массив значений x и y. Я сделал это с довольно высоким разрешением для моих целей. (Я искал для создания 8-битной справочной таблицы, поэтому я использовал ~1000 точек.) Я просто включил t в уравнение Безье для следующих x и следующих y координат для сохранения в массиве. После того, как я сгенерировал все это, я просмотрел массив, чтобы найти 2 ближайших значения x. (Или, если было точное совпадение, используйте это.) Затем я выполнил линейную интерполяцию на этом очень маленьком отрезке, чтобы получить нужное мне значение y.

Дальнейшее развитие выражения должно избавить вас от (1 - t) факторы

Если вы запускаете:

expand(800*t^3 + 3*(1-t)*800*t^2 + 3*(1-t)^2*600*t + (1-t)^3*100 -400 = 0);

В wxMaxima или Maple (вы должны добавить параметр t хотя в этом) вы получите:

100*t^3 - 900*t^2 + 1500*t - 300 = 0

Решите новое кубическое уравнение для t (вы можете использовать формулу кубического уравнения для этого), после того, как вы получили t, ты можешь найти x делать:

x = (x4 - x0) * t      (asuming x4 > x0) 

Поэтому я искал какой-то метод, который позволил бы мне найти Y-координату на кубической кривой Безье, учитывая x-координату на ней.

Рассмотрим кубическую кривую Безье между точками (0, 0) и (0, 100) с контрольными точками в точках (0, 33) и (0, 66). Существует бесконечное число Y для данного X. Так что нет уравнения, которое решило бы Y при X для произвольного кубического Безье.

Для надежного решения вы, вероятно, захотите начать с алгоритма де Кастельжау

Разделите кривую рекурсивно, пока отдельные сегменты не приблизятся к прямой линии. Затем вы можете определить, пересекают ли эти различные отрезки линии ваш x или являются ли они вертикальными отрезками, x которых соответствует искомому вами x (мой пример выше).

Уравнение для кривой Безье (получение значения х):

Bx = (-t^3 + 3*t^2 - 3*t + 1) * P0x + 
     (3*t^3 - 6*t^2 + 3*t) * P1x + 
     (-3*t^3 + 3*t^2) * P2x + 
     (t^3) * P3x

Переставить в виде кубика т

0  = (-P0x + 3*P1x - 3*P2x + P3x) * t^3+ 
     (3*P0x - 6*P1x + 3*P2x) * t^2 + 
     (-3*P0x + 3*P1x) * t + 
     (P0x) * P3x - Bx

Решите это, используя кубическую формулу, чтобы найти значения для t. Может быть несколько реальных значений t (если ваша кривая дважды пересекает одну и ту же точку x). В моем случае я имел дело с ситуацией, когда для любого значения x было только одно значение y. Таким образом, я смог просто взять единственный реальный корень в качестве значения t.

a = -P0x + 3.0 * P1x - 3.0 * P2x + P3x;
b = 3.0 * P0x - 6.0 * P1x + 3.0 * P2x;
c = -3.0 * P0x + 3.0 * P1x;
d = P0x;
t = CubicFormula(a, b, c, d);

Затем поместите значение t обратно в кривую Безье для y

By = (1-t)^3 * P0x + 
     3t(1-t)^2 * P1x + 
     3t^2(1-t) * P2x + 
     t^3 * P3x
Другие вопросы по тегам