Draw a Barnsley fern fractal in C#

For information about this 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 Form_Load event handler initializes the parameters for each function in the m_Func array and the probability for each function. It also sets the color to be used when plotting a point found by each function. Using different colors is interesting and gives you some sense of what each set of functions does but the final result here is drawn in green.

private float[] m_Prob = new float[4];
private float[,,] m_Func = new float[4, 2, 2];
private float[,] m_Plus = new float[4, 2];
private Color[] m_Clr = new Color[4];

// Initialize the fern functions, colors, etc.
private void Form1_Load(object sender, EventArgs e)
{
m_Clr[0] = Color.Red;
m_Prob[0] = 0.01f;
m_Func[0, 0, 0] = 0;
m_Func[0, 0, 1] = 0;
m_Func[0, 1, 0] = 0;
m_Func[0, 1, 1] = 0.16f;
m_Plus[0, 0] = 0;
m_Plus[0, 1] = 0;

m_Clr[1] = Color.Green;
m_Prob[1] = 0.85f;
m_Func[1, 0, 0] = 0.85f;
m_Func[1, 0, 1] = 0.04f;
m_Func[1, 1, 0] = -0.04f;
m_Func[1, 1, 1] = 0.85f;
m_Plus[1, 0] = 0;
m_Plus[1, 1] = 1.6f;

m_Clr[2] = Color.Blue;
m_Prob[2] = 0.08f;
m_Func[2, 0, 0] = 0.2f;
m_Func[2, 0, 1] = -0.26f;
m_Func[2, 0, 1] = -0.23f;
m_Func[2, 1, 1] = 0.22f;
m_Plus[2, 0] = 0;
m_Plus[2, 1] = 1.6f;

m_Clr[3] = Color.White;
m_Prob[3] = 0.06f;
m_Func[3, 0, 0] = -0.15f;
m_Func[3, 0, 1] = 0.28f;
m_Func[3, 1, 0] = 0.26f;
m_Func[3, 1, 1] = 0.24f;
m_Plus[3, 0] = 0;
m_Plus[3, 1] = 0.44f;

// New colors to make a lime fern.
m_Clr[0] = Color.Lime;
m_Clr[1] = Color.Lime;
m_Clr[2] = Color.Lime;
m_Clr[3] = Color.Lime;

MakeFern();
}

The MakeFern subroutine draws the fractal into the Bitmap named m_Bm. The form's Paint event handler simply displays the Bitmap.

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

private void MakeFern()
{
Bitmap bm = new Bitmap(picCanvas.ClientSize.Width, picCanvas.ClientSize.Height);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.Clear(picCanvas.BackColor);

Random rnd = new Random();
Color clr = Color.Red;
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 - m_Prob[j];
if (num <= 0)
{
func_num = j;
clr = m_Clr[j];
break;
}
}

x1 = x * m_Func[func_num, 0, 0] + y * m_Func[func_num, 0, 1] + m_Plus[func_num, 0];
y1 = x * m_Func[func_num, 1, 0] + y * m_Func[func_num, 1, 1] + m_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 * picCanvas.ClientSize.Height);
if ((ix >= 0) && (iy >= 0)
&& (ix < picCanvas.ClientSize.Width)
&& (iy < picCanvas.ClientSize.Height))
{
bm.SetPixel(ix, iy, clr);
}
}
}

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

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.