首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 分形圖繪製實戰:遞迴與迴圈繪製 Koch Snowflake、Sierpinski Triangle

     編輯:關於C#

分形幾何與程式設計

分形具有自相似性、非整數維度、簡單規則產生無限複雜結構特性。程式實作分形是驗證遞迴/迴圈邏輯、繪圖座標轉換、效能優化的絕佳練習。

Koch Snowflake (科赫雪花) 遞迴實作

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);
    }
}

Sierpinski Triangle (謝爾賓斯基三角形) 迭代實作

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);

Mandelbrot Set (曼德博集合) 像素級迴圈

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 => { ... }) 獨立計算每行
  • 快取三角函數值、避免重複計算
  • 迭代深度限制防止堆疊溢位

Koch Snowflake
Sierpinski Triangle
Mandelbrot Set

本文對應《叩響 C# 之門》第 4.7 節循環語句深化練習:分形圖教學內容

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved