Compose.jl has the radius of Forms tied to width

I was playing around with Compose.jl recently, when I realise that Forms that use a radius, such as circle have their radius tied to the width of the context window. See the two images and the code below for an example. As you can see, the first image fits nicely in the left and right halves of the image as I want, but in the second image, the radius fills to the width of the top and bottom halves, and the circle “exceeds” the respective halves.

besided
stacked

using Compose

set_default_graphic_size(10cm, 10cm)

function beside(left, right)
    compose(
        context(),
        (context(0, 0, 0.5, 1), left),
        (context(0.5, 0, 0.5, 1), right)
    )
end

function stack(top, btm)
    compose(
        context(),
        (context(0, 0, 1, 0.5), top),
        (context(0, 0.5, 1, 0.5), btm)
    )
end

c = circle()

besided = beside(c, c)
compose(
    context(),
    besided,
    (context(), rectangle(), fill("white"))
)
besided |> SVG("besided.svg")

stacked = stack(c, c)
compose(
    context(),
    stacked,
    (context(), rectangle(), fill("white"))
)
stacked |> SVG("stacked.svg")

The behavior seems to persist with other “radius based” Forms like star, ngon. I’m wondering if there is any way to tell the Form to always use the shorter side for the radius instead of only sticking to the width?

have their radius tied to the width of the context window

By default, that’s correct. But Compose actually has 4 size units: Context (cx, cy), relative (w, h), absolute (mm, pt etc), and recently Context (“relative position”) size (sx, sy)
(see Compose.jl#409). Units sx, sy are available in Compose 0.9.2.

This info would also be available in the Compose docs, but there’s an unresolved issue (Compose.jl#410) :grimacing:

Here’s your 2nd image with sy,sx units:

function stack(top, btm)
    compose(context(), fill(nothing), stroke("black"),
        (context(0, 0, 1, 0.5), top),
        (context(0, 0.5, 1, 0.5), btm)
    )
end

stack(circle(0.5w, 0.5h, 0.5sy), circle(0.5w, 0.5h, 0.5sx))

Compose_units

Thanks! Also I realised something really interesting. I can actually apply the min function on the relative units. So something like this will work:

c = circle(0.5w, 0.5h, min(0.5sx, 0.5sy))

beside(c, stack(c, c))

beside_stack

This allows me to always take the shorter side’s radius, regardless of dimensions of the context!

1 Like