
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




--
-- pwa\phix\BarnsleyFern.exw
-- =========================
--
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*canvas*/, integer /*posx*/, integer /*posy*/)
    atom x = 0, y = 0
    integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
    cdCanvasActivate(cddbuffer)
    for i=1 to 100000 do
        integer r = rand(100)
--      {x, y} = iff(r<=1? {             0,        0.16*y     } :
--               iff(r<=8? { 0.20*x-0.26*y, 0.23*x+0.22*y+1.60} :
--               iff(r<=15?{-0.15*x+0.28*y, 0.26*x+0.24*y+0.44} :
--                         { 0.85*x+0.04*y,-0.04*x+0.85*y+1.60})))
        if r<=1 then        {x, y} = {             0,        0.16*y     }
        elsif r<=8 then     {x, y} = { 0.20*x-0.26*y, 0.23*x+0.22*y+1.60}
        elsif r<=15 then    {x, y} = {-0.15*x+0.28*y, 0.26*x+0.24*y+0.44}
        else                {x, y} = { 0.85*x+0.04*y,-0.04*x+0.85*y+1.60}
        end if
        cdCanvasPixel(cddbuffer, width/2+x*50, y*50, CD_DARK_GREEN)
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

IupOpen()

canvas = IupCanvas(Icallback("redraw_cb"),"RASTERSIZE=340x540")
dlg = IupDialog(canvas,`TITLE="Barnsley Fern"`)

IupMap(dlg)
cdcanvas = cdCreateCanvas(CD_IUP, canvas)
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
IupShow(dlg)
if platform()!=JS then
    IupMainLoop()
    IupClose()
end if
