Draw a Barnsley fern fractal in C#

This example draws a Barnsley fern fractal. For information about this kind of fractal, see Barnsley’s Fern by Eric W. Weisstein from MathWorld, a Wolfram Web Resource.

The program starts from a random point. At each step, it randomly picks a function (with non-uniform probability) and applies the function to the point to find the next point. It then plots that point.

Each function has the form:

X(n+1) = A * X(n) + B * Y(n) + C
Y(n+1) = D * X(n) + E * Y(n) + F

The following code initializes the probability and function parameters.

private float[] Prob = { 0.01f, 0.85f, 0.08f, 0.06f };
private float[, ,] Func =
{
    {
        {0, 0},
        {0, 0.16f},
    },
    {
        {0.85f, 0.04f},
        {-0.04f, 0.85f},
    },
    {
        {0.2f, -0.26f},
        {0.23f, 0.22f},
    },
    {
        {-0.15f, 0.28f},
        {0.26f, 0.24f},
    },
};
private float[,] Plus =
{
    {0, 0},
    {0, 1.6f},
    {0, 1.6f},
    {0, 0.44f},
};

The Prob array gives the probabilities of picking each of the different functions. The Func array contains the values A, B, D, and E. The Plus array holds the values C and F.

The following MakeFern method draws the fractal into a Bitmap and displays it.

private void MakeFern()
{
    int wid = picCanvas.ClientSize.Width;
    int hgt = picCanvas.ClientSize.Height;
    Bitmap bm = new Bitmap(wid, hgt);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.Black);

        Random rnd = new Random();
        int func_num = 0, ix, iy;
        float x = 1, y = 1, x1, y1;
        for (int i = 1; i <= 100000; i++)
        {
            double num = rnd.NextDouble();
            for (int j = 0; j <= 3; j++)
            {
                num = num - Prob[j];
                if (num <= 0)
                {
                    func_num = j;
                    break;
                }
            }

            x1 = x * Func[func_num, 0, 0] +
                 y * Func[func_num, 0, 1] +
                 Plus[func_num, 0];
            y1 = x * Func[func_num, 1, 0] +
                 y * Func[func_num, 1, 1] +
                 Plus[func_num, 1];
            x = x1;
            y = y1;

            const float w_xmin = -4;
            const float w_xmax = 4;
            const float w_ymin = -0.1f;
            const float w_ymax = 10.1f;
            const float w_wid = w_xmax - w_xmin;
            const float w_hgt = w_ymax - w_ymin;
            ix = (int)Math.Round((x - w_xmin) /
                w_wid * picCanvas.ClientSize.Width);
            iy = (int)Math.Round(
                (picCanvas.ClientSize.Height - 1) - 
                (y - w_ymin) / w_hgt * hgt);
            if ((ix >= 0) && (iy >= 0) &&
                (ix < wid) && (iy < hgt))
            {
                bm.SetPixel(ix, iy, Color.Lime);
            }
        }
    }

    // Display the result.
    picCanvas.BackgroundImage = bm;
}

The MakeFern method starts at point (1, 1) and repeatedly applies randomly selected functions, plotting each point on the Bitmap.




This entry was posted in algorithms, fractals, graphics, mathematics and tagged , , , , , , , , , , , . Bookmark the permalink.

2 Responses to Draw a Barnsley fern fractal in C#

  1. gopal says:

    hi ,i am trying to draw some fractal image ,i am stuck here,can u help ?
    http://stackoverflow.com/questions/25424978/how-to-make-diagram-fit-with-in-panel

  2. RodStephens says:

    One problem here is that you’re using CreateGraphics to make the Graphics object. That’s rarely the right thing to do.

    If you’re drawing in a Paint event handler, use the e.Graphics parameter.

    In this example, pass e.Graphics into the draw_T method:

    private void Canvas_Paint(object sender, PaintEventArgs e)
    {
        start_x = Canvas.Width / 2;
        start_y = Canvas.Height / 2;
        for (int i = 0; i < 400; i++)
            draw_T(e.Graphics);
    }
    
    public void draw_T(Graphics g)
    {
        ...
    }

    It looks like you may have a sizing problem, too, but if you make this change at least you can see some results and then try to fix them. Give it a try and post again if you get stuck.

Leave a Reply

Your email address will not be published. Required fields are marked *