Сколько математики ушло на рисование сердечек.

Мой друг скоро женится, и мы хотели сделать что-нибудь творческое в подарок. Мы хотели создать что-то, включающее небольшой цветной экран, показывающий мотивирующие цитаты, связанные с браком. Я подумал, что было бы весело добавить анимированную графику. Какую графику вы включаете в свадебный подарок? Конечно же, сердца! Я хотел создать анимацию черного экрана с красным сердцем, которое растет, пока не заполняет весь экран.

Перво-наперво, давайте поговорим об оборудовании. Я решил использовать arduino uno, потому что он дешевый (то есть эти китайские клоны) и простой. Для экрана я сделал следующее:

Экран дороговат, но симпатичный и маленький, есть подсветка, 128х128 точек и 65 тыс. Цветов. Он поставляется с считывателем micro-sd и подключается через SPI к Arduino. Для этого экрана доступна библиотека arduino, а у adafruit есть отличное руководство по ее использованию.

Так как же нам показать сердца этого плохого парня? Ну, моей первой идеей было использовать растровые изображения. Библиотека arduino предоставляет хороший пример, который загружает растровое изображение с SD-карты и показывает его. Однако, если вы посмотрите на код, вы увидите, что он обрабатывает растровое изображение пиксель за пикселем. Для нашего маленького ардуино это много работы! Загрузка полноэкранного растрового изображения заняла около секунды. Слишком медленно для любых анимаций.

Итак, что у нас осталось, так это рисование сердечек по старинке: с помощью функций рисования, предоставляемых библиотекой. Чтобы создать анимацию, я хотел иметь функцию, которая могла бы рисовать сердце в любом месте, размере и цвете.

Итак, какие примитивные формы составляют сердце? Ну для верха вам понадобятся два перекрывающихся круга. Внизу это похоже на треугольник. Что-то вроде этого

Вот как выглядит моя функция:

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

Это сработало! Здорово! Сделанный? Нет! Настраивая параметры, я пришел к выводу, что моя интерпретация формы сердца была немного неправильной. Прямая линия треугольника не совпадает с изогнутой линией круга. Как это исправить? нарисовав треугольник ниже. Идеальной высотой кажется высота нижнего пересечения двух окружностей.

Итак, как нам рассчитать положение этого пересечения? Что ж, здесь и появляется наш герой Пифагор. Давайте внимательнее посмотрим на этот левый кружок.

Итак, на этом рисунке h - это центр формы сердца, точка c - центр левого круга, а i - точка мы хотим найти: где два круга перекрываются. Мы знаем, что i находится непосредственно под h, а точка c находится непосредственно рядом с h, поэтому h - угол 90 градусов. Мы хотим знать длину стороны a. Мы знаем, что сторона c - это радиус круга, мы это уже вычислили. Мы знаем, что b - это радиус за вычетом некоторого перекрытия, мы также вычислили это в переменной circleDistance). Итак, давайте сделаем это в стиле старшей школы:

Итак, вот полная функция в коде:

Когда я использую это в анимации, частота кадров все еще невелика, вы можете видеть круги, нарисованные перед треугольником. Но эффект выглядит круто, поэтому я считаю это победой Пифагора!

Немного поигравшись с параметрами, я решил установить перекрытие в 0,1 раза больше общей ширины, а хвост в 0,6 раза больше общей ширины.

Распространять любовь!