diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 648e55be..e60ea894 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -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 diff --git a/src/utils.jl b/src/utils.jl index 5ec52c4a..7b615759 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -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)