Simpler Yin-Yang?

I wanted to draw the Yin-Yang symbol in Luxor.jl.
Here’s what I came up with. Can this be done more idiomatic?
I would have preferred the white “eye” of the black “fish” to be just a cut-out rather than over-plotting with white. However, I was not able to figure out how.

using Luxor
R = 128
@png begin
    move(Point(0,-R))                            # start at top
    arc(Point(0,0), R, -pi/2, pi/2, :path)       # right side arc to bottom
    arc(Point(0,R/2), R/2, pi/2, -pi/2, :path)   # small arc up
    carc(Point(0,-R/2), R/2,  pi/2, -pi/2,:path) # small arc counter-clockwise
    fillpath()
    circle(Point(0,0), R, action=:stroke)        # large circle
    circle(Point(0,-R/2), R/8, action=:fill)     # white fish eye
    sethue("white")
    circle(Point(0,R/2), R/8, action=:fill)      # black fish eye
end 

4 Likes

My eye doesn’t like the discontinuity in the second derivative that arises when you glue two arcs together. Maybe a spline would be better?

9 Likes

Your version is fine. You could add a circular hole as a subpath of the shape:

R = 220
function y()
    arc(O, R, 0, π)
    arc(O - (R/2, 0), R/2, π, 0)
    carc(O + (R/2, 0), R/2, π, 0)
    newsubpath()
    circlepath(O - (R/2, 0), R/5, reversepath=false)
end

@draw begin
    background("maroon")
    for i in 1:2
        sethue(["black", "white"][i])
        y()
        fillpath()
        rotate(π)
    end
end

But I can’t think of a way to smooth out that jump from one semicircle to the next…

8 Likes

Thank you @cormullion - and thank you for all your work on Luxor.jl!

Do you have a reference for the R/5 radius of the “fish eye”?
I found references for R/8 and R/6:

Is this too simple to add to the Examples? I see now that there is an example of circlepath just above Draw simple shapes · Luxor, so it may be redundant. I’ll be happy to do a PR.

2 Likes

I must admit that I never used Luxor, but in Plots.jl this issue is minimised by asking the bounding lines to be transparent:

using Plots: plot, plot!, partialcircle as pc

R, n = 1.0, 1000
plot(pc(-pi/2, pi/2, n, R), ratio=1, fill=true, c=:black, legend=false)
plot!(map(x -> (0, -R/2) .+ x, pc(0, 2pi, n, R/2)), lc=:transparent, fill=true, c=:black, legend=false)
plot!(map(x -> (0,  R/2) .+ x, pc(0, 2pi, n, R/2)), lc=:transparent, fill=true, c=:white, legend=false)
plot!(map(x -> (0, -R/2) .+ x, pc(0, 2pi, n, R/8)), lc=:transparent, fill=true, c=:white, legend=false)
plot!(map(x -> (0,  R/2) .+ x, pc(0, 2pi, n, R/8)), lc=:transparent, fill=true, c=:black, legend=false)
plot!(pc(0, 2pi, n, R), lw=3, fill=false, c=:black, legend=false, ticks=false, showaxis=false)

3 Likes

Do you have a reference for the R/5 radius of the “fish eye”?

Just thought it looked OK - small holes can get filled in sometimes (like in fonts :slight_smile: )

Do you have a reference for the R/5 radius of the “fish eye”?
I found references for R/8 and R/6:

haha I didn’t think to look “in the literature”

I’ll be happy to do a PR.

Always welcome!

Looking at the transition:

@draw begin
    arc(O - (R/2, 0), R/2, π, 0)
    carc(O + (R/2, 0), R/2, π, 0)
    strokepath()
    arc(O - (R/2, 0), R/2, π, 0)
    carc(O + (R/2, 0), R/2, π, 0)
    for bp in pathtobezierpaths()
        for bps in bp
            @layer begin
                randomhue()
                circle.(bps, 5, :fill)
            end
            arrow(bps[1], bps[2])
            arrow(bps[4], bps[3])
        end
    end
end

Some way of moving the two central Bezier control points away from the vertical …:thinking:

2 Likes

Thanks @rafael.guerra . I had no idea Plots.jl could do this.

1 Like