Кривые Безье - отличные инструменты для представления кривизны и имеют множество приложений, таких как компьютерная графика, шрифты и анимация. Если вы раньше имели дело с CSS, вы, вероятно, сталкивались с кривыми Безье. Например, в CSS вы можете использовать функцию времени, выраженную в виде кривой Безье, как показано выше, где ось x - это время, а ось y - расстояние.

Зачем их использовать?

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

Было бы неплохо, если бы мы могли вызывать функцию 100 раз, каждый раз собирая очки. Давайте создадим сигнатуру метода для функции нашей мечты:

/**
 * @param {Number} t Number from 0 to 1.
 * @return {Array} Point on the curve
 */
function getCurveLocation(t) { ... }

Функция принимает число от 0 до 1 и s. После того, как нас попросят нарисовать 100 точек, мы вызовем getCurveLocation 100 раз с равномерно распределенными значениями.

var points = []
for(var i = 0; i <= 100; i++) {
 points.push(getCurveLocation(i * .01))
}

Все готово. С помощью этой настройки мы можем представить нашу кривую в произвольном количестве пикселей, то есть сделать масштабирование действительно просто - мы просто увеличим или уменьшим количество циклов, чтобы получить желаемое количество пикселей, а затем отобразить на экране.

Определение

Как работает getCurveLocation? Вот где в игру вступают кривые Безье. Общее определение следующее:

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

B - это функция, которая принимает число t от 0 до 1 и возвращает точку на кривой.

Σ - это цикл, суммирующий каждую итерацию. n представляет собой степень кривой Безье. Чем выше степень, тем более сложные формы вы можете сделать. В большинстве случаев квадратичный (2) и кубический (3) - это все, что вам нужно. i - целое число от 0 до полиномиальной степени, которое будет увеличивать каждый цикл.

Представляет биномиальные коэффициенты. Если мы развернули бином, например (x + y) ^ n, число перед каждым термином будет соответствовать выражению. Здесь мы можем сократить путь. Независимо от бинома, например, если n = 3 и i = 2, мы можем быстро вычислить это выражение, не расширяя все с помощью комбинаторики - сколькими способами мы можем выберите 2 элемента из набора 3 элементов - или мы могли бы взглянуть на Треугольник Паскаля, сосредоточив внимание на 4-й строке и 3-й срок.

Представляет конкретный член в многочлене. Пи - это контрольная точка.

Интуиция

Давайте создадим кривую Безье со следующими точками, взятыми из примера в начале:

P0 = (0,0)
P1 = (.2, .8)
P2 = (.9, .6)
P3 = (1, 1)

Поскольку имеется 4 точки, мы получим кубическую кривую Безье - степень порядка 3. Следовательно, 𝝨 сделает 4 цикла. Давайте опишем каждый цикл и вспомним, что 𝝨 выполняет итерацию и суммирует. Таким образом, результатом является конкатенация каждого цикла.

В качестве ориентира, вот треугольник Паскаля, чтобы мы могли легко найти коэффициенты:

Петля 1:

Цикл 2:

Цикл 3:

Петля 4:

Конечный многочлен:

Давайте построим это уравнение, подставив точки вместо P.

Вы можете подумать, что эта кривая не слишком полезна, но значимая часть находится в области от 0 до 1.

Это должно показаться знакомым - это кривая Безье, которую мы использовали в начале статьи. Наличие домена от 0 до 1 имеет решающее значение, потому что при этих двух значениях происходят интересные вещи. Давайте посмотрим на многочлен при t = 0

Получаем первую точку! Давайте посмотрим на многочлен при t = 1

Получили последний балл! Независимо от того, где находятся первая и последняя точка, t = 0 всегда будет возвращать первую точку, а t = 1 всегда будет возвращать последнюю точку. Это действительно мощно, потому что независимо от того, насколько сложным становится наш многочлен, мы можем легко проанализировать, где начинается и заканчивается путь. Любое другое значение t не отменяет условия так хорошо. Тем не менее, мы все еще можем интуитивно понять, что происходит, когда мы меняем два других пункта. Например, здесь мы меняем вторую точку, P1.

Когда P1 увеличивается, кривая изгибается вверх. Однако вначале он изгибается быстрее, чем в конце. Мы могли бы взять частную производную по отношению к P1, чтобы доказать это, но давайте сосредоточимся на уравнении, в котором, по нашему мнению, оно меняется быстро, а где, по нашему мнению, оно меняется медленно:

Давайте посмотрим, где он быстро изгибается, t = 0,25

Очевидно, что P1 имеет большее влияние на поведение кривой, чем P2. Теперь посмотрим на t = 0,75.

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

В этой статье мы использовали кубические кривые Безье в качестве примеров, но то же самое можно применить и к другим кривым Безье. Например, квадратичная кривая Безье имеет три точки - две конечные точки и контрольную точку:

Кривая изменяется более симметрично по мере изменения P1 благодаря меньшему количеству контрольных точек. Также, когда P1 становится коллинеарным с конечными точками, мы получаем прямую линию. Я оставлю это явление для вас. Надеюсь, вы получили некоторое представление о кривых Безье. Они очаровывают меня, потому что представляют собой мощные уравнения с чистым API - простым вводом от 0 до 1 - и простым ответом - расположение на кривой.