Fix colorbar for misc. series types with line_z,fill_z,marker_z.

This commit is contained in:
yharel 2019-03-29 21:20:36 +03:00
parent 78059bf825
commit 8982a67902
2 changed files with 62 additions and 67 deletions

View File

@ -415,32 +415,30 @@ function gr_set_viewport_polar()
r r
end end
mutable struct GRColorbar struct GRColorbar
heatmapseries::Union{Series,Nothing} gradient::Ref{Union{Series,Nothing}}
fillseries::Union{Series,Nothing} fill::Ref{Union{Series,Nothing}}
linesseries::Union{Series,Nothing} lines::Ref{Union{Series,Nothing}}
GRColorbar() = new(nothing,nothing,nothing) GRColorbar() = new(nothing,nothing,nothing)
end end
function gr_update_colorbar!(cbar::GRColorbar, series::Series) function gr_update_colorbar!(cbar::GRColorbar, series::Series)
if iscontour(series) style = colorbar_style(series)
if isfilledcontour(series) style === nothing && return
cbar.fillseries = series ref = style == cbar_gradient ? cbar.gradient :
else style == cbar_fill ? cbar.fill :
cbar.linesseries = series style == cbar_lines ? cbar.lines :
end error("Unknown colorbar style: $style.")
elseif series[:seriestype] == :heatmap if ref[] !== nothing
cbar.heatmapseries = series @warn "Overwriting colorbar entry"
end end
ref[] = series
end end
function gr_contour_levels(series::Series, clims) function gr_contour_levels(series::Series, clims)
levels = contour_levels(series, clims) levels = contour_levels(series, clims)
if isfilledcontour(series) if isfilledcontour(series)
# GR implicitly uses the maximal z value as the highest level # GR implicitly uses the maximal z value as the highest level
if levels[end] < clims[2]
@warn("GR: highest contour level less than maximal z value is not supported.")
end
levels = levels[1:end-1] levels = levels[1:end-1]
end end
levels levels
@ -471,16 +469,22 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
gr_set_viewport_cmap(sp) gr_set_viewport_cmap(sp)
GR.setscale(0) GR.setscale(0)
GR.setwindow(xmin, xmax, zmin, zmax) GR.setwindow(xmin, xmax, zmin, zmax)
if (hm = cbar.heatmapseries) !== nothing if (series = cbar.gradient[]) !== nothing
gr_set_gradient!(hm) gr_set_gradient(series)
# TODO should use z limits of the specific series
GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255)
end end
if (series = cbar.fillseries) !== nothing if (series = cbar.fill[]) !== nothing
gr_set_gradient!(cbar.fillseries) gr_set_gradient(series)
GR.setfillintstyle(GR.INTSTYLE_SOLID) GR.setfillintstyle(GR.INTSTYLE_SOLID)
levels = contour_levels(series, clims) levels = contour_levels(series, clims)
# GR implicitly uses the maximal z value as the highest level
if levels[end] < clims[2]
@warn("GR: highest contour level less than maximal z value is not supported.")
# replace levels, rather than assign to levels[end], to ensure type
# promotion in case levels is an integer array
levels = [levels[1:end-1]; clims[2]]
end
colors = gr_colorbar_colors(series, clims) colors = gr_colorbar_colors(series, clims)
for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors)
GR.setfillcolorind(color) GR.setfillcolorind(color)
@ -488,8 +492,8 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
end end
end end
if (series = cbar.linesseries) !== nothing if (series = cbar.lines[]) !== nothing
gr_set_gradient!(series) gr_set_gradient(series)
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims))
levels = contour_levels(series, clims) levels = contour_levels(series, clims)
colors = gr_colorbar_colors(series, clims) colors = gr_colorbar_colors(series, clims)
@ -557,18 +561,18 @@ function gr_set_gradient(c)
grad grad
end end
function gr_set_gradient!(series::Series) function gr_set_gradient(series::Series)
st = series[:seriestype] st = series[:seriestype]
if st in (:surface, :heatmap) || isfilledcontour(series) if st in (:surface, :heatmap) || isfilledcontour(series)
gr_set_gradient(series[:fillcolor]) gr_set_gradient(series[:fillcolor])
elseif st in (:contour, :wireframe) elseif st in (:contour, :wireframe)
gr_set_gradient(series[:linecolor]) gr_set_gradient(series[:linecolor])
elseif series[:marker_z] != nothing elseif series[:marker_z] != nothing
series[:markercolor] = gr_set_gradient(series[:markercolor]) gr_set_gradient(series[:markercolor])
elseif series[:line_z] != nothing elseif series[:line_z] != nothing
series[:linecolor] = gr_set_gradient(series[:linecolor]) gr_set_gradient(series[:linecolor])
elseif series[:fill_z] != nothing elseif series[:fill_z] != nothing
series[:fillcolor] = gr_set_gradient(series[:fillcolor]) gr_set_gradient(series[:fillcolor])
end end
end end
@ -778,7 +782,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
data_lims = gr_xy_axislims(sp) data_lims = gr_xy_axislims(sp)
end end
hascolorbar(series) && gr_update_colorbar!(cbar,series) gr_update_colorbar!(cbar,series)
end end
# set our plot area view # set our plot area view
@ -1046,8 +1050,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
for (idx, series) in enumerate(series_list(sp)) for (idx, series) in enumerate(series_list(sp))
st = series[:seriestype] st = series[:seriestype]
# update the current stored gradient and the series # update the current stored gradient
gr_set_gradient!(series) gr_set_gradient(series)
GR.savestate() GR.savestate()

View File

@ -584,55 +584,46 @@ end
_update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
function hascolorbar(series::Series) @enum ColorbarStyle cbar_gradient cbar_fill cbar_lines
if get(series, :colorbar_entry, true) == false
return false function colorbar_style(series::Series)
colorbar_entry = series[:colorbar_entry]
if !(colorbar_entry isa Bool)
@warn "Non-boolean colorbar_entry ignored."
colorbar_entry = true
end end
st = series[:seriestype]
hascbar = st == :heatmap if !colorbar_entry
if st == :contour nothing
hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1) elseif isfilledcontour(series)
cbar_fill
elseif iscontour(series)
cbar_lines
elseif series[:seriestype] (:heatmap,:surface) ||
any(series[z] !== nothing for z [:marker_z,:line_z,:fill_z])
cbar_gradient
else
nothing
end end
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
end
# no colorbar if we are creating a surface LightSource
if xor(st == :surface, series[:fill_z] != nothing)
hascbar = true
end
return hascbar
end end
function hascolorbar(sp::Subplot) hascolorbar(series::Series) = colorbar_style(series) !== nothing
cbar = sp[:colorbar] hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
hascbar = false
if cbar != :none
for series in series_list(sp)
if hascolorbar(series)
hascbar = true
end
end
end
hascbar
end
iscontour(series::Series) = series[:seriestype] == :contour iscontour(series::Series) = series[:seriestype] == :contour
isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing
function contour_levels(series::Series, clims) function contour_levels(series::Series, clims)
if iscontour(series) iscontour(series) || error("Not a contour series")
zmin, zmax = clims zmin, zmax = clims
levels = series[:levels] levels = series[:levels]
if levels isa Integer if levels isa Integer
levels = range(zmin, stop=zmax, length=levels+2) levels = range(zmin, stop=zmax, length=levels+2)
if !isfilledcontour(series) if !isfilledcontour(series)
levels = levels[2:end-1] levels = levels[2:end-1]
end
end end
levels
else # including heatmap, surface
nothing
end end
levels
end end