什麼是碎形?
碎形(Fractal)是一種「自相似」的幾何結構:放大任一部分,都能看到整體的縮小版。
自然界中的碎形例子:
Koch 雪花
從一段線段出發,中間三分之一換成一個等邊三角形,重複無限次。
function kochSegment(ctx, x1, y1, x2, y2, depth) {
if (depth === 0) {
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
return;
}
const dx = x2 - x1, dy = y2 - y1;
const mx = x1 + dx / 3, my = y1 + dy / 3;
const nx = x1 + 2 * dx / 3, ny = y1 + 2 * dy / 3;
const px = mx + (dx / 3) * Math.cos(-Math.PI / 3)
- (dy / 3) * Math.sin(-Math.PI / 3);
const py = my + (dx / 3) * Math.sin(-Math.PI / 3)
+ (dy / 3) * Math.cos(-Math.PI / 3);
kochSegment(ctx, x1, y1, mx, my, depth - 1);
kochSegment(ctx, mx, my, px, py, depth - 1);
kochSegment(ctx, px, py, nx, ny, depth - 1);
kochSegment(ctx, nx, ny, x2, y2, depth - 1);
}
Barnsley 蕨
用「迭代函數系統(IFS)」只需 4 條仿射變換公式,就能產生逼真的蕨葉:
import random, math
def barnsley_fern(n=100000):
x, y = 0, 0
points = []
for _ in range(n):
r = random.random()
if r < 0.01:
x, y = 0, 0.16 * y
elif r < 0.86:
x, y = 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6
elif r < 0.93:
x, y = 0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6
else:
x, y = -0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44
points.append((x, y))
return points
Mandelbrot 集合
最著名的碎形之一。對複數 c,反覆計算 z = z² + c,看 z 是否發散。
function mandelbrot(cx, cy, maxIter = 100) {
let zx = 0, zy = 0, iter = 0;
while (zx * zx + zy * zy <= 4 && iter < maxIter) {
const newZx = zx * zx - zy * zy + cx;
zy = 2 * zx * zy + cy;
zx = newZx;
iter++;
}
return iter;
}
前往碎形繪圖頁面,用互動 Canvas 繪製你自己的碎形!