Home page

The Barnsley Fern fractal

The Barnsley fractal
The Barnsley Fern is a fractal named after the British mathematician Michael Barnsley who first described it in his book Fractals Everywhere. He made it to resemble the Black Spleenwort, Asplenium adiantum-nigrum.

The program to generate it uses an iterative function system, like one of the methods of producing the Sierpinski triangle.
Here, I shall first write some pseudo-code to show you how it works, then some code written in Java and for the Casio calculators in order to produce it.

The method below uses matrices to encapsulate all the numbers. My program code has all the numbers, just expanded to avoid matrices.


First of all, select an x,y at 0,0 in this form:
( 0
0
)
... and plot that pixel.
Now you iterate hundreds of thousands of times. Select one of four matrices at random and apply the equation. Here is an image used to illustrate what is happening:


Here is the method to draw it. Note that the complete fern is within the range −2.1818 < x < 2.6556 and 0 < y < 9.95851 so program code has convert it or use certain commands to set the screen up, if available.

while (KeyNotPressed)
{
Choose a random number which is used to select from the matrices below:

Choose this 1% of the time. It maps any point to a point in the first line segment at the base of the stem (it draws the stem)
( x
y
) = ( 0.00
0.00
0.00
0.16
) ( x
y
)

Chose this 85% of the time. It maps any point inside the leaflet represented by the red triangle to a point inside the opposite, smaller leaflet represented by the blue triangle (it generates successive copies of the stem and bottom fronds to make the complete fern)
( x
y
) = ( 0.85
-0.04
0.04
0.85
) ( x
y
) + ( 0.00
1.60
)

Choose this 7% of the time. It maps any point inside the leaflet (or pinna) represented by the blue triangle to a point inside the alternating corresponding triangle across the stem, flipping it (it draws the bottom frond on the left)
( x
y
) = ( 0.20
0.23
-0.26
0.22
) ( x
y
) + ( 0.00
1.60
)

Choose this 7% of the time. It maps any point inside the leaflet (or pinna) represented by the blue triangle to a point inside the alternating corresponding triangle across the stem, without flipping it (it draws the bottom frond on the right)

( x
y
) = ( -0.15
0.26
0.28
0.24
) ( x
y
) + ( 0.00
0.44
)
}


Here is the code on a Casio calculator (it is quite slow to appear):
ViewWindow -2.1818,2.6556,0,0,10,0
[[0,0][0,.16]]→Mat A
[[.85,.04][-.04,.85]]→Mat B
[[.2,-.26][.23,.22]]→Mat C
[[0.15,.28][.26,.24]]→Mat D
[[0][0]]→Mat P
For 1→A to 5000
Ran#→R
If R ≤.01
Then Mat A×Mat P→Mat P
Goto 1
Endif
If R ≤.08
Then Mat C×Mat P+[[0][1.6]]→Mat P
Goto 1
Endif
If R ≤.16
Then Mat D×Mat P+[[0][.44]]→Mat P
Goto 1
Endif
Mat B×Mat P+[[0][1.6]]→Mat P
Lbl 1
Plot Mat P[1,1],Mat P[2,1]
Next
Text 1,1,"Done"


Here is a portion of the code for Java (which can be converted to C++) but without using matrices and it uses scaling to plot it to the screen. I shall explain how the probabilities work later:

public void paintComponent(Graphics g)
    {
float    a[]={0F,0.2F,-0.15F,0.85F},
    b[]={0F,-0.26F,0.28F,0.04F},
    c[]={0F,0.23F,0.26F,-0.04F},
    d[]={0.16F,0.22F,0.24F,0.85F},
    e[]={0F,0F,0F,0F},
    f[]={0F,1.6F,0.44F,1.6F},
    rand,NewX,NewY;
int Select=0;
int xscale,yscale,xoffset,ScreenX,ScreenY;
Rectangle drawarea = getBounds();
xoffset =(int) ((2.1818F/(2.6556F+2.1818F))*drawarea.width);
xscale = (int)((drawarea.width-xoffset)/2.6556F);
yscale = drawarea.height/10;

/*Barnsley fractal has -2.1818 < x < 2.6556
 * 0<=y<=9.95851
 * The scale came from ScreenWidth = 2.6556 * scale + offset
 */
float x=0,y=0;
g.setColor(new Color(0,128,0));
for(int n=0;n<1000000;n++)
    {
   rand=(float)Math.random();//rand now is 0 <= rand < 1
    if (rand<=0.01F){Select=0;rand=10;}
    if (rand<=0.08F){Select=1;rand=10;}
    if (rand<=0.15F){Select=2;rand=10;}
    if(rand<1)Select=3;

    NewX=a[Select]*x+b[Select]*y+e[Select];
    NewY=c[Select]*x+d[Select]*y+f[Select];
    x=NewX;y=NewY;

        ScreenX=(int)(x*xscale+xoffset);
        ScreenY=(int)(y*yscale);
        g.drawLine(ScreenX,ScreenY,ScreenX,ScreenY);
    }//end of "for" loop

    }

The probabilities has come from adding them in decimal form. The first is 0.01 which is 1%. I set rand to 10 (or any large number) so the other 'if' statements will not operate (to avoid using a goto statement). The second is the 7% equation. I add 0.01 to 0.07. The third is another 7% equation, adding to the number above gives 0.15. The last statement corresponds to the 85% equation but if this one is executed, that means the others didn't so it is a sort of "catch-all" statement at the end.
I shall explain what happens with the "if (rand<=0.08F){Select=1;rand=10;}" section when rand = 0.5.
The rand variable is greater than 0.01 so the first "if" statement is ignored. Since 0.5 is less than 0.08, this "if" statement is executed and rand is set to 10 so the other "if" statements will not execute.

By playing with the coefficients, it is possible to create mutant fern varieties. In his paper on V-variable fractals, Barnsley calls this trait a superfractal. One experimenter has come up with a table of coefficients to produce another remarkably naturally looking fern however, resembling the Cyclosorus or Thelypteridaceae fern. These are:
w a b c d e f p
ƒ1 0 0 0 0.25 0 −0.4 0.02
ƒ2 0.95 0.005 −0.005 0.93 −0.002 0.5 0.84
ƒ3 0.035 −0.2 0.16 0.04 −0.09 0.02 0.07
ƒ4 −0.04 0.2 0.16 0.04 0.083 0.12 0.07
Where the p column are the probabilities.

Have you found an error or do you want to add more information to these pages?
You can contact me at the bottom of the home page.

Home page