分形具有自相似性、非整數維度、簡單規則產生無限複雜結構特性。程式實作分形是驗證遞迴/迴圈邏輯、繪圖座標轉換、效能優化的絕佳練習。
private void DrawKoch(Graphics g, Pen pen, PointF p1, PointF p2, int depth) {
if (depth == 0) {
g.DrawLine(pen, p1, p2);
return;
}
// 將線段三等分:p1 -> a -> b -> p2
PointF a = new PointF(
p1.X + (p2.X - p1.X) / 3f,
p1.Y + (p2.Y - p1.Y) / 3f
);
PointF b = new PointF(
p1.X + 2f * (p2.X - p1.X) / 3f,
p1.Y + 2f * (p2.Y - p1.Y) / 3f
);
// 計算等邊三角形頂點 c (向外凸出)
double angle = Math.PI / 3; // 60 度
float dx = b.X - a.X;
float dy = b.Y - a.Y;
PointF c = new PointF(
a.X + dx * (float)Math.Cos(angle) - dy * (float)Math.Sin(angle),
a.Y + dx * (float)Math.Sin(angle) + dy * (float)Math.Cos(angle)
);
// 遞迴繪製 4 段
DrawKoch(g, pen, p1, a, depth - 1);
DrawKoch(g, pen, a, c, depth - 1);
DrawKoch(g, pen, c, b, depth - 1);
DrawKoch(g, pen, b, p2, depth - 1);
}
// 呼叫:繪製三角形三邊
void DrawSnowflake(Graphics g, int depth) {
PointF[] triangle = {
new PointF(200, 50),
new PointF(50, 300),
new PointF(350, 300)
};
Pen pen = Pens.Blue;
for (int i = 0; i < 3; i++) {
DrawKoch(g, pen, triangle[i], triangle[(i+1)%3], depth);
}
}
void DrawSierpinski(Graphics g, PointF top, PointF left, PointF right, int depth) {
if (depth == 0) {
g.FillPolygon(Brushes.Blue, new[] { top, left, right });
return;
}
// 計算三邊中點
PointF midLeft = MidPoint(top, left);
PointF midRight = MidPoint(top, right);
PointF midBottom = MidPoint(left, right);
// 遞迴繪製三個小三角形 (中間留白)
DrawSierpinski(g, top, midLeft, midRight, depth - 1);
DrawSierpinski(g, midLeft, left, midBottom, depth - 1);
DrawSierpinski(g, midRight, midBottom, right, depth - 1);
}
PointF MidPoint(PointF a, PointF b) => new PointF((a.X+b.X)/2f, (a.Y+b.Y)/2f);
void DrawMandelbrot(Bitmap bmp, int maxIter = 100) {
double xMin = -2.5, xMax = 1.0;
double yMin = -1.25, yMax = 1.25;
for (int px = 0; px < bmp.Width; px++) {
for (int py = 0; py < bmp.Height; py++) {
// 像素座標映射到複數平面
double x0 = xMin + px * (xMax - xMin) / bmp.Width;
double y0 = yMin + py * (yMax - yMin) / bmp.Height;
double x = 0, y = 0;
int iter = 0;
while (x*x + y*y <= 4 && iter < maxIter) {
double xNew = x*x - y*y + x0;
y = 2*x*y + y0;
x = xNew;
iter++;
}
// 著色:依迭代次數漸層
int color = iter == maxIter ? 0 : (iter * 255 / maxIter);
bmp.SetPixel(px, py, Color.FromArgb(color, color, 255 - color));
}
}
}
Bitmap.LockBits + unsafe 指標直接操作像素,避免 SetPixel 呼叫開銷Parallel.For(0, height, y => { ... }) 獨立計算每行

