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

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

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

Что такое кривая Безье?

Кривые Безье — это параметрические кривые (с параметром t, изменяющимся от 0 до 1), которые определяются набором контрольных точек. Положения этих точек по отношению друг к другу определяют форму кривой.

Если вы когда-либо использовали программное обеспечение для редактирования графики, такое как Adobe Illustrator или Figma, вы уже видели эти контрольные точки в действии. Обратите внимание на гифку ниже, как по мере перемещения точек форма кривой меняется соответствующим образом.

Вы также можете использовать столько контрольных точек, сколько захотите. Чем больше контрольных точек вы добавите, тем больше у вас будет контроля над окончательной формой кривой. Например, функция cubic-bezier в CSS использует кривую Безье с 4 точками (следовательно, кубическую), описывающую эволюцию вашей анимации.

Что происходит?

Это здорово и все такое, но как нам получить кривую, просто расположив кучу точек вокруг?

Ответ на этот вопрос кроется в математической основе кривых Безье — полиномах Бернштейна. Полином Бернштейна степени n определяется как сумма базисных полиномов Бернштейна, каждый из которых умножается на коэффициент Бернштейна.

Не зацикливайтесь на этих формулах, есть только несколько ключевых моментов, которые вам нужно извлечь из них.

Во-первых, какова их цель? Короче говоря, полиномы Бернштейна впервые использовались как способ аппроксимации любых реальных непрерывных функций в пределах замкнутого интервала (подробнее см. Теорему Стоуна-Вейерштрасса). Другими словами, используя эти полиномы, мы можем аппроксимировать практически любую функцию (моделировать любую кривую), которую захотим. Это действительно полезно, так как полиномы, как правило, гораздо проще вычислять и манипулировать ими, чем другими типами функций.

Во-вторых, как именно происходит это приближение? Помните коэффициенты Бернштейна? Это их работа! Обратите внимание, что в формуле базисные полиномы всегда одни и те же (они различаются только в зависимости от степени n) — коэффициент действительно аппроксимирует целевую функцию. Точная формула для аппроксимации функции f выглядит следующим образом:

Итак, что же такое кривая Безье? Это полином Бернштейна, где коэффициенты Бернштейна являются контрольными точками! Итак, при построении кривой Безье мы, по сути, аппроксимируем реальную функцию! Это прямое применение полиномов Бернштейна.

Это то, что известно как явное/математическое определение кривой Безье. Есть еще один способ взглянуть на кривые Безье, который я считаю более мощным и интуитивно понятным. Именно его мы и рассмотрим сейчас.

Другой подход

Есть несколько известных форм кривых Безье, каждая из которых различается по степени (сколько у нее контрольных точек). Это линейная, квадратичная и кубическая кривые Безье. Изучая эту тему, вы наверняка встретите их формулы, которые можно получить, применив формулу, основанную на полиномах Бернштейна.

Опять же, не зацикливайтесь на этих формулах. Есть только одна ключевая вещь, которую вам нужно взять у них.

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

Образец (1-t)и tумножает что-то повторяющееся. Мы представляем квадратичную кривую P0P1P2 как (1-t) * (Безье(P0P1)) + t * (Безье(P1P2))(вернемся к предыдущему изображению с различными типами кривых Безье и обратите внимание на линии, соединяющие контрольные точки). Вы можете проверить это на более высоких кривых и убедиться, что это работает. Отсюда мы получаем новый рекурсивный способ определения кривой Безье:

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

Представьте, что мы пытаемся вычислить точку t=0,5 на квадратичной кривой Безье. Мы только что видели, что эту кривую можно представить в виде двух линейных кривых Безье с концами в точках P0, P1 и P1, P2. Подставляя 0,5 в нашу новую рекурсивную формулу, мы вычисляем t=0,5 в линии P0P1, затем в P1P2 — что даст нам две новые точки — , чтобы затем соединить эти две промежуточные точки другой линией ( помните, что у нас есть (1-t) и tумножение меньших градусных кривых) и вычислите конечное положение t=0,5.

Позвольте мне дать вам визуализацию того, что происходит:

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

Понимание этого важно, потому что это объяснение специальной темы, которая всегда возникает при изучении кривых Безье: Алгоритм де Кастельжо.

Алгоритм де Кастельжо

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

Поэтому, учитывая, что каждая точка на уровне 0 сама является контрольной точкой, и рассматривая произвольную точку Pi на уровне j, алгоритм де Кастельжо говорит нам, что ее значение будет:

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

Почему кривые Безье?

Учитывая все, что мы сказали о кривых Безье, что в них такого особенного? Почему мы так часто их используем?

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

Возьмите яркий пример типографики. Кривые Безье позволяют нам создавать самые разные шрифты, от простых моноширинных до красивых экранных!

Окончательный обзор

Подводя итог всему, что мы узнали в этой статье:

  • Кривые Безье — это параметрические кривые, которые определяются набором контрольных точек.
  • Их математическое происхождение происходит от многочленов Бернштейна, которые представляют собой способ аппроксимации реальных функций.
  • Кривые Безье представляют собой многочлены Бернштейна, в которых контрольные точки заменяют коэффициенты Бернштейна.
  • Кривые Безье рекурсивны, и каждую точку Безье с Pn точками можно представить как линейную интерполяцию (линию) кривых Безье P0Pn-1 и P1Pn.
  • Алгоритм де Кастельжо по существу использует это рекурсивное соотношение для вычисления произвольной точки кривой Безье.
  • Кривые Безье действительно полезны, потому что их можно бесконечно масштабировать, и они позволяют нам создавать практически любую кривую, которую мы хотим.