Кривые Безье — это способ определения кривой по опорным точкам.
Для наглядности можно рассматривать их как график передвижения точки от начала до конца маршрута в зависимости от времени движения.
Время изменяется от 0 до 1 (до 100%). То есть мы изначально знаем время, за которое нужно переместиться из начальной точки (P0) в конечную (Pn) (конкретная величина не имеет значения). На основании этого времени можно вычислить точную траекторию — по формулам.
Берем все время за 100% (или за единицу). В момент 0 (0%) точка находится в точке P0, в момент 1 (100%) – в точке Pn. Положение точки в любой момент между этими моментами можно вычислить по формуле.
Порядок кривой всегда на 1 меньше количества контрольных точек. Рассмотрим построение пошагово, начиная с самой простой кривой.
Кривая Безье первого порядка
Простейшая кривая Безье — это обычная линия. Порядок первый – значит, контрольных точек две. Ее академическое уравнение выглядит так:
B(t) = (1-t)*P0 + t*P1
А график — вот так:
Разберем на простейшем примере. Пусть:
- первая контрольная точка — P0 имеет координаты (0; 0),
- вторая (и последняя) – P1 – (5; 0).
Сразу же проверим формулу.
При t = 0
(в начальный момент времени) должна получиться точка P0, а при t = 1
должна получиться точка P1.
- B(0) = (1-0)*P0 + 0*P1 = P0 — (0; 0)
- B(1) = (1-1)*P0 + 1*P1 = P1 — (5; 0)
А теперь найдем несколько точек между началом и концом. Тут используется сложение и умножение векторов, но в данном случае все интуитивно понятно:
B(0.1) = (1-0.1)*P0 + 0.1*P1 = 0.9*P0 + 0.1*P1 = 0.9*(0;0) + 0.1*(5;0) = (0.5; 0)
B(0.2) = (1-0.2)*P0 + 0.2*P1 = 0.8*P0 + 0.2*P1 = 0.8*(0;0) + 0.2*(5;0) = (1; 0)
B(0.3) = (1-0.3)*P0 + 0.3*P1 = 0.7*P0 + 0.3*P1 = 0.7*(0;0) + 0.3*(5;0) = (1.5; 0)
B(0.4) = (1-0.4)*P0 + 0.4*P1 = 0.6*P0 + 0.4*P1 = 0.6*(0;0) + 0.4*(5;0) = (2; 0)
B(0.5) = (1-0.5)*P0 + 0.5*P1 = 0.5*P0 + 0.5*P1 = 0.5*(0;0) + 0.5*(5;0) = (2.5; 0)
B(0.6) = (1-0.6)*P0 + 0.6*P1 = 0.4*P0 + 0.6*P1 = 0.4*(0;0) + 0.6*(5;0) = (3; 0)
B(0.7) = (1-0.7)*P0 + 0.7*P1 = 0.3*P0 + 0.7*P1 = 0.3*(0;0) + 0.7*(5;0) = (3.5; 0)
B(0.8) = (1-0.8)*P0 + 0.8*P1 = 0.2*P0 + 0.8*P1 = 0.2*(0;0) + 0.8*(5;0) = (4; 0)
B(0.9) = (1-0.9)*P0 + 0.9*P1 = 0.1*P0 + 0.9*P1 = 0.1*(0;0) + 0.9*(5;0) = (4.5; 0)
Все полученные точки лежат на одной прямой – это и есть кривая Безье первого порядка.
Время идет, точка движется от старта к финишу. И в любой момент времени мы точно знаем, где она находится.
Кривые Безье второго порядка и больше
В определении кривых Безье выше первого порядка кроме начала и конца появляются дополнительные опорные точки, смысл которых сложно понять с первого захода.
Непосредственно через них кривая не проходит, так зачем же они нужны?
На самом деле эти точки определяют направление движения (направление изгиба кривой) и крутизну этого изгиба.
Квадратичная кривая
Кривая Безье второго порядка, или квадратичная, задается тремя контрольными точками:
- P0 – начало;
- P2 – конец;
- P1 – вспомогательная точка, определяющая изгиб кривой.
Маленький спойлер: кривая Безье второго порядка имеет форму параболы (не обязательно симметричной).
Формула у нее вот такая:
B(t) = (1 - t)2*P0 + 2t*(1 - t)*P1 + t2*P2
Проверим, что в начале и конце движения мы окажемся в точках P0 и P2 соответственно:
- B(0) = (1 — 0)2 *P0 + 2*0*(1 — 0) * P1 + 02*P2 = P0
- B(1) = (1 — 1)2 *P0 + 2*1*(1 — 1) * P1 + 12*P2 = P2
На примере:
- P0 (-1; 0)
- P2 (1; 0)
- опорная точка P1 (0; 2):
Найдем, где будет точка через половину времени t (0.5):
B(0.5) = 0.25*P0 + 0.5*P1 + 0.25*P2 = (-0.25; 0) + (0; 1) + (0.25; 0) = (0; 1)
То есть на половине временного интервала мы окажемся в точке (0; 1)
.
Если найти еще несколько точек, вырисуется ровная парабола. Так, в общем, и было задумано для простоты вычислений и визуальной ясности.
Рекурсивность кривых Безье
Волшебство кривых Безье заключается в том, что они рекурсивны. То есть умея строить кривую первого порядка, мы можем построить и квадратичную кривую, даже не зная ее формулы.
Вернемся к предыдущему примеру:
- P0 (-1; 0)
- P2 (1; 0)
- опорная точка P1 (0; 2):
Предположим, что мы не знаем, как построить кривую второго порядка между P0 и P2. Но мы можем построить простейшую кривую первого порядка между P0 и P1, а также между P1 и P2, пользуясь формулой:
B(t) = (1-t)*P0 + t*P1
Для каждого момента времени мы можем найти положение точки на каждой из этих кривых.
Например, в момент времени 0.25
соответствующие точки Q0 и Q1 будут в таких позициях:
Между этими точками тоже можно построить кривую первого порядка.
Магия заключается в том, что точка на этой кривой в момент времени t = 0.25
соответствует точке на искомой кривой второго порядка в этот же момент времени.
Распишем чуть подробнее.
Мы хотим найти точку на кривой второго порядка P0-P11-P2 в момент времени t
.
- Этому моменту на кривой P0-P1 соответствует точка Q0;
- А на кривой P1-P2 – точка Q1.
Искомая точка – это точка на кривой Q0-Q1, соответствующая моменту времени t
.
Этот рекурсивный алгоритм построения кривой Безье носит имя Поля де Кастельжо.
Кубическая кривая
Кривая Безье третьего порядка, или кубическая кривая, определяется уже четырьмя опорными точками – началом, концом и двумя вспомогательными, через которые она не будет непосредственно проходить.
Две вспомогательные точки снова определяют направление и крутизну изгибов кривой.
Формула кубической кривой еще сложнее:
B(t) = (1 - t)3*P0 + 3t*(1-t)2*P1 + 3t2*(1 - t)*P2 + t3*P3
Вы можете попробовать эту кривую рассчитать самостоятельно.
Обратите внимание, ее тоже можно получить рекурсивно!
Найти точку кривой третьего порядка в момент времени t
можно по следующему алгоритму:
- Строим кривые первого порядка P0-P1, P1-P2, P2-P3
- Находим на них соответствующие t точки Q0, Q1, Q2
- Строим кривые первого порядка Q0-Q1 и Q1-Q2
- Находим на них соответствующие t точки R0 и R1
- Строим кривую первого порядка R0-R1
- Находим на ней точку, соответствующую
t
.
Зачем все это нужно?
Круто, теперь мы умеем строить кривые Безье любого порядка, но зачем нам это нужно? Каково практическое применение этих построений?
Кривые Безье используются в описаниях шрифтов TrueType, в SVG, GIMP и других графических форматах, в 3D-графике. Они используются даже в CSS для описания плавности анимации.
В общем, штука очень полезная.
1 комментарий