
A Barnsley fern is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS).



Task

Create this fractal fern, using the following transformations:

 ƒ1   (chosen 1% of the time)
        xn + 1 = 0
        yn + 1 = 0.16 yn

 ƒ2   (chosen 85% of the time)
        xn + 1 = 0.85 xn + 0.04 yn
        yn + 1 = −0.04 xn + 0.85 yn + 1.6

 ƒ3   (chosen 7% of the time)
        xn + 1 = 0.2 xn − 0.26 yn
        yn + 1 = 0.23 xn + 0.22 yn + 1.6

 ƒ4   (chosen 7% of the time)
        xn + 1 = −0.15 xn + 0.28 yn
        yn + 1 = 0.26 xn + 0.24 yn + 0.44.

Starting position: x = 0, y = 0




 
MODULE BarnsleyFern;
(**
	Oxford Oberon-2
**)
 
	IMPORT Random, XYplane;
 
	VAR
		a1, b1, c1, d1, e1, f1, p1: REAL;
		a2, b2, c2, d2, e2, f2, p2: REAL;
		a3, b3, c3, d3, e3, f3, p3: REAL;
		a4, b4, c4, d4, e4, f4, p4: REAL;
		X, Y: REAL;
		x0, y0, e: INTEGER;
 
	PROCEDURE Draw;
		VAR x, y: REAL; xi, eta: INTEGER; rn: REAL;
	BEGIN
		REPEAT
			rn := Random.Uniform();
			IF rn < p1 THEN
				x := a1 * X + b1 * Y + e1; y := c1 * X + d1 * Y + f1
			ELSIF rn < (p1 + p2) THEN
				x := a2 *X + b2 * Y + e2; y := c2 * X + d2 * Y + f2
			ELSIF rn < (p1 + p2 + p3) THEN
				x := a3 * X + b3 * Y + e3; y := c3 * X + d3 * Y + f3
			ELSE
				x := a4 * X + b4 * Y + e4; y := c4 * X + d4 * Y + f4
			END;
			X := x; xi := x0 + SHORT(ENTIER(X * e));
			Y := y; eta := y0 + SHORT(ENTIER(Y * e));
			XYplane.Dot(xi, eta, XYplane.draw)
		UNTIL "s" = XYplane.Key()
	END Draw;
 
	PROCEDURE Init;
	BEGIN
		X := 0; Y := 0;
		x0 := 120; y0 := 0; e := 25;
 
		a1 := 0.00; a2 :=  0.85; a3 :=  0.20; a4 := -0.15;
		b1 := 0.00; b2 :=  0.04; b3 := -0.26; b4 :=  0.28;
		c1 := 0.00; c2 := -0.04; c3 :=	0.23; c4 :=  0.26;
		d1 := 0.16; d2 :=  0.85; d3 :=	0.22; d4 :=	 0.24;
		e1 := 0.00; e2 :=  0.00; e3 :=	0.00; e4 :=  0.00;
		f1 := 0.00; f2 :=  1.60; f3 :=	1.60; f4 :=  0.44;
		p1 := 0.01; p2 :=  0.85; p3 :=	0.07; p4 :=	 0.07;
		XYplane.Open;
	END Init;
 
BEGIN
	Init;Draw
END BarnsleyFern.
 