How to Draw an Ellipse or Circle on Dialog Canvas v1.3-rc1

Hi all,

Here is one way to make an ellipse with the new graphics context feature in version 1.3-rc1:

screenCap

local function ellipse(ctx, xc, yc, w, h)
    -- local kappa = (math.sqrt(2.0) - 1.0) * 4.0 / 3.0
    local kappa = 0.5522847498307936

    -- Adjust depending on whether ellipse should
    -- display from top left corner, from center
    -- and radius, from center and and diameter,
    -- or from top left to bottom right corners.
    -- "extap" extent anchor or control point
    local extapw = w
    local extcpw = kappa * extapw
    local extaph = h
    local extcph = kappa * extaph

    local right = xc + extapw
    local left = xc - extapw
    local top = yc + extaph
    local bottom = yc - extaph

    ctx:beginPath()
    ctx:moveTo(right, yc)
    ctx:cubicTo(right, yc + extcph, xc + extcpw, top, xc, top)
    ctx:cubicTo(xc - extcpw, top, left, yc + extcph, left, yc)
    ctx:cubicTo(left, yc - extcph, xc - extcpw, bottom, xc, bottom)
    ctx:cubicTo(xc + extcpw, bottom, right, yc - extcph, right, yc)
    ctx:closePath()
end

local dlg = Dialog { title = "Canvas Ellipse" }

dlg:canvas {
    width = 256,
    height = 256,
    onpaint = function(ev)
        local ctx = ev.context

        local xc = ctx.width * 0.5
        local yc = ctx.height * 0.5
        local w = 64
        local h = w * (9 / 16)

        ctx.antialias = true

        ctx.strokeWidth = 2.0
        ctx.color = Color { r = 255, g = 0, b = 127 }
        ellipse(ctx, xc, yc, w, h)
        ctx:stroke()
    end
}

dlg:show { wait = false }

The idea is to approximate the circle with four cubic Bezier curves and the magic number kappa, (math.sqrt(2.0) - 1.0) * 4.0 / 3.0.

The exact variables depend on whether you want w and h to be radii or diameters; whether you want to draw from the top-left corner or center by w and h; or draw from top-left to bottom-right corner. A circle would be an ellipse with equal width and height.

Appearance will vary with screen scaling.

Cheers,
Jeremy

3 Likes