Знамя Победы
Аэродинамическое моделирование полотна
Введение
Движение полотна на ветру — завораживающее физическое явление, объединяющее аэродинамику, волновую теорию и вычислительную математику. В данном примере представлена математическую модель распространения волн в гибком полотне, закреплённом с одного края (имитация флагштока).
В основе модели лежит суперпозиция гармонических составляющих: продольной бегущей волны, её второй гармоники и поперечной волны. Амплитуда волн плавно затухает у закреплённого края, имитируя реальное поведение ткани. Для высокопроизводительной 3D-визуализации используется библиотека GLMakie, что позволяет достичь плавной анимации даже на сетках высокого разрешения.
Вы можете загрузить любое изображение — от государственного флага до произведения искусства — и увидеть, как оно «оживает» под воздействием цифрового ветра, настраивая параметры скорости, частоты и интенсивности волн.
Используемые библиотеки
Присоединим необходимые библиотеки. Для создания трёхмерной графической анимации с текстурой, нам понадобится библиотека GLMakie.
using Images, FileIO, LinearAlgebra, GLMakie
Функция визуального моделирования
Данная функция принимает текстуру и геометрические параметры полотна, создавая трёхмерную координатную сетку заданного разрешения. На каждом временном шаге вычисляется новое вертикальное смещение каждой вершины как суперпозиция бегущих продольной и поперечной волн с экспоненциальным затуханием у закреплённого края. Волновое поле параметризуется амплитудой, частотой и скоростью распространения, что позволяет моделировать широкий диапазон ветровых условий — от полного штиля до штормового ветра.
function аэродинамическое_моделирование_полотна(текстура, Ширина, Высота, nx, ny, квс, амплитуда, частота, скорость, время, модель)
изображение = load(текстура)
изображение = rot180(изображение)
изображение = reverse(изображение, dims=2)
x = range(0, Ширина, length=nx)
y = range(0, Высота, length=ny)
X = repeat(reshape(x, 1, :), ny, 1)
Y = repeat(y, 1, nx)
шаг_времени = 1/квс
число_кадров = floor(Int, время / шаг_времени)
X_данные = X
Z_данные = Y .- 0.7
фигура = GLMakie.Figure(size=(800, 600))
оси = GLMakie.Axis3(фигура[1, 1], aspect=(1, 1, 1), limits=((0, Ширина), (0.5, 1.5), (-2.5, 2.0)))
оси.xspinesvisible = false
оси.yspinesvisible = false
оси.zspinesvisible = false
GLMakie.hidedecorations!(оси)
GLMakie.hidexdecorations!(оси, grid=false)
GLMakie.hideydecorations!(оси, grid=false)
GLMakie.hidezdecorations!(оси, grid=false)
Y_данные = ones(size(X))
полотно = GLMakie.surface!(оси, X_данные, Y_данные, Z_данные, color = изображение, backlight = 0.0, alpha = 0.85, shading = false)
GLMakie.lines!([0.0, 0.0], [1.0, 1.0], [-2.0, Высота - 0.7], linestyle = :solid, linewidth = 3, color = GLMakie.RGB(0.5, 0.5, 0.5), label = "")
камера = оси.scene.camera_controls
GLMakie.update_cam!(оси.scene, камера, GLMakie.Vec3f(30, 0, 0))
function волна(t)
текущее_время = t * шаг_времени
Y_новая = zeros(size(X))
for j in 1:ny
for i in 1:nx
эффект_волны = амплитуда * (
sin(2*pi*частота*(X[j,i]/Ширина - скорость*текущее_время)) +
0.5*sin(3*pi*частота*(2*X[j,i]/Ширина - скорость*текущее_время + 0.5)) +
0.3*sin(pi*частота*(3*Z_данные[j,i]/Высота + скорость*текущее_время)))
эффект_волны = эффект_волны * min(1, X[j,i]/0.5)
Y_новая[j,i] = 1.0 + эффект_волны
end
end
return Y_новая
end
GLMakie.record(фигура, модель, 1:число_кадров; framerate = квс) do кадр
Y_новая = волна(кадр)
полотно[2] = Y_новая
end
end
Создадим несколько визуальных моделей, используя различные текстуры и волновые параметры.
Знамя Победы
В связи с приближающейся 81-й годовщиной Победы в Великой Отечественной войне (на момент публикации данного примера), используем изображение Знамени Победы в качестве текстуры полотна. Определим волновые и другие параметры, и создадим анимационную модель.
текстура = "Знамя_Победы.png"
Ширина = 4.0
Высота = 2.5
nx = 960
ny = 480
квс = 20
амплитуда = 0.03
частота = 0.8
скорость = 0.9
время = 16
модель = "Модель_1.gif"
аэродинамическое_моделирование_полотна(текстура, Ширина, Высота, nx, ny, квс, амплитуда, частота, скорость, время, модель)

Флаг России
Немного увеличим амплитуду волн и скорость ветра. В качестве текстуры используем изображение государственного флага Российской Федерации.
текстура = "Флаг_России.png"
Ширина = 4.0
Высота = 2.5
nx = 960
ny = 480
квс = 20
амплитуда = 0.04
частота = 0.8
скорость = 1.5
время = 16
модель = "Модель_2.gif"
аэродинамическое_моделирование_полотна(текстура, Ширина, Высота, nx, ny, квс, амплитуда, частота, скорость, время, модель)

Логотип Engee
Уменьшим амплитуду и скорость скорость ветра, и немного увеличим частоту волн. В качестве текстуры используем изображение логотипа Engee.
текстура = "Engee_flag.png"
Ширина = 4.0
Высота = 2.5
nx = 960
ny = 480
квс = 20
амплитуда = 0.01
частота = 1.5
скорость = 1.1
время = 16
модель = "Модель_3.gif"
аэродинамическое_моделирование_полотна(текстура, Ширина, Высота, nx, ny, квс, амплитуда, частота, скорость, время, модель)

Заключение
Данный пример демонстрирует элегантный синтез прикладной математики и современной компьютерной графики. Представленный инструмент может найти применение не только в образовательных и демонстрационных целях, но и послужить основой для более сложных симуляций: добавления турбулентности, взаимодействия с препятствиями, расчёта натяжений и разрывов полотна.
Возможные направления развития:
-
Интерактивное управление параметрами в реальном времени
-
Моделирование нескольких взаимодействующих полотен
-
Учёт гравитации и упругих свойств материала
-
Моделирование парашютов, парусов, и других изделий из полотен
-
Экспорт в форматы дополненной реальности
«Цифровой ветер» — это не просто анимация флага. Это введение в исследование красоты физических процессов, скрытых за привычными явлениями.