2

我是编码新手,我通过学习 C# 作为我的第一门编程语言开始了我的旅程。作为一项任务,我正在尝试编写一个绘制 Mandelbrot 集的程序,但它没有绘制它应该绘制的内容,而且在调试时我似乎找不到任何问题。它只是在左上角绘制了一个带有几个黑色像素的白色正方形。

这是我的代码中最重要的部分(PaintEventArgs 方法):

        //Magnitude and mandelnum @ start
        int mandelnum = 0;
        double Magnitude = 0; //Magnitude is the distance of (a,b) to middle of my picturebox
        
        //a and b @ start. a and b are all (x,y) pixels of my bitmap reformed with the 
        following formulas: (a*a-b*b+x, 2*a*b+y)

        double a = 0;
        double b = 0;

        int x = 0;
        int y = 0;
        int picboxmiddleX = (50 + pictureBox1.Width) / 2;
        int picboxmiddleY = (110 + pictureBox1.Height) / 2; //the location of picturebox is 
                                                            (50,110)
            //loop through all pixels, calc magnitude for every (x,y) and stop if magnitude is                                
            larger than 2, attach color black or white to ever pixel dependent on even or odd 
            mandelnums.

            for (x = 0; x < pictureBox1.Width; x++)
            {
                for (y = 0; y < pictureBox1.Height; y++)
                {
                while (Magnitude < 2.0) {
                    mandelgetal++;

                    if (mandelgetal < 100)
                    {
                        break;
                    }

                    a = (a * a) - (b * b) + x;
                    b = (2 * a * b) + y;
                    Magnitude = Math.Sqrt(Math.Pow((a - middenpanelX), 2) + Math.Pow((b - 
                    middenpanelY), 2));
                }
                    //pixels with even mandelnum get color white and odd is black
                    if (mandelgetal % 2 == 0)
                    {
                        bm.SetPixel(x, y, Color.White);
                    }
                    else if (mandelgetal % 2 != 0)
                    {
                        bm.SetPixel(x, y, Color.Black);
                    }
                }                        
            }
        pictureBox1.Image = bm;
    }

我希望有人能帮帮忙!

4

2 回答 2

1
  1. 声明

    a = 0.0;
    b = 0.0;
    

    需要在像素循环内移动

  2. 和变量在 Mandelbrot 迭代中使用时需要保存坐标而不是像素值xy请记住,mandelbrot 坐标在 -2 和 2 之间变化(取决于缩放),而不是 0 到像素大小

  3. picboxmiddleX不需要,并且计算不正确。如果要从表单像素转换为控制像素,请使用.PointToScreen().PointToClient()

    您可以通过查看 if 来检查计算是否会发散a*a+b*b>4.0。计算Magnitude是完全没有必要的。

  4. 我看到在下面的迭代中,您a在计算中使用了 的新值b

    a = (a * a) - (b * b) + x;
    b = (2 * a * b) + y;
    

    我建议使用临时变量来保存原始变量a

    ta = a;
    a = (a * a) - (b * b) + x;
    b = (2 * ta * b) + y;
    
  5. 如果你想生成一个Bitmap来填充图片框,那么你不需要订阅Paint()事件。您在初始化时执行一次,然后在每次调整表单大小时执行此操作。创建Bitmap集合pictureBox1.Image = bm后,它将显示。

  6. 如果您想在每个绘画事件中绘制分形,请使用

    e.Graphics.DrawRectangle(pen, x,y,1,1);
    

    绘制单个像素。

这是一个使用分形生成位图的示例函数

    public Bitmap GenerateMandelbrot(Size size, double xMin, double yMin, double xMax, double yMax, int iterLimit)
    {
        var bmp = new Bitmap(size.Width, size.Height);
        for (int py = 0; py < size.Height; py++)
        {
            for (int px = 0; px < size.Width; px++)
            {
                // get coordinates of pixel (px, py)
                double x = xMin + ((xMax - xMin) * px) / (size.Width - 1);
                double y = yMin + ((yMax - yMin) * py) / (size.Height- 1);

                double a = x, b = y;
                int iter = 0;
                do
                {
                    // use tuples for iteration
                    (a, b) = (a * a - b * b + x, 2 * a * b + y);
                    iter++;
                } while (iter<=iterLimit && a*a+b*b<4);
                if (iter > iterLimit)
                {
                    // interior color
                    bmp.SetPixel(px, py, Color.Black);
                }
                else
                {
                    // exterior color banded by iteration
                    Color color = iter % 2 == 0 ? Color.DarkOrange : Color.Yellow;
                    bmp.SetPixel(px, py, color);
                }
            }
        }
        return bmp;
    }

它可以按如下方式使用

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        var bmp = GenerateMandelbrot(pictureBox1.ClientSize, -2.0, -1.6, 1.0, 1.6, 100);
        pictureBox1.Image = bmp;
    }

    ...
}

请参阅GitHub存储库以获取更多详细信息并获取有关下一步如何移动的想法。

表格1

于 2021-10-04T18:01:17.933 回答
0

在我看来,一旦Magnitude超过/等于 2.0,它就会停止计算 - 似乎没有什么可以将其重置为低于该值..

由于像素值的计算是在while循环中完成的,如果while循环不运行,那么您的像素将全部为白色或黑色,具体取决于mandelgetal卡住的值。

如果左上角有几个黑色像素*,那么可以合理地说while循环运行了少量次数,但在(比如说)10 个像素之后没有,其余的数千个像素在PB里都只是涂了同一种颜色

*在winforms中,原点0,0在左上角

于 2021-10-04T16:41:03.657 回答