en.javascript.info/3-more/2-animation/2-bezier/article.md
2015-01-20 18:27:28 +03:00

12 KiB
Raw Blame History

Кривые Безье

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

Тему эту стоит изучить, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом. [cut]

Виды кривых Безье

Кривая Безье задаётся опорными точками.

Их может быть две, три, четыре или больше. Например:

По двум точкам По трём точкам По четырём точкам

Если вы посмотрите внимательно на эти кривые, то "на глазок" заметите:

  1. **Степень кривой равна числу точек минус один**. На рисунках выше, соответственно, получаются для двух точек -- линейная кривая (прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая.
  2. **Кривая всегда находится внутри [выпуклой оболочки](http://ru.wikipedia.org/wiki/%D0%92%D1%8B%D0%BF%D1%83%D0%BA%D0%BB%D0%B0%D1%8F_%D0%BE%D0%B1%D0%BE%D0%BB%D0%BE%D1%87%D0%BA%D0%B0), образованной опорными точками:**

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

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

Попробуйте двигать точки мышью в примере ниже:

[iframe src="demo.svg?nocpath=1&p=0,0,0.5,0,0.5,1,1,1" height=370]

Как можно заметить, кривая натянута по касательным 1 -> 2 и 3 -> 4.

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

Вот некоторые примеры:

Математика

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

Координаты кривой описываются в зависимости от параметра t⋲[0,1]

  • Для двух точек:

    [pre] P = (1-t)P1 + tP2 [/pre]

  • Для трёх точек:

    [pre] P = (1t)2P1 + 2(1t)tP2 + t2P3 [/pre]

  • Для четырёх точек:

    [pre] P = (1t)3P1 + 3(1t)2tP2 +3(1t)t2P3 + t3P4 [/pre]

Эти уравнения -- векторные, т.е. вместо Pi нужно подставить координаты i-й опорной точки (xi, yi).

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

Рисование "де Кастельжо"

Метод де Кастельжо идентичен математическому определению кривой и наглядно показывает, как она строится.

Посмотрим его на примере трех точек (точки можно двигать). Нажатие на кнопку "edit" запустит демонстрацию.

[iframe src="demo.svg?p=0,0,0.5,1,1,0&animate=1" height=370]

Алгоритм построения "де Кастельжо":

  1. Строятся отрезки между опорными точками 1-2-3. На рисунке выше они **чёрные**.
  2. Параметр `t` пробегает значения от `0` до `1`. В примере выше использован шаг `0.05`, т.е. в цикле `0, 0.05, 0.1, 0.15, ... 0.95, 1`.

    Для каждого значения t:

    1. На каждом из этих отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. То есть, при `t=0` -- точка будет в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце. Так как **чёрных** отрезков -- два, то и точек выходит две штуки.
    2. Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён синим.
      При `t=0.25`При `t=0.5`
    3. На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` получаем точку в конце первой четверти отрезка, для `t=0.5` -- в середине отрезка. На рисунке выше эта точка отмечена красным.
  3. По мере того как `t` пробегает последовательность от `0` до `1`, каждое значение `t` добавляет к кривой точку. **Совокупность таких точек для всех значений `t` образуют кривую Безье.**
**Это был процесс для построения по трём точкам. Но то же самое происходит и с четырьмя точками.**

Демо для четырёх точек (точки можно двигать):

[iframe src="demo.svg?p=0,0,0.5,0,0.5,1,1,1&animate=1" height=370]

Алгоритм:

  • Точки по порядку соединяются отрезками: `1-2`, `2-3`, `3-4`. Получается три чёрных отрезка.
  • На отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается два зелёных отрезка.
  • На этих отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается один синий отрезок.
  • На синем отрезке берётся точка, соответствующая текущему `t`. При запуске примера выше она красная.
  • Эти точки описывают кривую.

Нажмите на кнопку "edit" в примере выше, чтобы увидеть это в действии.

Ещё примеры кривых:

[iframe src="demo.svg?p=0,0,0,0.75,0.25,1,1,1&animate=1" height=370]

С другими точками:

[iframe src="demo.svg?p=0,0,1,0.5,0,0.5,1,1&animate=1" height=370]

Петелька:

[iframe src="demo.svg?p=0,0,1,0.5,0,1,0.5,0&animate=1" height=370]

Пример негладкой кривой Безье:

[iframe src="demo.svg?p=0,0,1,1,0,1,1,0&animate=1" height=370]

Аналогичным образом могут быть построены кривые Безье и более высокого порядка: по пяти точкам, шести и так далее. Но обычно используются 2-3 точки, а для сложных линий несколько кривых соединяются. Это гораздо проще с точки зрения поддержки и расчётов.

[smart header="Как провести кривую через нужные точки?"] Этот вопрос не связан с кривыми Безье, но он иногда возникает в смежных задачах.

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

Как правило, в компьютерной графике для интерполяции используют кубические кривые, соединённых гладким образом. Вместе они выглядят как одна кривая. Это называется интерполяция сплайнами. [/smart]

Итого

Кривые Безье задаются опорными точками. Мы рассмотрели два определения кривых:

  1. Через математическую формулу.
  2. Через процесс построения де Кастельжо.

С их помощью можно описать почти любую линию, особенно если соединить несколько.

Применение:

  • В компьютерной графике, моделировании, в графических редакторах. Шрифты описываются с помощью кривых Безье.
  • В веб-разработке -- для графики на Canvas или в формате SVG. Кстати, все живые примеры выше написаны на SVG. Фактически, это один SVG-документ, к которому точки передаются параметрами. Вы можете открыть его в отдельном окне и посмотреть исходник: demo.svg.
  • В CSS-анимации, для задания временной функции.