Пусть математика сложит сердца

в 7:28, , рубрики: Анимация и 3D графика, День святого Валентина, математика, метки: ,

Один и один — получается два. Все одиноки — здесь ты, а там я.
Люди всегда одиноки вдвойне сами с собою наедине.
Если б их что-то сблизить могло, сразу б из двух получилось одно.
Пусть математика сложит сердца — чтобы проделать нам путь до конца.

Уильямс Джей, «Герои Ниоткуда»

Вероятно, пост следовало назвать «Как нарисовать анимированное сердечко ко дню Святого Валентина, используя математику не по назначению». Я отверг это название в пользу более поэтичного: как-никак, надвигается замечательный романтический праздник, который мы, айтишники и прочие нёрды, должны встретить во всеоружии. Я сразу покажу вам результат, а под хабракатом будет много букв о том, как я этого результата достиг.

image

Дисклеймер

Я осознаю, что красивое мигающее сердечко можно сделать и без малейшего знания математики. Но разве это интересно?

Шаг 1. Параметризуем сердечко.

Для начала нам нужен математический объект, хотя бы отдалённо напоминающий сердечко. К счастью, для меня этот шаг был тривиален: ещё пару лет назад я обнаружил замечательную формулу как раз для такого случая (из эстетических соображений график на рисунке растянут по горизонтали, на самом деле он должен умещаться между -1 и 1).

image

Формула была обнаружена из следующий соображений: возьмём обыкновенную окружность (x = cos(t); y = sin(t)) и представим, что она состоит из желе, будучи при этом жёстко прикреплена к оси ординат. Теперь «подуем» на неё снизу: прибавим к координате игрек некую функцию w(x) = w(x(t)), равную нулю при x=0, монотонно возрастающую при x>0 и чётную по x. После такого «дуновения» половинки окружности сместятся вверх, образуя «выпуклости» сердечка, а благодаря жёсткому креплению к оси Y образуется нижний «хвостик» и верхняя «вмятинка». В данном случае w(x(t)) = |x|1/2 = |cos(t)|1/2. Можете самостоятельно попробовать другую «функцию дуновения» и посмотреть, что из этого выйдет.

Шаг 2. От параметрического задания к неявной функции.

Для нашего коварного плана параметрическое уравнение (x(t); y(t)) неудобно; предпочтительнее было бы неявное задание вида f(x, y) = 0. Что ж, всё в наших руках. Итак, брюки превращаются:

x = cos(t)
y = sin(t) + |cos(t)|1/2
y — |x|1/2 = sin(t)
(y — |x|1/2)2 + x2 = 1
f(x,y) = (y — |x|1/2)2 + x2 — 1 = 0

Шаг 3. От неявной функции к функции двух переменных. Функция цвета.

Имея на руках f(x,y), мы наконец можем осуществить свою мечту: нарисовать красивую цветную картинку. Для этого нам понадобится ещё одна функция: функция цвета. Она должна принимать вещественный аргумент r и возвращать целое значение от 0 до 255. Также желательно, чтобы она была монотонна и имела максимум в точке нуль. В качестве такой функции можно взять, например, эту:

c(r) = max([255 — 100*|r|], 0)

Здесь 100 — «магическое число», позднее мы его в полном соответствии с «хорошим стилем программирования» заменим параметром.
Теперь для каждой точки (x,y) мы можем задать цвет как rgb(c(f(x,y)), 0, 0). Те точки, которые раньше принадлежали непосредственно графику «сердечка», стали ярко-красными (обратите внимание на неподвижный светлый контур на гифке). По мере удаления от графика цвет будет тускнеть, пока на некотором расстоянии от него не станет чёрным.

Шаг 4. Добавляем параметр, создаём анимацию.

Теперь заменим магическое число 100 параметром k. Новая функция цвета выглядит так:

c(r, k) = max([255 — k*|r|], 0)

Меняя k с течением времени, мы можем получить смену кадров. В частности, чтобы добиться пульсирования сердца, я последовательно присваивал k значения 80, 90, 100, 110, 120, 110, 100, 90. Затем изображения, сгенерированные для этих значений, объединяются в GIF-анимацию.

Заключение

К сожалению, мне не удалось устроить сюрприз своей девушке: она коварно подкралась ко мне сзади как раз тогда, когда я генерировал кадры для анимации. Тем не менее, ей понравилось.
Художники, дизайнеры и прочие товарищи с обострённым чувством прекрасного наверняка скажут, что сердечко могло бы быть и покрасивее. Отчасти я с ними соглашусь: картинка не лишена недостатков. Однако её истинная красота — в математической строгости. Моя девушка это оценила. А вы?

Автор: Sirion

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js