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

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 <

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

( | 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"

[[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

}

{

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 |

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. |