Produce a graphical or ASCII-art representation of a Sierpinski pentagon (aka a Pentaflake) of order 5. Your code should also be able to correctly generate representations of lower orders: 1 to 4.





See also
 Sierpinski pentagon


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

Ihandle dlg, canvas
cdCanvas cddbuffer

constant title = "Sierpinski Pentagon",
         scale_factor = 1/(2+cos(2*PI/5)*2),
         side_factor = 1+cos(2*PI/5)*2,
         angles = sq_mul(2*PI/5,tagset(7,3)),
         cosangles = apply(angles,cos),
         sinangles = apply(angles,sin)

integer level = 3

procedure drawPentagon(atom x, y, side, w, h, integer depth)
    if depth=0 then
        cdCanvasBegin(cddbuffer,CD_FILL)
        for i=1 to 5 do
            x += cosangles[i] * side
            y -= sinangles[i] * side
            cdCanvasVertex(cddbuffer, w+x, h-y)
        end for
        cdCanvasEnd(cddbuffer)
    else
        side *= scale_factor
        atom distance = side*side_factor
        for i=1 to 5 do
            x += cosangles[i] * distance
            y -= sinangles[i] * distance
            drawPentagon(x, y, side, w, h, depth-1)
        end for
    end if
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
    atom hw = min(w/2,h/2),
         margin = 20,
         radius = hw - 2*margin,
         side = radius * sin(PI/5) * 2
    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    drawPentagon(hw, 3*margin, side, w/2-radius-2*margin, h, level)
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

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

procedure set_dlg_title()
    IupSetStrAttribute(dlg, "TITLE", "%s (level %d)",{title,level})
end procedure

function key_cb(Ihandle /*ih*/, atom c)
    if c=K_ESC then return IUP_CLOSE end if
    if find(c,"+-") then
        if c='+' then
            level = min(5,level+1)
        elsif c='-' then
            level = max(0,level-1)
        end if
        set_dlg_title()
        IupRedraw(canvas)
    end if
    return IUP_CONTINUE
end function

procedure main()
    IupOpen()
    canvas = IupCanvas("RASTERSIZE=640x640")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})
    dlg = IupDialog(canvas)
    IupSetCallback(dlg, "KEY_CB", Icallback("key_cb"))
    set_dlg_title()
    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()
