introduce iter_segments(series::Series) considering certain vector series attributes

This commit is contained in:
Daniel Schwabeneder 2018-03-31 18:18:58 +02:00
parent b57abfd563
commit 1b5240a513
2 changed files with 31 additions and 13 deletions

View File

@ -1021,16 +1021,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if st in (:path, :scatter, :straightline)
if length(x) > 1
lz = series[:line_z]
segments_iterator = if lz != nothing && length(lz) > 1
[i:(i + 1) for i in 1:(length(x) - 1)]
else
iter_segments(x, y)
end
segments = iter_segments(series)
# do area fill
if frng != nothing
GR.setfillintstyle(GR.INTSTYLE_SOLID)
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
for (i, rng) in enumerate(segments_iterator)
for (i, rng) in enumerate(segments)
gr_set_fillcolor(get_fillcolor(series, i))
fx = _cycle(x, vcat(rng, reverse(rng)))
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
@ -1041,7 +1037,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# draw the line(s)
if st in (:path, :straightline)
for (i, rng) in enumerate(segments_iterator)
for (i, rng) in enumerate(segments)
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(series, i)) #, series[:linealpha])
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
gr_polyline(x[rng], y[rng]; arrowside = arrowside)
@ -1119,12 +1115,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
if st == :path3d
if length(x) > 1
lz = series[:line_z]
segments_iterator = if lz != nothing && length(lz) > 1
[i:(i + 1) for i in 1:(length(x) - 1)]
else
iter_segments(x, y, z)
end
for (i, rng) in enumerate(segments_iterator)
segments = iter_segments(series)
for (i, rng) in enumerate(segments)
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(series, i)) #, series[:linealpha])
GR.polyline3d(x[rng], y[rng], z[rng])
end

View File

@ -192,6 +192,20 @@ function iter_segments(args...)
SegmentsIterator(tup, n)
end
function iter_segments(series::Series)
x, y, z = series[:x], series[:y], series[:z]
if has_attribute_segments(series)
return [i:(i + 1) for i in 1:(length(y) - 1)]
else
segs = UnitRange{Int64}[]
args = is3d(series) ? (x, y, z) : (x, y)
for seg in iter_segments(args...)
push!(segs, seg)
end
return segs
end
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args::Tuple) = any(a -> !isfinite(_cycle(a,i)), args)
anynan(istart::Int, iend::Int, args::Tuple) = any(i -> anynan(i, args), istart:iend)
@ -631,6 +645,18 @@ function get_fillcolor(series::Series, i::Int = 1)
end
end
function has_attribute_segments(series::Series)
# we want to check if a series needs to be split into segments just because
# of its attributes
for letter in (:x, :y, :z)
# If we have NaNs in the data they define the segments and
# SegmentsIterator is used
NaN in series[letter] && return false
end
# ... else we check relevant attributes if they have multiple inputs
return any((typeof(series[attr]) <: AbstractVector && length(series[attr] > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :fillcolor, :fillalpha])
end
# ---------------------------------------------------------------
makekw(; kw...) = KW(kw)