:straightline seriestype and gr implementation

This commit is contained in:
Daniel Schwabeneder 2018-03-18 23:15:45 +01:00
parent 047a13a8dc
commit bffd9bcb53
4 changed files with 63 additions and 25 deletions

View File

@ -287,8 +287,8 @@ end
function expand_extrema!(ex::Extrema, v::Number)
ex.emin = NaNMath.min(v, ex.emin)
ex.emax = NaNMath.max(v, ex.emax)
ex.emin = isfinite(v) ? min(v, ex.emin) : ex.emin
ex.emax = isfinite(v) ? max(v, ex.emax) : ex.emax
ex
end
@ -303,8 +303,8 @@ expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number}
ex = axis[:extrema]
ex.emin = NaNMath.min(v[1], ex.emin)
ex.emax = NaNMath.max(v[2], ex.emax)
ex.emin = isfinite(v[1]) ? min(v[1], ex.emin) : ex.emin
ex.emax = isfinite(v[2]) ? max(v[2], ex.emax) : ex.emax
ex
end
function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
@ -326,6 +326,9 @@ function expand_extrema!(sp::Subplot, d::KW)
else
letter == :x ? :y : letter == :y ? :x : :z
end]
if letter != :z && d[:seriestype] == :straightline && any(series[:seriestype] != :straightline for series in series_list(sp)) && data[1] != data[2]
data = [NaN]
end
axis = sp[Symbol(letter, "axis")]
if isa(data, Volume)

View File

@ -48,7 +48,7 @@ const _gr_attr = merge_with_base_supported([
:contour_labels,
])
const _gr_seriestype = [
:path, :scatter,
:path, :scatter, :straightline,
:heatmap, :pie, :image,
:contour, :path3d, :scatter3d, :surface, :wireframe,
:shape
@ -1014,7 +1014,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
x, y = convert_to_polar(x, y, (rmin, rmax))
end
if st in (:path, :scatter)
if st == :straightline
x, y = straightline_data(sp, series)
end
if st in (:path, :scatter, :straightline)
if length(x) > 1
lz = series[:line_z]
segments_iterator = if lz != nothing && length(lz) > 1
@ -1036,7 +1040,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
# draw the line(s)
if st == :path
if st in (:path, :straightline)
for (i, rng) in enumerate(segments_iterator)
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(sp, series, i)) #, series[:linealpha])
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
@ -1295,7 +1299,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
st == :shape && gr_polyline(x, y)
end
if st == :path
if st in (:path, :straightline)
GR.settransparency(gr_alpha(series[:linealpha]))
if series[:fillrange] == nothing || series[:ribbon] != nothing
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])

View File

@ -79,28 +79,26 @@ function hvline_limits(axis::Axis)
end
@recipe function f(::Type{Val{:hline}}, x, y, z)
xmin, xmax = hvline_limits(plotattributes[:subplot][:xaxis])
n = length(y)
newx = repmat(Float64[xmin, xmax, NaN], n)
newx = repmat(Float64[-1, 1, NaN], n)
newy = vec(Float64[yi for i=1:3,yi=y])
x := newx
y := newy
seriestype := :path
seriestype := :straightline
()
end
@deps hline path
@deps hline straightline
@recipe function f(::Type{Val{:vline}}, x, y, z)
ymin, ymax = hvline_limits(plotattributes[:subplot][:yaxis])
n = length(y)
newx = vec(Float64[yi for i=1:3,yi=y])
newy = repmat(Float64[ymin, ymax, NaN], n)
newy = repmat(Float64[-1, 1, NaN], n)
x := newx
y := newy
seriestype := :path
seriestype := :straightline
()
end
@deps vline path
@deps vline straightline
# ---------------------------------------------------------------------------
# path and scatter
@ -999,15 +997,7 @@ end
# -------------------------------------------------
"Adds a+bx... straight line over the current plot, without changing the axis limits"
function abline!(plt::Plot, a, b; kw...)
xl, yl = xlims(plt), ylims(plt)
x1, x2 = max(xl[1], (yl[1] - b)/a), min(xl[2], (yl[2] - b)/a)
if x2 > x1
plot!(plt, x -> b + a*x, x1, x2; kw...)
else
nothing
end
end
abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...)
abline!(args...; kw...) = abline!(current(), args...; kw...)

View File

@ -1079,3 +1079,44 @@ function convert_sci_unicode(label::AbstractString)
end
label
end
function straightline_data(sp::Subplot, series::Series)
xl, yl = isvertical(series.d) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
x, y = series[:x], series[:y]
n = length(x)
if n == 2
return straightline_data(xl, yl, x, y)
else
k, r = divrem(n, 3)
if r == 0
xdata, ydata = fill(NaN, n), fill(NaN, n)
for i in 1:k
inds = (3 * i - 2):(3 * i - 1)
xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds])
end
return xdata, ydata
else
error("Misformed data. `straightline_data` either accepts vectors of length 2 or 3k. The provided series has length $n")
end
end
end
function straightline_data(xl, yl, x, y)
if y[1] == y[2]
if x[1] == x[2]
error("Two identical points cannot be used to describe a straight line.")
else
return [xl[1], xl[2]], [y[1], y[2]]
end
elseif x[1] == x[2]
return [x[1], x[2]], [yl[1], yl[2]]
else
# get a and b from the line y = a * x + b through the points given by
# the coordinates x and x
b = y[1] - (y[1] - y[2]) * x[1] / (x[1] - x[2])
a = (y[1] - y[2]) / (x[1] - x[2])
# get the data values
xdata = [clamp(x[1] + (x[1] - x[2]) * (ylim - y[1]) / (y[1] - y[2]), xl...) for ylim in yl]
return xdata, a .* xdata .+ b
end
end