Визуализация изменения климата при помощи интерактивного генеративного искусства

JavaScriptАлгоритмыCanvasВизуализация данныхЭкология
Автор оригинала: Mariana Mysak, R&D engineer at ELEKS

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

Тему изменения климата нужно раскрывать со всех сторон - от громких и массовых событий до еле заметных и волнующих персонально человека. Акцент на распространение информации о «виновниках» изменения климата на всех уровнях даёт шанс обществу повысить осведомлённость об этом явлении. Для повышения осведомлённости нужно использовать разнообразные инструменты.

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

Интерактивное генеративное искусство - едва заметное, но влиятельное

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

И поэтому мы подумали о создании «живого окна», которое показывает погоду и её изменение. Мы решили создать веб-приложение, которое будет показывать нынешние погодные условия, используя природный ландшафт, созданный путём вычислений, но в то же время с внутренней эстетикой. Другими словами, при помощи генеративного искусства.

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

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

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

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

Для реализации этого проекта использовался JavaScript, визуальные элементы нарисованы при помощи Canvas. Ландшафт состоит из четырёх главных компонентов: дерево, земля, небо и осадки. Этого достаточно, чтоб показать времена года и основные погодные условия.

Дерево

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

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

Крона дерева не однородна, как, например, сфера, а состоит как бы из групп сфер. В результате цвета листьев разные, ибо некоторые из них темнее, а некоторые светлее. Поэтому крона поделена на две части, а каждая группа прокрашена слева направо плавной палитрой, переходящей от самых ярких к самым тёмным цветам. Функция divide(start,finish,intervalsAmount,n) делит числовой интервал между start и finish на сумму интервала intervalsAmount, и определяет интервал, включающий n.

const branchGroupDepth = 10; 
const leavesGroupSize = 2 ** (branchGroupDepth-1); 
let groupCounter = 0; 
function generate(angle, depth, arr) 
{ let leafColor = colors[divide(0, leavesGroupSize, colors.length, groupCounter)]; 
arr.push({ 
angle, 
branchArmLength: random(minBranchLenght, maxBranchLenght), 
color: leafColor 
}); 
if (depth === branchGroupDepth) { groupCounter = 0; } 
if (depth === 0) { groupCounter++; } 
if (depth != 0) { 
if (depth > 1) { generate(angle - random(minAngle, maxAngle), depth - 1, arr); generate(angle + random(minAngle, maxAngle), depth - 1, arr); 
} else { 
generate(angle, depth - 1, arr); }}}

Задача функции branch() - заставить деревья выглядеть живыми, она высчитывает координаты веток каждый раз, когда ветер меняется. Каждая ветка двигается по круговой траектории, где начало ветки обозначено центром круга, а длина - радиусом. Единственное, что нам нужно найти - координаты конца ветки (которые ещё и являются началом следующих веток).

windSidewayForce - направление движения ветки по направлению ветра.

bendabilityOfCurrentBranch - коэффициент наклона ветки по ветру, зависящий от толщины ветки (или глубины дерева).

calcX(angle, r)/calcY(angle, r) — функции, которые вычисляют координаты концов веток при помощи формулы rcos(angle)/rsin(angle).

let branchCounter = 0; 
const bendability = 2; 
const leafBendability = 17; 
function branch(x1, y1, arr, depth, windConfig) { 
if (depth != 0) { 
const xx = calcX(dir, depth * branchArmLength); 
const yy = calcY(dir, depth * branchArmLength); 
const windSidewayForce = windX * yy - windY * xx; 
const bendabiityOfCurrentBranch = (1 - (depth * 0.7) / (maxDepth * 0.7)) ** bendability; 
dir = angle + wind * bendabiityOfCurrentBranch * windSidewayForce; let x2 = x1 + calcX(dir, depth * branchArmLength); 
let y2 = y1 + calcY(dir, depth * branchArmLength); 
lines[depth].
ush([x1, y1, x2, y2]); 
if (depth > 1) { 
branch(x2, y2, arr, depth - 1, windConfig); 
branch(x2, y2, arr, depth - 1, windConfig); 
} else { 
branch(x2, y2, arr, depth - 1, windConfig); 
} 
} else { 
const leafAngle = angle + wind * windSidewayForce * leafBendability; leaves[color].push([x1, y1, leafAngle]); 
} 
}

Ветки дерева прокрашиваются простой lineTo() канвас функцией, и каждая ветка - линия. Листья красятся двумя кривыми Безье при помощи функции bezierCurveTo(). Кривые Безье состоят из трёх точек: начало (синяя), конец (синяя) и контроль (жёлтая). Последняя придаёт кривой форму.

Покраска листьев кривыми Безье
Покраска листьев кривыми Безье

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

Земля

Земля (или, скорее, трава) не менее важна, чем дерево, ибо трава может показывать ветер и времена года. Нужен массив столбцов, чтобы сгенерировать траву. Каждый столбец травы должен иметь свои координаты, обозначающие положение в поле, скорость реакции на ветер и угол наклона по отношению к земле. Более близкие столбцы травы должны иметь более насыщенный и контрастный цвет, а дальние должны казаться более сглаженными. Эта визуальная хитрость даёт ощущение травяного поля. Поле поделено на горизонтальные части, у каждой части свой цвет столбцов. После генерации массива поле нужно отсортировать от самых дальних до близких по y координате для эффекта наложения друг на друга.

function generate(number) { 
for (var i = 0; i < number; i++) { 
var y = random(fieldTopStart, h + fieldBottomDeviation); 
var x = random(0, w); 
var colorGroup = divide(fieldTopStart, h + fieldBottomDeviation + 1, fieldAreas, y); 
var color = colors[colorGroup][random(0, colors[colorGroup].length)]; 
var angle = random(-maxAngleDeviation, maxAngleDeviation); 
var speed = random(minSpeed, maxSpeed); 
dots.push([x, y, color, angle, speed]); 
} 
dots.sort()}

Столбец травы, как и листья, красится двумя кривыми Безье. К тому же, трава реагирует на ветер наклоном. Координаты конца столбца и контрольные точки вычисляются согласно индикатору ветра.

Столбец травы красится двумя кривыми Безье
Столбец травы красится двумя кривыми Безье

Небо и осадки

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

Облака содержат в себе круги двух типов. Первый тип - градиентные белые круги с градиентным центром в середине. Эти круги распределены равномерно по всей плоскости облака. Второй тип - градиентные серые круги со смещением вниз от центра. Они размещаются внизу плоскости облака и делают облако объёмным. Однако, облака перемещаются не только по небу, а ещё и внутри самих себя, меняя форму. Каждый круг динамичен и двигается по круговой траектории со своим центром.

Ещё один важный элемент неба - это осадки: снег и дождь. Капли дождя красятся простой вертикальной линией, а их толщина зависит от силы дождя. Снежинки красятся градиентым полупрозрачным кругом. У каждой снежинки свой размер, и чем больше она, тем быстрее падает. Это создаёт эффект, будто большие снежинки находятся ближе к экрану.

Как выглядит генеративное искусство, основанное на погоде?

После некоторых манипуляций, включающих использование разных цветов для разных времён года и интеграцию с «живыми» данными, мы можем показать через «живое окно» весь год.

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

Ещё один полезный аспект - то, что через «живое окно» можно показать рост растений. Было бы интересно увидеть, сколько времени нужно определённым растениям для достижения зрелости. Есть ещё шкала Бофорта, которая показывает силу ветра. Она может показывать, как сильно ветер влияет на деревья, давая пользователю реалистичное восприятие силы ветра.

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

Популярные посты по генеративному искусству:

Теги:глобальное потеплениевизуализация погодыгенеративное искусствоgenerative art
Хабы: JavaScript Алгоритмы Canvas Визуализация данных Экология
+7
1,2k 15
Комментировать

Похожие публикации

Javascript Developer
от 75 000 до 150 000 ₽WebLab TechnologyМожно удаленно
Senior Frontend
от 200 000 ₽AaplyМожно удаленно
Senior Node.js Engineer (Cube.js Core)
от 6 000 $Cube.jsМожно удаленно
Frontend-разработчик (Pixi+React)
от 120 000 ₽ZetaSoftМожно удаленно
Frontend Game Senior Developer
от 150 000 ₽Beem CasinoМоскваМожно удаленно

Лучшие публикации за сутки