大家是否看过下面的视频:
它就是著名的曼德博集合(Mandelbrot set,或译为曼德布洛特复数集合),是一种在复平面上组成分形的点的集合,是数学家本华.曼德博Benoit B. Mandelbrot提出的分形理论中最著名的分形。
这个集合的奇妙之处在于,将曼德博集合无限放大都能够有精妙的细节在内,而这瑰丽的图案仅仅由一个简单的公式生成。因此有人认为曼德博集合是“人类有史以来做出的最奇异、最瑰丽的几何图形”,曾被称为“上帝的指纹”。
今天,我们将分享什么是分形理论,如何用MoonBit来绘制出曼德博分形,用MoonBit发现数学之美。
什么是分形理论?
首先,让我们来了解一下什么是分形理论。
分形理论是由曼德博在1975年创造的,它源于拉丁语“fractus”,意思是“破碎的”或“断裂的”。分形理论的数学基础是分形几何学。分形理论的最基本特点是用分数维度的视角和数学方法描述和研究客观事物。
也正是因为如此,它跳脱出了我们常规世界的维度,可以更加具体和真实地描述复杂系统,得以窥见客观事物的复杂和多样性。
由于分形具有“无限复杂性”,你可能认为分形很难制作,但这是一个非常简单的过程。要做一个分形,只需要一遍又一遍地重复同样的过程。用数学术语来说,数学分形是一个迭代(递归的一种形式)的方程。
最著名的分形是曼德博集合,它来自于复数集合。数学家Adrien Douady定义了下面的函数:
以致敬曼德博,并将其命名为曼德博集合。当从迭代时,不会向无穷大发散。从本质上来说,这是一个迭代公式,式子当中的变量都是复数。所以当你按照这个式子进行代入计算的时候,局部的图形都能和整体表现出相似的地方,并且这种相似往往是集中在细微之处的,要仔细观察才能发现。
如何绘制?
为了确定我们要绘制的图形区域,必须先介绍区域坐标这个概念。一个复平面的点由一个复数来表示(d=x+yi)。加上 width 和 height 来确定复平面上一个长方形区域。
假设一个图像宽为个像素,高为个像素,我们需要计算个像素的颜色,并且将它们画上
我们使用 Moonbit 来完成颜色的计算部份,然后将计算完的颜色传给 js,用 js canvas 来画图。
颜色的计算
pub fn calc_color(col: Int, row: Int, ox: Double, oy: Double, width: Double) -> Int {
let pixel_size = width / image_width
let cx = (float_of_int(col) - coffset) * pixel_size + ox
let cy = (float_of_int(row) - roffset) * pixel_size + oy
var r = 0
var g = 0
var b = 0
var i = -1
while i <= 1 {
var j = -1
while j <= 1 {
let d = iter(
cx + float_of_int(i) * pixel_size / 3.0,
cy + float_of_int(j) * pixel_size / 3.0,
)
let c = get_color(d)
r = r + c.asr(16).land(0xFF)
g = g + c.asr(8).land(0xFF)
b = b + c.land(0xFF)
j = j + 1
}
i = i + 1
}
r = r / 9
g = g / 9
b = b / 9
return r.lsl(16).lor(g.lsl(8)).lor(b)
}
这里用于计算 row 行和 col 列那个像素所代表的复平面上的正方形的中心点的坐标
let pixel_size = width / image_width
let cx = (float_of_int(col) - coffset) * pixel_size + ox
let cy = (float_of_int(row) - roffset) * pixel_size + oy
我们知道对一个复数,它属于Mandelbrot集合,当且仅当下面这个递归定义得到的无穷复数列一直处于复平面上以原点为中心以为半径的圆内:; 如果我们把 写成 这样实部和虚部分开的形式,同样也把写成的形式(和