基于Julia集创建分形动画
导言
1918年,法国科学家加斯顿*朱莉娅(Gaston Julia)在迭代过程中研究了复杂函数的行为,但只有随着计算机的出现,世界才看到了隐藏在他的方程中的美丽。
Julia集是秩序与混沌边界的视觉体现。 一个简单的方程 创建无限多种自相似的分形,其中每个点都冲向无穷大或保留在有限的区域内。
在这个例子中,我们将看看如何使用复数,迭代和配色方案来创建Julia set形状的动画,该形状根据常量的变化角度改变其状态。
我们将附加必要的库。
neededLibs = ["LinearAlgebra", "Printf", "ProgressMeter", "Images", "FileIO", "ColorSchemes", "VideoIO"]
for lib in neededLibs
try
eval(Meta.parse("using $lib"))
catch ex
Pkg.add(lib)
eval(Meta.parse("using $lib"))
end
end
形状和动画参数
定义动画参数。 所需参数:
*动画持续时间;
*框架宽度;
*框架高度;
*每秒帧数;
*常数的初始角度;
*常数的最终角度;
*形状的半径;
*迭代次数;
*复杂平面的尺寸(与框架的宽度和高度成比例地转换)。
сек = 60 # 动画持续时间
ш = 1920 # 框架宽度
в = 1080 # 框架高度
квс = 60 # 每秒帧数
α = 2π*0.14 # 常数的初始角度
β = 2π*0.86 # 常数的最终角度
r = 0.78 # 半径
итер = 20 # 迭代次数
л = 1.5 # 复平面的线性宽度
复平面
基于初始帧,我们将计算动画中的帧数,并为复平面创建数字数组。 哪里 -实部阵列, -虚部的阵列。
кадры = сек * квс # 总帧数
# 创建一个复杂的平面
X = [x for y in range(-л, л, length=в), x in range(-л, л, length=ш)];
Y = [y for y in range(-л, л, length=в), x in range(-л, л, length=ш)];
具有表达式和迭代的函数
让我们定义一个计算每个复数的函数,并执行计算函数的迭代,并将结果值替换为函数参数。
函数定义如下:
,
哪里:
,
,
-常数的变化角度,影响图形的动画,
-假想单位。
function Жюлиа(X, Y, a, r, итер)
Z = X .+ im .* Y
C = r .* cos(a) .+ im .* r .* sin(a)
for k in 1:итер
Z = Z .^ 2 .+ C
end
return exp.(-abs.(Z)), C
end
创建字幕
让我们定义一个函数,以srt格式创建字幕,以显示与形状的当前状态相对应的当前Z值。
function кадр_время(к, квс)
T = zeros(UInt32, 4)
квч = 3600 * квс # 每小时帧数
квм = 60 * квс # 每分钟帧数
бч = mod(к, квч) # 没有手表的镜头
бм = mod(бч, квм) # 没有分钟和小时的帧
T[1] = (к - бч) ÷ квч # 手表
T[2] = (бч - бм) ÷ квм # 分钟
T[4] = mod(бм, квс) # 没有秒、分钟或小时的帧
T[3] = (бм - T[4]) ÷ квс # 秒数
мс = round(Int, 999 * T[4] / (квс - 1))
субт = string(lpad(T[1], 2, '0'), ':', lpad(T[2], 2, '0'), ':', lpad(T[3], 2, '0'), ',', lpad(мс, 3, '0'))
return субт
end
创建动画
让我们创建一个进度条并开始动画创建过程。
кадр = 0
t = 0.0
время = 0.0
видео = []
п = Progress(кадры, 1, "Создание анимации:")
субтитры = open("Множество Жюлиа.srt", "w")
ProgressMeter.ijulia_behavior(:clear)
for a in range(α + (β - α)/кадры, stop = β, step = (β - α)/кадры)
старт = time()
время += t
кадр += 1
скорость = кадр / max(время, 0.001)
осталось = (кадры - кадр) / скорость
ProgressMeter.next!(п; showvalues = [(:Время, @sprintf "%d секунд" round(Int, время)), (:Создано, @sprintf "%d кадров" кадр), (:Скорость, @sprintf "%.4f кадров в секунду" скорость), (:Осталось, @sprintf "%d секунд" round(Int, осталось))])
J, C = Жюлиа(X, Y, a, r, итер)
J[isnan.(J)] .= 0.0
push!(видео, convert.(RGB{N0f8}, get.(Ref(ColorSchemes.magma), clamp.(J, 0.0, 1.0))))
write(субтитры, string(string(кадр), "\n", кадр_время(кадр-1, квс), " --> ", кадр_время(кадр, квс), "\n", "f(z) = z² ", real(C) >= 0 ? "+ " : "- ", @sprintf("%.5f", abs(real(C))), " ", imag(C) >= 0 ? "+ " : "- ", @sprintf("%.5fi", abs(imag(C))), "\n\n"))
t = time() - старт
end
if !isempty(видео)
@info "Сохраняем видео..."
параметры = (crf=23, preset="medium")
VideoIO.save("Множество Жюлиа.mp4", видео, framerate=квс, encoder_options=параметры)
end
close(субтитры)
println("\nАнимация создана успешно!")
println(" - Всего кадров: $кадры")
println(" - Время создания: $(round(Int, время)) секунд")
println(" - Средняя скорость создания: $(round(кадры/время, digits=4)) кадров в секунду")
完成动画创建过程后,当前文件夹中会出现一个带有图形的视频文件。:
.gif)
如果在计算迭代而不是表达式的函数中 替换为 ,并将配色方案替换为 turbo, 我们将得到一个同样有趣的数字。
.gif)
如果我们将表达式定义为 通过将配色方案替换为 rainbow,我们得到一个更不寻常的形状。
.gif)
结论
Julia集的动画不仅展示了美学,还展示了分形几何的应用价值。 基于复平面迭代变换原理的算法被用于各种科学和工程领域。
主要应用领域
*电信。
具有自相似结构的分形天线提供具有最小尺寸的多频带,这对于移动设备和卫星通信至关重要。
*计算机建模。
分形生成算法用于合成计算机图形中的自然景观,以及对多孔材料和生物结构进行建模。
*医疗诊断。
分形分析用于医学图像处理,以量化血管,神经网络和肺组织的复杂性。
*加密和数据保护。
分形系统的确定性混沌用于伪随机数发生器和隐写方法。
因此,从一个抽象的数学对象到一个实用的工具,分形代表了理论数学和应用技术之间的重要桥梁。 所展示的动画技术不仅可以可视化这些概念,还可以通过参数实验来探索动态系统中秩序和混沌之间的界限。