Draw a Koch curve. See details: Koch curve

--
-- demo\rosetta\Koch_curve.exw
-- ===========================
--
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

integer ox = 0, oy = 0

procedure koch(atom x1, y1, x2, y2, integer iter)
    atom angle = -PI/3, -- -60 degrees
         x3 := (x1*2 + x2) / 3,
         y3 := (y1*2 + y2) / 3,
         x4 := (x1 + x2*2) / 3,
         y4 := (y1 + y2*2) / 3,
         x5 := x3 + (x4-x3)*cos(angle) + (y4-y3)*sin(angle),
         y5 := y3 - (x4-x3)*sin(angle) + (y4-y3)*cos(angle)
    if iter>0  then
        iter -= 1
        koch(x1, y1, x3, y3, iter)
        koch(x3, y3, x5, y5, iter)
        koch(x5, y5, x4, y4, iter)
        koch(x4, y4, x2, y2, iter)
    else
        cdCanvasVertex(cddbuffer, x1+ox, y1+oy)
        cdCanvasVertex(cddbuffer, x3+ox, y3+oy)
        cdCanvasVertex(cddbuffer, x5+ox, y5+oy)
        cdCanvasVertex(cddbuffer, x4+ox, y4+oy)
        cdCanvasVertex(cddbuffer, x2+ox, y2+oy)
    end if
end procedure
 
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    atom {w,h} = IupGetIntInt(canvas, "DRAWSIZE")
    if w>h then ox = floor((w-h)/2); w=h 
           else oy = floor((h-w)/2); h=w end if
    atom {x,y} = {w*0.05+w/6,h*0.05+h/4}
    {w,h} = {w*0.6,h*0.6}
    cdCanvasActivate(cddbuffer)
    cdCanvasBegin(cddbuffer, CD_OPEN_LINES)  
    koch(x,y,x+w/2,y+h,4)
    koch(x+w/2,y+h,x+w,y,4)
    koch(x+w,y,x,y,4)
    cdCanvasEnd(cddbuffer)
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_BLUE)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    
    canvas = IupCanvas("RASTERSIZE=512x512")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})

    dlg = IupDialog(canvas,`TITLE="Koch curve"`)

    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()
