|
54 | 54 | xs, ys |
55 | 55 | end |
56 | 56 |
|
| 57 | +## Plot recipe |
| 58 | +## define a heuristic to work around asymptotes |
| 59 | +## just sort of successful |
| 60 | +@recipe function f(pq::AbstractRationalFunction{T}, a=nothing, b=nothing) where {T} |
| 61 | + |
| 62 | + xlims = get(plotattributes, :xlims, (nothing, nothing)) |
| 63 | + ylims = get(plotattributes, :ylims, (nothing, nothing)) |
| 64 | + rational_function_trim(pq, a, b, xlims, ylims) |
| 65 | + |
| 66 | +end |
| 67 | + |
| 68 | +isapproxreal(x::Real) = true |
| 69 | +isapproxreal(x::Complex{T}) where {T} = imag(x) <= sqrt(eps(real(T))) |
| 70 | +function toobig(pq) |
| 71 | + x -> begin |
| 72 | + y = pq(x) |
| 73 | + isinf(y) && return true |
| 74 | + isnan(y) && return true |
| 75 | + abs(y) > 1e8 && return true |
| 76 | + return false |
| 77 | + end |
| 78 | +end |
| 79 | + |
| 80 | +function rational_function_trim(pq, a, b, xlims, ylims) |
| 81 | + |
| 82 | + p,q = lowest_terms(//(pq...), method=:numerical) |
| 83 | + dpq = derivative(p//q) |
| 84 | + p′,q′ = lowest_terms(dpq) |
| 85 | + |
| 86 | + λs = Multroot.multroot(q).values |
| 87 | + λs = isempty(λs) ? λs : real.(filter(isapproxreal, λs)) |
| 88 | + |
| 89 | + cps = Multroot.multroot(p′).values |
| 90 | + cps = isempty(cps) ? cps : real.(filter(isapproxreal, cps)) |
| 91 | + cps = isempty(cps) ? cps : filter(!toobig(pq), cps) |
| 92 | + |
| 93 | + a = isnothing(a) ? xlims[1] : a |
| 94 | + b = isnothing(b) ? xlims[2] : b |
| 95 | + |
| 96 | + if isnothing(a) && isnothing(b) |
| 97 | + u= poly_interval(p) |
| 98 | + v= poly_interval(q) |
| 99 | + a,b = min(first(u), first(v)), max(last(u), last(v)) |
| 100 | + |
| 101 | + if !isempty(λs) |
| 102 | + a,b = min(a, real(minimum(λs))), max(b, real(maximum(λs))) |
| 103 | + end |
| 104 | + if !isempty(cps) |
| 105 | + a,b = min(a, real(minimum(cps))), max(b, real(maximum(cps))) |
| 106 | + end |
| 107 | + a *= (a > 0 ? 1/1.5 : 1.25) |
| 108 | + b *= (b < 0 ? 1/1.5 : 1.25) |
| 109 | + end |
| 110 | + |
| 111 | + n = 601 |
| 112 | + xs = range(a,stop=b, length=n) |
| 113 | + ys = pq.(xs) |
| 114 | + Mcps = isempty(cps) ? 5 : 3*maximum(abs, pq.(cps)) |
| 115 | + M = max(5, Mcps, 1.25*maximum(abs, pq.((a,b)))) |
| 116 | + |
| 117 | + lo = isnothing(ylims[1]) ? -M : ylims[1] |
| 118 | + hi = isnothing(ylims[2]) ? M : ylims[2] |
| 119 | + ys′ = [lo <= yᵢ <= hi ? yᵢ : NaN for yᵢ ∈ ys] |
| 120 | + xs, ys′ |
| 121 | + |
| 122 | +end |
57 | 123 | end |
0 commit comments