extract gr_draw_<seriestype> functions
This commit is contained in:
parent
44bd1812e0
commit
51527705de
@ -333,35 +333,6 @@ function gr_draw_marker(series, xi, yi, clims, i, msize, strokewidth, shape::Sym
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# draw the markers, one at a time
|
|
||||||
function gr_draw_markers(
|
|
||||||
series::Series,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
clims,
|
|
||||||
msize = series[:markersize],
|
|
||||||
strokewidth = series[:markerstrokewidth],
|
|
||||||
)
|
|
||||||
|
|
||||||
isempty(x) && return
|
|
||||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
|
||||||
|
|
||||||
shapes = series[:markershape]
|
|
||||||
if shapes != :none
|
|
||||||
for (i, rng) in enumerate(iter_segments(series, :scatter))
|
|
||||||
rng = intersect(eachindex(x), rng)
|
|
||||||
if !isempty(rng)
|
|
||||||
ms = get_thickness_scaling(series) * _cycle(msize, i)
|
|
||||||
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
|
|
||||||
shape = _cycle(shapes, i)
|
|
||||||
for j in rng
|
|
||||||
gr_draw_marker(series, _cycle(x, j), _cycle(y, j), clims, i, ms, msw, shape)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
function gr_set_line(lw, style, c, s) # s can be Subplot or Series
|
function gr_set_line(lw, style, c, s) # s can be Subplot or Series
|
||||||
@ -900,305 +871,25 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
# fill in the plot area background
|
# fill in the plot area background
|
||||||
gr_fill_plotarea(sp, viewport_plotarea)
|
gr_fill_plotarea(sp, viewport_plotarea)
|
||||||
|
|
||||||
cbar = GRColorbar()
|
|
||||||
|
|
||||||
draw_axes = sp[:framestyle] != :none
|
|
||||||
# axes_2d = true
|
|
||||||
for series in series_list(sp)
|
|
||||||
# st = series[:seriestype]
|
|
||||||
# if st in (:heatmap, :image)
|
|
||||||
# x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
|
|
||||||
# xy_lims = x[1], x[end], y[1], y[end]
|
|
||||||
# expand_extrema!(sp[:xaxis], x)
|
|
||||||
# expand_extrema!(sp[:yaxis], y)
|
|
||||||
# end
|
|
||||||
|
|
||||||
gr_update_colorbar!(cbar,series)
|
|
||||||
end
|
|
||||||
|
|
||||||
# set our plot area view
|
# set our plot area view
|
||||||
GR.setviewport(viewport_plotarea...)
|
GR.setviewport(viewport_plotarea...)
|
||||||
|
|
||||||
# these are the Axis objects, which hold scale, lims, etc
|
|
||||||
xaxis = sp[:xaxis]
|
|
||||||
yaxis = sp[:yaxis]
|
|
||||||
zaxis = sp[:zaxis]
|
|
||||||
|
|
||||||
# set the scale flags and window
|
# set the scale flags and window
|
||||||
gr_set_window(sp)
|
gr_set_window(sp, viewport_plotarea)
|
||||||
|
|
||||||
# draw the axes
|
# draw the axes
|
||||||
gr_draw_axes(sp, viewport_plotarea)
|
gr_draw_axes(sp, viewport_plotarea)
|
||||||
|
gr_add_title(sp, viewport_plotarea, viewport_subplot)
|
||||||
# add the guides
|
|
||||||
GR.savestate()
|
|
||||||
if sp[:title] != ""
|
|
||||||
gr_set_font(titlefont(sp), sp)
|
|
||||||
loc = sp[:titlelocation]
|
|
||||||
if loc == :left
|
|
||||||
xpos = viewport_plotarea[1]
|
|
||||||
halign = GR.TEXT_HALIGN_LEFT
|
|
||||||
elseif loc == :right
|
|
||||||
xpos = viewport_plotarea[2]
|
|
||||||
halign = GR.TEXT_HALIGN_RIGHT
|
|
||||||
else
|
|
||||||
xpos = gr_view_xcenter(viewport_plotarea)
|
|
||||||
halign = GR.TEXT_HALIGN_CENTER
|
|
||||||
end
|
|
||||||
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
|
|
||||||
gr_text(xpos, viewport_subplot[4], sp[:title])
|
|
||||||
end
|
|
||||||
|
|
||||||
GR.restorestate()
|
|
||||||
|
|
||||||
# this needs to be here to point the colormap to the right indices
|
# this needs to be here to point the colormap to the right indices
|
||||||
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
||||||
|
|
||||||
for (idx, series) in enumerate(series_list(sp))
|
# init the colorbar
|
||||||
st = series[:seriestype]
|
cbar = GRColorbar()
|
||||||
|
|
||||||
# update the current stored gradient
|
for series in series_list(sp)
|
||||||
gr_set_gradient(series)
|
gr_add_series(sp, series)
|
||||||
|
gr_update_colorbar!(cbar, series)
|
||||||
GR.savestate()
|
|
||||||
|
|
||||||
# update the bounding window
|
|
||||||
if ispolar(sp)
|
|
||||||
gr_set_viewport_polar(viewport_plotarea)
|
|
||||||
else
|
|
||||||
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
|
||||||
if xmax > xmin && ymax > ymin
|
|
||||||
GR.setwindow(xmin, xmax, ymin, ymax)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
x, y, z = series[:x], series[:y], series[:z]
|
|
||||||
frng = series[:fillrange]
|
|
||||||
|
|
||||||
clims = get_clims(sp, series)
|
|
||||||
|
|
||||||
# add custom frame shapes to markershape?
|
|
||||||
series_annotations_shapes!(series)
|
|
||||||
# -------------------------------------------------------
|
|
||||||
|
|
||||||
# recompute data
|
|
||||||
if typeof(z) <: Surface
|
|
||||||
z = vec(transpose_z(series, z.surf, false))
|
|
||||||
elseif ispolar(sp)
|
|
||||||
rmin, rmax = axis_limits(sp, :y)
|
|
||||||
if frng !== nothing
|
|
||||||
_, frng = convert_to_polar(x, frng, (rmin, rmax))
|
|
||||||
end
|
|
||||||
x, y = convert_to_polar(x, y, (rmin, rmax))
|
|
||||||
end
|
|
||||||
|
|
||||||
if st == :straightline
|
|
||||||
x, y = straightline_data(series)
|
|
||||||
end
|
|
||||||
|
|
||||||
if st in (:path, :scatter, :straightline)
|
|
||||||
if x !== nothing && length(x) > 1
|
|
||||||
lz = series[:line_z]
|
|
||||||
segments = iter_segments(series, st)
|
|
||||||
# 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)
|
|
||||||
fc = get_fillcolor(series, clims, i)
|
|
||||||
gr_set_fillcolor(fc)
|
|
||||||
fx = _cycle(x, vcat(rng, reverse(rng)))
|
|
||||||
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
|
|
||||||
gr_set_transparency(fc, get_fillalpha(series, i))
|
|
||||||
GR.fillarea(fx, fy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# draw the line(s)
|
|
||||||
if st in (:path, :straightline)
|
|
||||||
for (i, rng) in enumerate(segments)
|
|
||||||
lc = get_linecolor(series, clims, i)
|
|
||||||
gr_set_line(
|
|
||||||
get_linewidth(series, i), get_linestyle(series, i), lc, sp
|
|
||||||
)
|
|
||||||
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
|
|
||||||
arrowstyle = isa(series[:arrow], Arrow) ? series[:arrow].style : :simple
|
|
||||||
gr_set_fillcolor(lc)
|
|
||||||
gr_set_transparency(lc, get_linealpha(series, i))
|
|
||||||
gr_polyline(x[rng], y[rng]; arrowside = arrowside, arrowstyle = arrowstyle)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if series[:markershape] != :none
|
|
||||||
gr_draw_markers(series, x, y, clims)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st == :contour
|
|
||||||
GR.setspace(clims[1], clims[2], 0, 90)
|
|
||||||
GR.setlinetype(gr_linetype(get_linestyle(series)))
|
|
||||||
GR.setlinewidth(max(0, get_linewidth(series)) / gr_nominal_size(sp))
|
|
||||||
is_lc_black = let black=plot_color(:black)
|
|
||||||
plot_color(series[:linecolor]) in (black,[black])
|
|
||||||
end
|
|
||||||
h = gr_contour_levels(series, clims)
|
|
||||||
if series[:fillrange] !== nothing
|
|
||||||
if series[:fillcolor] != series[:linecolor] && !is_lc_black
|
|
||||||
@warn("GR: filled contour only supported with black contour lines")
|
|
||||||
end
|
|
||||||
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
|
|
||||||
else
|
|
||||||
coff = is_lc_black ? 0 : 1000
|
|
||||||
GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0))
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st in [:surface, :wireframe]
|
|
||||||
if st == :surface
|
|
||||||
if length(x) == length(y) == length(z)
|
|
||||||
GR.trisurface(x, y, z)
|
|
||||||
else
|
|
||||||
try
|
|
||||||
GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
|
||||||
catch
|
|
||||||
GR.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
GR.setfillcolorind(0)
|
|
||||||
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st == :volume
|
|
||||||
sp[:legend] = :none
|
|
||||||
GR.gr3.clear()
|
|
||||||
dmin, dmax = GR.gr3.volume(y.v, 0)
|
|
||||||
|
|
||||||
elseif st == :heatmap
|
|
||||||
zmin, zmax = clims
|
|
||||||
fillgrad = _as_gradient(series[:fillcolor])
|
|
||||||
if !ispolar(sp)
|
|
||||||
GR.setspace(clims..., 0, 90)
|
|
||||||
x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(series[:z]))
|
|
||||||
w, h = length(x) - 1, length(y) - 1
|
|
||||||
if is_uniformly_spaced(x) && is_uniformly_spaced(y)
|
|
||||||
# For uniformly spaced data use GR.drawimage, which can be
|
|
||||||
# much faster than GR.nonuniformcellarray, especially for
|
|
||||||
# pdf output, and also supports alpha values.
|
|
||||||
# Note that drawimage draws uniformly spaced data correctly
|
|
||||||
# even on log scales, where it is visually non-uniform.
|
|
||||||
colors = plot_color.(get(fillgrad, z, clims), series[:fillalpha])
|
|
||||||
rgba = gr_color.(colors)
|
|
||||||
GR.drawimage(first(x), last(x), last(y), first(y), w, h, rgba)
|
|
||||||
else
|
|
||||||
if something(series[:fillalpha],1) < 1
|
|
||||||
@warn "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored."
|
|
||||||
end
|
|
||||||
z_normalized = get_z_normalized.(z, zmin, zmax)
|
|
||||||
rgba = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
|
|
||||||
GR.nonuniformcellarray(x, y, w, h, rgba)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
phimin, phimax = 0.0, 360.0 # nonuniform polar array is not yet supported in GR.jl
|
|
||||||
nx, ny = length(series[:x]), length(series[:y])
|
|
||||||
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
|
||||||
GR.setwindow(-ymax, ymax, -ymax, ymax)
|
|
||||||
if ymin > 0
|
|
||||||
@warn "'ymin[1] > 0' (rmin) is not yet supported."
|
|
||||||
end
|
|
||||||
if series[:y][end] != ny
|
|
||||||
@warn "Right now only the maximum value of y (r) is taken into account."
|
|
||||||
end
|
|
||||||
# colors = get(fillgrad, z, clims)
|
|
||||||
# GR.polarcellarray(0, 0, phimin, phimax, ymin, ymax, nx, ny, colors)
|
|
||||||
z_normalized = get_z_normalized.(z, zmin, zmax)
|
|
||||||
# z_normalized = map(c -> c == invisible() ? 256/255 : PlotUtils.getinverse(fillgrad.colors, c), colors)
|
|
||||||
rgba = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
|
|
||||||
GR.polarcellarray(0, 0, phimin, phimax, 0, ymax, nx, ny, rgba)
|
|
||||||
# Right now only the maximum value of y (r) is taken into account.
|
|
||||||
# This is certainly not perfect but nonuniform polar array is not yet supported in GR.jl
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st in (:path3d, :scatter3d)
|
|
||||||
# draw path
|
|
||||||
if st == :path3d
|
|
||||||
if length(x) > 1
|
|
||||||
lz = series[:line_z]
|
|
||||||
segments = iter_segments(series, st)
|
|
||||||
for (i, rng) in enumerate(segments)
|
|
||||||
lc = get_linecolor(series, clims, i)
|
|
||||||
gr_set_line(
|
|
||||||
get_linewidth(series, i), get_linestyle(series, i), lc, sp
|
|
||||||
)
|
|
||||||
gr_set_transparency(lc, get_linealpha(series, i))
|
|
||||||
GR.polyline3d(x[rng], y[rng], z[rng])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# draw markers
|
|
||||||
if st == :scatter3d || series[:markershape] != :none
|
|
||||||
x2, y2 = RecipesPipeline.unzip(map(GR.wc3towc, x, y, z))
|
|
||||||
gr_draw_markers(series, x2, y2, clims)
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st == :shape
|
|
||||||
x, y = shape_data(series)
|
|
||||||
for (i,rng) in enumerate(iter_segments(x, y))
|
|
||||||
if length(rng) > 1
|
|
||||||
# connect to the beginning
|
|
||||||
rng = vcat(rng, rng[1])
|
|
||||||
|
|
||||||
# get the segments
|
|
||||||
xseg, yseg = x[rng], y[rng]
|
|
||||||
|
|
||||||
# draw the interior
|
|
||||||
fc = get_fillcolor(series, clims, i)
|
|
||||||
gr_set_fill(fc)
|
|
||||||
gr_set_transparency(fc, get_fillalpha(series, i))
|
|
||||||
GR.fillarea(xseg, yseg)
|
|
||||||
|
|
||||||
# draw the shapes
|
|
||||||
lc = get_linecolor(series, clims, i)
|
|
||||||
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc, sp)
|
|
||||||
gr_set_transparency(lc, get_linealpha(series, i))
|
|
||||||
GR.polyline(xseg, yseg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
elseif st == :image
|
|
||||||
z = transpose_z(series, series[:z].surf, true)'
|
|
||||||
x, y = heatmap_edges(series[:x], sp[:xaxis][:scale], series[:y], sp[:yaxis][:scale], size(z))
|
|
||||||
w, h = size(z)
|
|
||||||
xmin, xmax = ignorenan_extrema(x)
|
|
||||||
ymin, ymax = ignorenan_extrema(y)
|
|
||||||
rgba = gr_color.(z)
|
|
||||||
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
|
|
||||||
end
|
|
||||||
|
|
||||||
# this is all we need to add the series_annotations text
|
|
||||||
anns = series[:series_annotations]
|
|
||||||
for (xi,yi,str,fnt) in EachAnn(anns, x, y)
|
|
||||||
gr_set_font(fnt, sp)
|
|
||||||
gr_text(GR.wctondc(xi, yi)..., str)
|
|
||||||
end
|
|
||||||
|
|
||||||
if sp[:legend] == :inline && should_add_to_legend(series)
|
|
||||||
gr_set_font(legendfont(sp), sp)
|
|
||||||
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
|
|
||||||
if sp[:yaxis][:mirror]
|
|
||||||
(_,i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x)
|
|
||||||
GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF)
|
|
||||||
offset = -0.01
|
|
||||||
else
|
|
||||||
(_,i) = sp[:xaxis][:flip] ? findmin(x) : findmax(x)
|
|
||||||
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
|
||||||
offset = 0.01
|
|
||||||
end
|
|
||||||
(x_l,y_l) = GR.wctondc(x[i],y[i])
|
|
||||||
gr_text(x_l+offset,y_l,series[:label])
|
|
||||||
end
|
|
||||||
GR.restorestate()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# draw the colorbar
|
# draw the colorbar
|
||||||
@ -1208,16 +899,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
gr_add_legend(sp, leg, viewport_plotarea)
|
gr_add_legend(sp, leg, viewport_plotarea)
|
||||||
|
|
||||||
# add annotations
|
# add annotations
|
||||||
GR.savestate()
|
|
||||||
# update the bounding window
|
|
||||||
if ispolar(sp)
|
|
||||||
gr_set_viewport_polar(viewport_plotarea)
|
|
||||||
else
|
|
||||||
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
|
||||||
if xmax > xmin && ymax > ymin
|
|
||||||
GR.setwindow(xmin, xmax, ymin, ymax)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for ann in sp[:annotations]
|
for ann in sp[:annotations]
|
||||||
x, y, val = locate_annotation(sp, ann...)
|
x, y, val = locate_annotation(sp, ann...)
|
||||||
x, y = if RecipesPipeline.is3d(sp)
|
x, y = if RecipesPipeline.is3d(sp)
|
||||||
@ -1228,7 +909,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
gr_set_font(val.font, sp)
|
gr_set_font(val.font, sp)
|
||||||
gr_text(x, y, val.str)
|
gr_text(x, y, val.str)
|
||||||
end
|
end
|
||||||
GR.restorestate()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1479,17 +1159,21 @@ function gr_update_viewport_ratio!(viewport_plotarea, sp)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function gr_set_window(sp)
|
function gr_set_window(sp, viewport_plotarea)
|
||||||
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
if ispolar(sp)
|
||||||
scaleop = 0
|
gr_set_viewport_polar(viewport_plotarea)
|
||||||
if xmax > xmin && ymax > ymin
|
else
|
||||||
sp[:xaxis][:scale] == :log10 && (scaleop |= GR.OPTION_X_LOG)
|
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
||||||
sp[:yaxis][:scale] == :log10 && (scaleop |= GR.OPTION_Y_LOG)
|
scaleop = 0
|
||||||
sp[:xaxis][:flip] && (scaleop |= GR.OPTION_FLIP_X)
|
if xmax > xmin && ymax > ymin
|
||||||
sp[:yaxis][:flip] && (scaleop |= GR.OPTION_FLIP_Y)
|
sp[:xaxis][:scale] == :log10 && (scaleop |= GR.OPTION_X_LOG)
|
||||||
# NOTE: setwindow sets the "data coordinate" limits of the current "viewport"
|
sp[:yaxis][:scale] == :log10 && (scaleop |= GR.OPTION_Y_LOG)
|
||||||
GR.setwindow(xmin, xmax, ymin, ymax)
|
sp[:xaxis][:flip] && (scaleop |= GR.OPTION_FLIP_X)
|
||||||
GR.setscale(scaleop)
|
sp[:yaxis][:flip] && (scaleop |= GR.OPTION_FLIP_Y)
|
||||||
|
# NOTE: setwindow sets the "data coordinate" limits of the current "viewport"
|
||||||
|
GR.setwindow(xmin, xmax, ymin, ymax)
|
||||||
|
GR.setscale(scaleop)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1499,6 +1183,7 @@ function gr_fill_plotarea(sp, viewport_plotarea)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
## Axes
|
## Axes
|
||||||
|
|
||||||
function gr_draw_axes(sp, viewport_plotarea)
|
function gr_draw_axes(sp, viewport_plotarea)
|
||||||
@ -1769,6 +1454,310 @@ function gr_label_axis_3d(sp, letter)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function gr_add_title(sp, viewport_plotarea, viewport_subplot)
|
||||||
|
if sp[:title] != ""
|
||||||
|
GR.savestate()
|
||||||
|
gr_set_font(titlefont(sp), sp)
|
||||||
|
loc = sp[:titlelocation]
|
||||||
|
if loc == :left
|
||||||
|
xpos = viewport_plotarea[1]
|
||||||
|
halign = GR.TEXT_HALIGN_LEFT
|
||||||
|
elseif loc == :right
|
||||||
|
xpos = viewport_plotarea[2]
|
||||||
|
halign = GR.TEXT_HALIGN_RIGHT
|
||||||
|
else
|
||||||
|
xpos = gr_view_xcenter(viewport_plotarea)
|
||||||
|
halign = GR.TEXT_HALIGN_CENTER
|
||||||
|
end
|
||||||
|
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
|
||||||
|
gr_text(xpos, viewport_subplot[4], sp[:title])
|
||||||
|
GR.restorestate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
## Series
|
||||||
|
|
||||||
|
function gr_add_series(sp, series)
|
||||||
|
st = series[:seriestype]
|
||||||
|
|
||||||
|
# update the current stored gradient
|
||||||
|
gr_set_gradient(series)
|
||||||
|
|
||||||
|
GR.savestate()
|
||||||
|
|
||||||
|
x, y, z = series[:x], series[:y], series[:z]
|
||||||
|
xscale, yscale = sp[:xaxis][:scale], sp[:yaxis][:scale]
|
||||||
|
frng = series[:fillrange]
|
||||||
|
|
||||||
|
# recompute data
|
||||||
|
if typeof(z) <: Surface
|
||||||
|
z = transpose_z(series, z.surf, false)
|
||||||
|
elseif ispolar(sp)
|
||||||
|
rmin, rmax = axis_limits(sp, :y)
|
||||||
|
if frng !== nothing
|
||||||
|
_, frng = convert_to_polar(x, frng, (rmin, rmax))
|
||||||
|
end
|
||||||
|
x, y = convert_to_polar(x, y, (rmin, rmax))
|
||||||
|
end
|
||||||
|
|
||||||
|
clims = get_clims(sp, series)
|
||||||
|
|
||||||
|
# add custom frame shapes to markershape?
|
||||||
|
series_annotations_shapes!(series)
|
||||||
|
# -------------------------------------------------------
|
||||||
|
|
||||||
|
# draw the series
|
||||||
|
if st in (:path, :scatter, :straightline)
|
||||||
|
if st === :straightline
|
||||||
|
x, y = straightline_data(series)
|
||||||
|
end
|
||||||
|
gr_draw_segments(series, x, y, frng, clims)
|
||||||
|
if series[:markershape] !== :none
|
||||||
|
gr_draw_markers(series, x, y, clims)
|
||||||
|
end
|
||||||
|
elseif st === :shape
|
||||||
|
gr_draw_shapes(series, x, y, clims)
|
||||||
|
elseif st in (:path3d, :scatter3d)
|
||||||
|
gr_draw_segments_3d(series, x, y, z, clims)
|
||||||
|
if st === :scatter3d || series[:markershape] !== :none
|
||||||
|
# TODO: Do we need to transform to 2d coordinates here?
|
||||||
|
x2, y2 = RecipesPipeline.unzip(map(GR.wc3towc, x, y, z))
|
||||||
|
gr_draw_markers(series, x2, y2, clims)
|
||||||
|
end
|
||||||
|
elseif st === :contour
|
||||||
|
gr_draw_contour(series, x, y, z, clims)
|
||||||
|
elseif st in (:surface, :wireframe)
|
||||||
|
gr_draw_surface(series, x, y, z, clims)
|
||||||
|
elseif st === :volume
|
||||||
|
sp[:legend] = :none
|
||||||
|
GR.gr3.clear()
|
||||||
|
dmin, dmax = GR.gr3.volume(y.v, 0)
|
||||||
|
elseif st in (:heatmap, :image)
|
||||||
|
if !ispolar(series)
|
||||||
|
x, y = heatmap_edges(x, xscale, y, yscale, size(z))
|
||||||
|
end
|
||||||
|
if st === :heatmap
|
||||||
|
gr_draw_heatmap(series, x, y, z, clims)
|
||||||
|
else
|
||||||
|
gr_draw_image(series, x, y, z, clims)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# this is all we need to add the series_annotations text
|
||||||
|
anns = series[:series_annotations]
|
||||||
|
for (xi,yi,str,fnt) in EachAnn(anns, x, y)
|
||||||
|
gr_set_font(fnt, sp)
|
||||||
|
gr_text(GR.wctondc(xi, yi)..., str)
|
||||||
|
end
|
||||||
|
|
||||||
|
if sp[:legend] == :inline && should_add_to_legend(series)
|
||||||
|
gr_set_font(legendfont(sp), sp)
|
||||||
|
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
|
||||||
|
if sp[:yaxis][:mirror]
|
||||||
|
(_,i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x)
|
||||||
|
GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF)
|
||||||
|
offset = -0.01
|
||||||
|
else
|
||||||
|
(_,i) = sp[:xaxis][:flip] ? findmin(x) : findmax(x)
|
||||||
|
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
||||||
|
offset = 0.01
|
||||||
|
end
|
||||||
|
(x_l,y_l) = GR.wctondc(x[i],y[i])
|
||||||
|
gr_text(x_l+offset,y_l,series[:label])
|
||||||
|
end
|
||||||
|
GR.restorestate()
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_segments(series, x, y, fillrange, clims)
|
||||||
|
st = series[:seriestype]
|
||||||
|
if x !== nothing && length(x) > 1
|
||||||
|
segments = iter_segments(series, st)
|
||||||
|
# do area fill
|
||||||
|
if fillrange !== nothing
|
||||||
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
|
fr_from, fr_to = (is_2tuple(fillrange) ? fillrange : (y, fillrange))
|
||||||
|
for (i, rng) in enumerate(segments)
|
||||||
|
fc = get_fillcolor(series, clims, i)
|
||||||
|
gr_set_fillcolor(fc)
|
||||||
|
fx = _cycle(x, vcat(rng, reverse(rng)))
|
||||||
|
fy = vcat(_cycle(fr_from, rng), _cycle(fr_to, reverse(rng)))
|
||||||
|
gr_set_transparency(fc, get_fillalpha(series, i))
|
||||||
|
GR.fillarea(fx, fy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# draw the line(s)
|
||||||
|
if st in (:path, :straightline)
|
||||||
|
for (i, rng) in enumerate(segments)
|
||||||
|
lc = get_linecolor(series, clims, i)
|
||||||
|
gr_set_line(
|
||||||
|
get_linewidth(series, i), get_linestyle(series, i), lc, series
|
||||||
|
)
|
||||||
|
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
|
||||||
|
arrowstyle = isa(series[:arrow], Arrow) ? series[:arrow].style : :simple
|
||||||
|
gr_set_fillcolor(lc)
|
||||||
|
gr_set_transparency(lc, get_linealpha(series, i))
|
||||||
|
gr_polyline(x[rng], y[rng]; arrowside = arrowside, arrowstyle = arrowstyle)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_segments_3d(series, x, y, z, clims)
|
||||||
|
if series[:seriestype] === :path3d && length(x) > 1
|
||||||
|
lz = series[:line_z]
|
||||||
|
segments = iter_segments(series, :path3d)
|
||||||
|
for (i, rng) in enumerate(segments)
|
||||||
|
lc = get_linecolor(series, clims, i)
|
||||||
|
gr_set_line(
|
||||||
|
get_linewidth(series, i), get_linestyle(series, i), lc, series
|
||||||
|
)
|
||||||
|
gr_set_transparency(lc, get_linealpha(series, i))
|
||||||
|
GR.polyline3d(x[rng], y[rng], z[rng])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_markers(
|
||||||
|
series::Series,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
clims,
|
||||||
|
msize = series[:markersize],
|
||||||
|
strokewidth = series[:markerstrokewidth],
|
||||||
|
)
|
||||||
|
|
||||||
|
isempty(x) && return
|
||||||
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
|
|
||||||
|
shapes = series[:markershape]
|
||||||
|
if shapes != :none
|
||||||
|
for (i, rng) in enumerate(iter_segments(series, :scatter))
|
||||||
|
rng = intersect(eachindex(x), rng)
|
||||||
|
if !isempty(rng)
|
||||||
|
ms = get_thickness_scaling(series) * _cycle(msize, i)
|
||||||
|
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
|
||||||
|
shape = _cycle(shapes, i)
|
||||||
|
for j in rng
|
||||||
|
gr_draw_marker(series, _cycle(x, j), _cycle(y, j), clims, i, ms, msw, shape)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_shapes(series, x, y, clims)
|
||||||
|
x, y = shape_data(series)
|
||||||
|
for (i,rng) in enumerate(iter_segments(x, y))
|
||||||
|
if length(rng) > 1
|
||||||
|
# connect to the beginning
|
||||||
|
rng = vcat(rng, rng[1])
|
||||||
|
|
||||||
|
# get the segments
|
||||||
|
xseg, yseg = x[rng], y[rng]
|
||||||
|
|
||||||
|
# draw the interior
|
||||||
|
fc = get_fillcolor(series, clims, i)
|
||||||
|
gr_set_fill(fc)
|
||||||
|
gr_set_transparency(fc, get_fillalpha(series, i))
|
||||||
|
GR.fillarea(xseg, yseg)
|
||||||
|
|
||||||
|
# draw the shapes
|
||||||
|
lc = get_linecolor(series, clims, i)
|
||||||
|
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc, series)
|
||||||
|
gr_set_transparency(lc, get_linealpha(series, i))
|
||||||
|
GR.polyline(xseg, yseg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_contour(series, x, y, z, clims)
|
||||||
|
GR.setspace(clims[1], clims[2], 0, 90)
|
||||||
|
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series), series)
|
||||||
|
is_lc_black = let black=plot_color(:black)
|
||||||
|
plot_color(series[:linecolor]) in (black,[black])
|
||||||
|
end
|
||||||
|
h = gr_contour_levels(series, clims)
|
||||||
|
if series[:fillrange] !== nothing
|
||||||
|
if series[:fillcolor] != series[:linecolor] && !is_lc_black
|
||||||
|
@warn("GR: filled contour only supported with black contour lines")
|
||||||
|
end
|
||||||
|
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
|
||||||
|
else
|
||||||
|
coff = is_lc_black ? 0 : 1000
|
||||||
|
GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_surface(series, x, y, z, clims)
|
||||||
|
if series[:seriestype] === :surface
|
||||||
|
if length(x) == length(y) == length(z)
|
||||||
|
GR.trisurface(x, y, z)
|
||||||
|
else
|
||||||
|
try
|
||||||
|
GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
||||||
|
catch
|
||||||
|
GR.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else # wireframe
|
||||||
|
GR.setfillcolorind(0)
|
||||||
|
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_heatmap(series, x, y, z, clims)
|
||||||
|
fillgrad = _as_gradient(series[:fillcolor])
|
||||||
|
if !ispolar(series)
|
||||||
|
GR.setspace(clims..., 0, 90)
|
||||||
|
w, h = length(x) - 1, length(y) - 1
|
||||||
|
if is_uniformly_spaced(x) && is_uniformly_spaced(y)
|
||||||
|
# For uniformly spaced data use GR.drawimage, which can be
|
||||||
|
# much faster than GR.nonuniformcellarray, especially for
|
||||||
|
# pdf output, and also supports alpha values.
|
||||||
|
# Note that drawimage draws uniformly spaced data correctly
|
||||||
|
# even on log scales, where it is visually non-uniform.
|
||||||
|
colors = plot_color.(get(fillgrad, z, clims), series[:fillalpha])
|
||||||
|
rgba = gr_color.(colors)
|
||||||
|
GR.drawimage(first(x), last(x), last(y), first(y), w, h, rgba)
|
||||||
|
else
|
||||||
|
if something(series[:fillalpha], 1) < 1
|
||||||
|
@warn "GR: transparency not supported in non-uniform heatmaps. Alpha values ignored."
|
||||||
|
end
|
||||||
|
z_normalized = get_z_normalized.(z, clims...)
|
||||||
|
rgba = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
|
||||||
|
GR.nonuniformcellarray(x, y, w, h, rgba)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
phimin, phimax = 0.0, 360.0 # nonuniform polar array is not yet supported in GR.jl
|
||||||
|
nx, ny = length(series[:x]), length(series[:y])
|
||||||
|
xmin, xmax, ymin, ymax = gr_xy_axislims(sp)
|
||||||
|
GR.setwindow(-ymax, ymax, -ymax, ymax)
|
||||||
|
if ymin > 0
|
||||||
|
@warn "'ymin[1] > 0' (rmin) is not yet supported."
|
||||||
|
end
|
||||||
|
if series[:y][end] != ny
|
||||||
|
@warn "Right now only the maximum value of y (r) is taken into account."
|
||||||
|
end
|
||||||
|
z_normalized = get_z_normalized.(z, clims...)
|
||||||
|
rgba = Int32[round(Int32, 1000 + _i * 255) for _i in z_normalized]
|
||||||
|
GR.polarcellarray(0, 0, phimin, phimax, 0, ymax, nx, ny, rgba)
|
||||||
|
# Right now only the maximum value of y (r) is taken into account.
|
||||||
|
# This is certainly not perfect but nonuniform polar array is not yet supported in GR.jl
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function gr_draw_image(series, x, y, z, clims)
|
||||||
|
z = transpose_z(series, series[:z].surf, true)'
|
||||||
|
w, h = size(z)
|
||||||
|
xmin, xmax = ignorenan_extrema(x)
|
||||||
|
ymin, ymax = ignorenan_extrema(y)
|
||||||
|
rgba = gr_color.(z)
|
||||||
|
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
for (mime, fmt) in (
|
for (mime, fmt) in (
|
||||||
|
|||||||
@ -659,6 +659,7 @@ function locate_annotation(sp::Subplot, pos::Symbol, lab::PlotText)
|
|||||||
(x, y, lab)
|
(x, y, lab)
|
||||||
end
|
end
|
||||||
locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label)
|
locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label)
|
||||||
|
locate_annotation(sp::Subplot, x, y, z, label::PlotText) = (x, y, z, label)
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
"type which represents z-values for colors and sizes (and anything else that might come up)"
|
"type which represents z-values for colors and sizes (and anything else that might come up)"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user