JuliaGraphics / Luxor.jl

Simple drawings using vector graphics; Cairo "for tourists!"
http://juliagraphics.github.io/Luxor.jl/
Other
576 stars 72 forks source link

Small circles does not have enough precision #268

Closed hyrodium closed 10 months ago

hyrodium commented 11 months ago

MWE

using Luxor

@svg begin
    setline(0.1)
    for r in 1:10
        circle(Point(0, 0), r, action = :stroke)
    end
    sethue(1,0,0)
    rotate(deg2rad(22.5))
    for r in 1:10
        circle(Point(0, 0), r, action = :stroke)
    end
end 50 50 "b.svg"

Generated image: b

Magnified image: image

There are 10 circles in the image, and the small five circles does not have enough precision.

Detail

There are four bezier segments for circles with a radius larger than 5, but if the radius is less or equal to 5, the number of segments will be two.

The following image is a screenshot with Inkscape. image

I think this behavior is due to Cairo because the circle function just calls Cairo.arc(_get_current_cr(), x, y, r, 0, 2pi). https://github.com/JuliaGraphics/Luxor.jl/blob/375bb999e04f0ec5fcf14af82d5bd4188378bdc2/src/curves.jl#L3-L11

How to fix

Update the definition of circle will solve the problem.

function circle(x::Real, y::Real, r::Real;
    action = :none)
    if action != :path
        newpath()
    end
    Cairo.arc(_get_current_cr(), x, y, r, 0, pi/2)
    Cairo.arc(_get_current_cr(), x, y, r, pi/2, pi)
    Cairo.arc(_get_current_cr(), x, y, r, pi, 3pi/2)
    Cairo.arc(_get_current_cr(), x, y, r, 3pi/2, 2pi)
    do_action(action)
    return (Point(x, y) - (r, r), Point(x, y) + (r, r))
end

image

If this fix is the right way, I'm happy to make a PR!

cormullion commented 11 months ago

Good idea! These circles are pretty small - I wonder whether the Cairo routines (https://github.com/ImageMagick/cairo/blob/main/src/cairo-arc.c might be the one) aren't so accurate for very small radii...

Anyway, your suggested code/fix looks good!

cormullion commented 10 months ago

@hyrodium I'm going to get another release out this week - do you want to make a PR for these circles?

hyrodium commented 10 months ago

Sorry for the late reply. I opened #269!

cormullion commented 10 months ago

Cool! Thanks!

cormullion commented 10 months ago

I'll add a closepath() as well so that the path ends are correctly mitred...

Screenshot 2023-09-06 at 09 15 55