""" ```julia legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax, inout) ``` Return `(x,y)` at an angle `theta` degrees from `(xcenter,ycenter)` on a rectangle defined by (`xmin`, `xmax`, `ymin`, `ymax`). """ function legend_pos_from_angle(theta, xmin, xcenter, xmax, ymin, ycenter, ymax) (s, c) = sincosd(theta) x = c < 0 ? (xmin - xcenter) / c : (xmax - xcenter) / c y = s < 0 ? (ymin - ycenter) / s : (ymax - ycenter) / s A = min(x, y) return (xcenter + A * c, ycenter + A * s) end """ Split continuous range `[-1,1]` evenly into an integer `[1,2,3]` """ function legend_anchor_index(x) x < -1 // 3 && return 1 x < 1 // 3 && return 2 return 3 end """ Turn legend argument into a (theta, :inner) or (theta, :outer) tuple. For backends where legend position is given in normal coordinates (0,0) -- (1,1), so :topleft exactly corresponds to (45, :inner) etc. If `leg` is a (::Real,::Real) tuple, keep it as is. """ legend_angle(leg::Real) = (leg, :inner) legend_angle(leg::Tuple{S,T}) where {S<:Real,T<:Real} = leg legend_angle(leg::Tuple{S,Symbol}) where {S<:Real} = leg legend_angle(leg::Symbol) = get( ( topleft = (135, :inner), top = (90, :inner), topright = (45, :inner), left = (180, :inner), right = (0, :inner), bottomleft = (225, :inner), bottom = (270, :inner), bottomright = (315, :inner), outertopleft = (135, :outer), outertop = (90, :outer), outertopright = (45, :outer), outerleft = (180, :outer), outerright = (0, :outer), outerbottomleft = (225, :outer), outerbottom = (270, :outer), outerbottomright = (315, :outer), ), leg, (45, :inner), )