Construction Steps of Barnsley's Fern

After playing with the variables in a Manipulate I came up with these numbers for the arguments of the AffineMap functions.

They aren't perfect. I recommend tuning them yourself:

enter image description here

         (* Activate Roman Maeder's Code first!* )

   (fract2[x_, n_] := Show[Graphics[Nest[IFS[{
   AffineMap[0 °, 0 °, 0, 0, 0.18, 0], 
   AffineMap[-2.5 °, -2.5 °, 0.90, 0.90, 0, 1.7], 
   AffineMap[49 °, 49 °, 0.33, 0.33, 0, 1.7], 
   AffineMap[120 °, -50 °, 0.33, 0.33, 0.0, 0.33]}],
      x, n]], Axes ->  False,
     AspectRatio ->  Automatic,
    AxesOrigin -> {0, 0}]; 
   Table[fract2[Circle[{1, 1}, {1, 2}], c], {c, 8}])

You set the initial conditions: AffineMap provides the fractal Step

This is Roman Maeder's AffineMap function and IFS

$CirclePoints = 24
Format[m_map] := "-map-"

AffineMap[phi_, psi_, r_, s_, e_, f_] := 
 map[{{r Cos[phi], -s Sin[psi], e}, {r Sin[phi], s Cos[psi], f}}]
AffineMap[params : {_Symbol, _Symbol}, expr : {_, _}] := 
 map[Function[params, expr]]

AffineMap[mat_?MatrixQ] /; Dimensions[mat] == {2, 3} := map[mat]

map[mat_?MatrixQ][{x_, y_}] := mat.{x, y, 1}
map[f_Function][{x_, y_}] := f[x, y]

map /: Composition[map[mat1_?MatrixQ], map[mat2_?MatrixQ]] := 
 map[mat1.Append[mat2, {0, 0, 1}]]
map /: Composition[map[f_Function], map[g_Function]] := 
 Module[{x, y}, AffineMap[{x, y}, f @@ g[x, y]]]

 AverageContraction[map[mat_?MatrixQ]] := Abs[Det[Drop[#, -1] & /@     mat]]
AverageContraction[map[f_Function]] := 
 Module[{x, y}, Abs[Det[Outer[D, f[x, y], {x, y}]]]]

(m_map)[Point[xy_]] := Point[m[xy]]

(m_map)[Line[points_]] := Line[m /@ points]

(m_map)[Polygon[points_]] := Polygon[m /@ points]

(m_map)[Rectangle[{xmin_, ymin_}, {xmax_, ymax_}]] := 
 m[Polygon[{{xmin, ymin}, {xmax, ymin}, {xmax, ymax}, {xmin, ymax}}]]

(m_map)[Circle[xy_, {rx_, ry_}]] := 
 With[{dp = N[2 Pi/$CirclePoints]}, 
 m[Line[Table[xy + {rx Cos[phi], ry Sin[phi]}, {phi, 0, 2 Pi, dp}]]]]

(m_map)[Circle[xy_, r_]] := m[Circle[xy, {r, r}]]

(m_map)[Disk[xy_, {rx_, ry_}]] := 
 With[{dp = N[2 Pi/$CirclePoints]}, 
 m[Polygon[
 Table[xy + {rx Cos[phi], ry Sin[phi]}, {phi, 0, 2 Pi - dp, dp}]]]]

 (m_map)[Disk[xy_, r_]] := m[Disk[xy, {r, r}]]

 (m_map)[(Circle | Disk)[xy_, r_, args__]] := 
  Sequence[]

 (m_map)[Text[text_, pos : {_, _}, args___]] := Text[text, m[pos], args]
  (m_map)[(h : 
     PointSize | AbsolutePointSize | Thickness | AbsoluteThickness)    [r_]] := h[r Sqrt[AverageContraction[m]]]

 (m_map)[Graphics[objs_List, opts___]] := 
 Graphics[Function[g, m[g], Listable] /@ objs, opts]

(m_map)[unknown_] := unknown

rotation[alpha_] := AffineMap[alpha, alpha, 1, 1, 0, 0]

scale[s_, t_] := AffineMap[0, 0, s, t, 0, 0]
scale[r_] := scale[r, r]

translation[{x_, y_}] := AffineMap[0, 0, 1, 1, x, y]

Options[IFS] = {Probabilities -> Automatic};

Format[_ifs] := "-ifs-"

optnames = First /@ Options[IFS]

IFS[ms : {_map ...}, opts___?OptionQ] := 
Module[{optvals}, 
optvals = optnames /. Flatten[{opts}] /. Options[IFS];
ifs[ms, Thread[optnames -> optvals]]]

 ifs[ms_List, _][gr : Graphics[_, opts___]] := 
 Graphics[First /@ Through[ms[gr]], opts]
 (i_ifs)[objs_List] := i /@ objs
 ifs[ms_List, _][obj_] := Through[ms[obj]]

The examples below are from the book and they use points.

 collage1[x_, n_] := Graphics[Nest[IFS[{
    AffineMap[-2 °, -2 °, 0.02, 0.6, -0.14, -0.8], 
    AffineMap[0, 0, 0.6, 0.4, 0, 1.2], 
    AffineMap[-30 °, -30 °, 0.4, 0.7, 0.6, -0.35], 
    AffineMap[30 °, 30 °, 0.4, 0.65, -0.7, -0.5]}], 
   x, n],
  Axes -> False,
  AspectRatio -> Automatic,
 AxesOrigin -> {0, 0},
  ColorOutput -> (RGBColor[0.316411, 0.699229, 0.0585946] &)];

Show[collage1[Point[{0, 0}], 8]]

enter image description here

  collage2[x_, n_] := Graphics[Nest[IFS[{
  AffineMap[0 °, 0 °, 0, 0, 0.16, 0], 
  AffineMap[-2.5 °, -2.5 °, 0.85, 0.85, 0, 1.6], 
  AffineMap[49 °, 49 °, 0.3, 0.34, 0, 1.6], 
  AffineMap[120 °, -50 °, 0.3, 0.37, 0.0, 0.37]}],
 x, n],
 Axes -> False,
 AspectRatio -> Automatic,
 AxesOrigin -> {0, 0},
 ColorOutput -> (RGBColor[0.316411, 0.699229, 0.0585946] &)];


 Show[collage2[Point[{0, 0}], 8]]

enter image description here

I took this from enter image description here

enter image description here


I've got a package that makes dealing with iterated function systems pretty easy. You can download it off of my webspace. That package implements both deterministic and stochastic alorithms to generate images of self-affine sets like the Barnesly fern

Also, I think we can use a better initial shape than an oval. Let's use the functions of the IFS to obtain an outline of the set:

barnsleyFernIFS = {
   {{{.85, .04}, {-.04, .85}}, {0, 1.6}},
   {{{-.15, .28}, {.26, .24}}, {0, .44}},
   {{{.2, -.26}, {.23, .22}}, {0, 1.6}},
   {{{0, 0}, {0, .16}}, {0, 0}}};
toFunction[{A_, b_}] := A.# + b &;
{f1, f2, f3, f4} = toFunction /@ barnsleyFernIFS;
tip = {x, y} /. First[Solve[f1[{x, y}] == {x, y}, {x, y}]];
leftSide = NestList[f1, f2[tip], 30];
rightSide = NestList[f1, f3[tip], 30];
outline = Join[{{0, 0}}, rightSide, {tip}, Reverse[leftSide]];
init = {EdgeForm[Black], Polygon[outline]};
Graphics[{Gray, init}]

enter image description here

Now, if you have the package above installed, you can do the following:

Needs["FractalGeometry`IteratedFunctionSystems`"];
pics = Table[
   ShowIFS[barnsleyFernIFS, k, Initiator -> init, Colors -> 
     {Darker[Green], Green, Green, Black}], {k, 1, 4}];
GraphicsRow[pics]

enter image description here

The result illustrates a difficulty with this approach when the pieces of the attractor have different sizes like this. The ShowIFS command implements another version of the deterministic algorithm where the pieces are decomposed until they reach a certain size, rather than a certain depth. To access this approach, we simply make the second argument a real number smaller than one to indicate how small we want the sizes to be - rather than an integer indicating the depth. This allows us to generate a picture like so:

init = {EdgeForm[Opacity[0.3]], Polygon[outline]};
ShowIFS[barnsleyFernIFS, 0.02, Initiator -> init, Colors -> 
  {Darker[Green], Green, Green, Black}]

enter image description here

If you'd like to illustrate how this process works, it probably makes the most sense to do so dynamically:

Manipulate[
  ShowIFS[barnsleyFernIFS, r, Initiator -> init, Colors -> 
    {Darker[Green], Green, Green, Black}],
   {{r, 0.9}, 0.1, 0.9}]

This allows you to see the decomposition happen as you move the slider down.