Compare commits

...

41 Commits

Author SHA1 Message Date
Simon Christ 2022aebb07 Update Project.toml 2019-12-17 15:24:20 +01:00
Simon Christ b73c38fe69 Merge pull request #2310 from BeastyBlacksmith/pgfplotsx
fix ribbons and interaction between background and fill between
2019-12-17 15:23:26 +01:00
Daniel Schwabeneder 82479d48b9 Merge pull request #2325 from daschw/axes-3d
Improve GR 3D axes
2019-12-13 23:48:25 +01:00
Daniel Schwabeneder a07fd5d3db Merge pull request #2328 from daschw/showtheme
update showtheme
2019-12-13 23:37:15 +01:00
daschw 10ab3ae974 update showtheme 2019-12-13 23:35:05 +01:00
Daniel Schwabeneder b908202c47 Merge pull request #2327 from daschw/theme
copy theme defaults
2019-12-13 21:14:45 +01:00
daschw 61d4c84ef4 copy theme defaults 2019-12-13 19:44:37 +01:00
Daniel Schwabeneder 68a0baf299 update and reactivate precompile 2019-12-13 14:55:16 +01:00
Daniel Schwabeneder aef75cb073 add guides and fix 3d bg_inside 2019-12-13 14:16:05 +01:00
Daniel Schwabeneder c5fe90d135 move zaxis to the left 2019-12-13 14:16:05 +01:00
Daniel Schwabeneder 85e5f2e971 increase right margin for outer legend 2019-12-13 14:16:05 +01:00
Daniel Schwabeneder 58bf14fc85 minor preparations for guides 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder 0d09975fba avoid precompilation temporarily 2019-12-13 14:16:04 +01:00
daschw 06afcedf56 implement 3d tick labels 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder c7cc76b2b6 increase plotarea for 3d plots in gr 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder 84b108f6d0 3d axes grid and ticks in gr 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder cb6f0772b7 avoid multiple calls to axis_drawing_info 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder 4263ced69b implement axes_drawing_info_3d 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder f5c6b06eb6 fix 3d Segments constructor 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder 05ef841d63 simplify axes_drawing_info 2019-12-13 14:16:04 +01:00
Daniel Schwabeneder 140afeb53d Merge pull request #2320 from korsbo/layout_colon
Support colons in layout keyword argument.
2019-12-12 09:35:56 +01:00
Daniel Schwabeneder 639a09bccb Merge pull request #2322 from JuliaPlots/compathelper/new_version/2019-12-12-03-02-29-808-2906006334
CompatHelper: bump compat for "Requires" to "1.0"
2019-12-12 09:32:10 +01:00
github-actions[bot] f105d41e54 CompatHelper: bump compat for "Requires" to "1.0" 2019-12-12 03:02:30 +00:00
Niklas Korsbo 140a429e09 Fix regression of layout_args. 2019-12-11 12:27:44 +00:00
Simon Christ 28d5e0bb7d commented too much 2019-12-11 13:23:50 +01:00
Simon Christ 3dec7fe394 comment save tests 2019-12-11 13:09:48 +01:00
Niklas Korsbo e54eb53665 Fix layout specification bug. 2019-12-11 11:11:14 +00:00
Niklas Korsbo 9b3cf3a818 Support colons in layout kwarg. 2019-12-11 10:58:39 +00:00
Daniel Schwabeneder 3d306578f1 Merge pull request #2317 from daschw/gr-logticks
fix extra blank space in GR with log axis and engineering notation
2019-12-11 09:28:21 +01:00
Daniel Schwabeneder fbbbd40353 fix extra blank space in GR with log axis and engineering notation 2019-12-10 13:12:35 +01:00
Simon Christ 0e694a9767 forget extra ribbon plot legend entries 2019-12-09 11:21:33 +01:00
Simon Christ 203e351cef fix scalar ribbon 2019-12-09 11:17:37 +01:00
Simon Christ 74ec895aca fix unintended filling of simple lines 2019-12-07 15:18:47 +01:00
Simon Christ d2c0840c43 fix dimensions 2019-12-06 19:37:35 +01:00
Simon Christ 9534bae4ef support asymmetric ribbons 2019-12-06 18:22:02 +01:00
Simon Christ 2a720a7491 better ribbon tests 2019-12-06 16:04:10 +01:00
Simon Christ 7b31e5f9b8 fix ribbon legend 2019-12-06 15:04:22 +01:00
Simon Christ d0be1e7d1d use UUIDs 2019-12-06 14:45:56 +01:00
Simon Christ 8434741599 add test 2019-12-06 14:42:35 +01:00
Simon Christ cfe1ede25a fix ribbon 2019-12-06 14:40:34 +01:00
Simon Christ ecc891279e fix background + fill between 2019-12-06 14:36:24 +01:00
9 changed files with 1756 additions and 1097 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.28.3"
version = "0.28.4"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@@ -43,7 +43,7 @@ PlotThemes = "1"
PlotUtils = "0.6.1"
RecipesBase = "0.6, 0.7"
Reexport = "0.2"
Requires = "0.5"
Requires = "0.5, 1.0"
Showoff = "0.3.1"
StatsBase = "0.32"
julia = "1"
+310 -66
View File
@@ -637,13 +637,13 @@ function axis_drawing_info(sp::Subplot)
if sp[:framestyle] != :none
# xaxis
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
push!(xaxis_segs, (xmin, y1), (xmax, y1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
@@ -656,55 +656,48 @@ function axis_drawing_info(sp::Subplot)
if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(ymin) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t2 = invf(f(ymax) - 0.015 * (f(ymax) - f(ymin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
(-t, t)
else
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xticks[1]
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
end
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
end
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(ymin) + 0.01 * (f(ymax) - f(ymin)) * ticks_in)
t2 = invf(f(ymax) - 0.01 * (f(ymax) - f(ymin)) * ticks_in)
t3 = invf(f(0) + 0.01 * (f(ymax) - f(ymin)) * ticks_in)
for xminortick in xminorticks
if xaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
end
push!(xtick_segs, (xminortick, tick_start), (xminortick, tick_stop)) # bottom tick
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xminorticks
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
end
xaxis[:minorgrid] && push!(xminorgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
end
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top tick
xaxis[:minorgrid] && push!(xminorgrid_segs, (xminortick, ymin), (xminortick, ymax)) # vertical grid
end
end
# yaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
push!(yaxis_segs, (x1, ymin), (x1, ymax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
@@ -717,46 +710,297 @@ function axis_drawing_info(sp::Subplot)
if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(xmin) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t2 = invf(f(xmax) - 0.015 * (f(xmax) - f(xmin)) * ticks_in)
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(xmax) - f(xmin)))
(-t, t)
else
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yticks[1]
if yaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
end
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t1 = invf(f(xmin) + 0.01 * (f(xmax) - f(xmin)) * ticks_in)
t2 = invf(f(xmax) - 0.01 * (f(xmax) - f(xmin)) * ticks_in)
t3 = invf(f(0) + 0.01 * (f(xmax) - f(xmin)) * ticks_in)
for ytick in yminorticks
if yaxis[:showaxis]
tick_start, tick_stop = if sp[:framestyle] == :origin
(0, t3)
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
end
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(xmax) - f(xmin)))
(-t, t)
else
t = invf(f(x1) + 0.006 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yminorticks
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
end
yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right tick
yaxis[:minorgrid] && push!(yminorgrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
end
end
end
xticks, yticks, xaxis_segs, yaxis_segs, xtick_segs, ytick_segs, xgrid_segs, ygrid_segs, xminorgrid_segs, yminorgrid_segs, xborder_segs, yborder_segs
end
function axis_drawing_info_3d(sp::Subplot)
xaxis, yaxis, zaxis = sp[:xaxis], sp[:yaxis], sp[:zaxis]
xmin, xmax = axis_limits(sp, :x)
ymin, ymax = axis_limits(sp, :y)
zmin, zmax = axis_limits(sp, :z)
xticks = get_ticks(sp, xaxis)
yticks = get_ticks(sp, yaxis)
zticks = get_ticks(sp, zaxis)
xminorticks = get_minor_ticks(sp, xaxis, xticks)
yminorticks = get_minor_ticks(sp, yaxis, yticks)
zminorticks = get_minor_ticks(sp, zaxis, zticks)
xaxis_segs = Segments(3)
yaxis_segs = Segments(3)
zaxis_segs = Segments(3)
xtick_segs = Segments(3)
ytick_segs = Segments(3)
ztick_segs = Segments(3)
xgrid_segs = Segments(3)
ygrid_segs = Segments(3)
zgrid_segs = Segments(3)
xminorgrid_segs = Segments(3)
yminorgrid_segs = Segments(3)
zminorgrid_segs = Segments(3)
xborder_segs = Segments(3)
yborder_segs = Segments(3)
zborder_segs = Segments(3)
if sp[:framestyle] != :none
# xaxis
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(xaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
end
if xaxis[:showaxis]
if sp[:framestyle] != :grid
push!(xaxis_segs, (xmin, y1, z1), (xmax, y1, z1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
showticks = xticks[1] .!= 0
xticks = (xticks[1][showticks], xticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2, z2), (xmax, y2, z2)) # top spine
end
if !(xaxis[:ticks] in (:none, nothing, false))
f = scalefunc(yaxis[:scale])
invf = invscalefunc(yaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
(-t, t)
else
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xticks[1]
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
end
if xaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(xgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
push!(xgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
else
push!(xgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
push!(xgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
end
end
end
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for xtick in xminorticks
if xaxis[:showaxis]
push!(xtick_segs, (xtick, tick_start, z1), (xtick, tick_stop, z1)) # bottom tick
end
if xaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(xminorgrid_segs, (xtick, ymin, 0.0), (xtick, ymax, 0.0))
push!(xminorgrid_segs, (xtick, 0.0, zmin), (xtick, 0.0, zmax))
else
push!(xminorgrid_segs, (xtick, y1, z1), (xtick, y2, z1))
push!(xminorgrid_segs, (xtick, y2, z1), (xtick, y2, z2))
end
end
end
end
end
# yaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], xaxis[:flip]) ? (xmin, xmax) : (xmax, xmin)
end
z1, z2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(yaxis[:mirror], zaxis[:flip]) ? (zmax, zmin) : (zmin, zmax)
end
if yaxis[:showaxis]
if sp[:framestyle] != :grid
push!(yaxis_segs, (x1, ymin, z1), (x1, ymax, z1))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
showticks = yticks[1] .!= 0
yticks = (yticks[1][showticks], yticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin, z2), (x2, ymax, z2)) # right spine
end
if !(yaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(xmax) - f(xmin)))
(-t, t)
else
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(x1) + 0.012 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yticks[1]
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
end
if yaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(ygrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
push!(ygrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
else
push!(ygrid_segs, (x1, ytick, z1), (x2, ytick, z1))
push!(ygrid_segs, (x2, ytick, z1), (x2, ytick, z2))
end
end
end
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(xmax) - f(xmin)))
(-t, t)
else
t = invf(f(x1) + 0.006 * (f(x2) - f(x1)) * ticks_in)
(x1, t)
end
for ytick in yminorticks
if yaxis[:showaxis]
push!(ytick_segs, (tick_start, ytick, z1), (tick_stop, ytick, z1)) # left tick
end
if yaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(yminorgrid_segs, (xmin, ytick, 0.0), (xmax, ytick, 0.0))
push!(yminorgrid_segs, (0.0, ytick, zmin), (0.0, ytick, zmax))
else
push!(yminorgrid_segs, (x1, ytick, z1), (x2, ytick, z1))
push!(yminorgrid_segs, (x2, ytick, z1), (x2, ytick, z2))
end
end
end
end
end
# zaxis
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(zaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
end
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
0.0, 0.0
else
xor(zaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
end
if zaxis[:showaxis]
if sp[:framestyle] != :grid
push!(zaxis_segs, (x1, y1, zmin), (x1, y1, zmax))
# don't show the 0 tick label for the origin framestyle
if sp[:framestyle] == :origin && !(zticks in (:none, nothing,false)) && length(zticks) > 1
showticks = zticks[1] .!= 0
zticks = (zticks[1][showticks], zticks[2][showticks])
end
end
sp[:framestyle] in (:semi, :box) && push!(zborder_segs, (x2, y2, zmin), (x2, y2, zmax))
end
if !(zaxis[:ticks] in (:none, nothing, false))
f = scalefunc(xaxis[:scale])
invf = invscalefunc(xaxis[:scale])
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.012 * (f(ymax) - f(ymin)))
(-t, t)
else
ticks_in = zaxis[:tick_direction] == :out ? -1 : 1
t = invf(f(y1) + 0.012 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for ztick in zticks[1]
if zaxis[:showaxis]
push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
end
if zaxis[:grid]
if sp[:framestyle] in (:origin, :zerolines)
push!(zgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
push!(ygrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
else
push!(ygrid_segs, (x1, y1, ztick), (x1, y2, ztick))
push!(ygrid_segs, (x1, y2, ztick), (x2, y2, ztick))
end
end
end
if !(zaxis[:minorticks] in (:none, nothing, false)) || zaxis[:minorgrid]
tick_start, tick_stop = if sp[:framestyle] == :origin
t = invf(f(0) + 0.006 * (f(ymax) - f(ymin)))
(-t, t)
else
t = invf(f(y1) + 0.006 * (f(y2) - f(y1)) * ticks_in)
(y1, t)
end
for ztick in zminorticks
if zaxis[:showaxis]
push!(ztick_segs, (x1, tick_start, ztick), (x1, tick_stop, ztick)) # left tick
end
if zaxis[:minorgrid]
if sp[:framestyle] in (:origin, :zerolines)
push!(zminorgrid_segs, (xmin, 0.0, ztick), (xmax, 0.0, ztick))
push!(zminorgrid_segs, (0.0, ymin, ztick), (0.0, ymax, ztick))
else
push!(zminorgrid_segs, (x1, y1, ztick), (x1, y2, ztick))
push!(zminorgrid_segs, (x1, y2, ztick), (x2, y2, ztick))
end
end
end
end
end
end
xticks, yticks, zticks, xaxis_segs, yaxis_segs, zaxis_segs, xtick_segs, ytick_segs, ztick_segs, xgrid_segs, ygrid_segs, zgrid_segs, xminorgrid_segs, yminorgrid_segs, zminorgrid_segs, xborder_segs, yborder_segs, zborder_segs
end
+457 -114
View File
@@ -155,6 +155,48 @@ function gr_polyline(x, y, func = GR.polyline; arrowside = :none, arrowstyle = :
end
end
function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowstyle = :simple)
iend = 0
n = length(x)
while iend < n-1
# set istart to the first index that is finite
istart = -1
for j = iend+1:n
if isfinite(x[j]) && isfinite(y[j]) && isfinite(z[j])
istart = j
break
end
end
if istart > 0
# iend is the last finite index
iend = -1
for j = istart+1:n
if isfinite(x[j]) && isfinite(y[j]) && isfinite(z[j])
iend = j
else
break
end
end
end
# if we found a start and end, draw the line segment, otherwise we're done
if istart > 0 && iend > 0
func(x[istart:iend], y[istart:iend], z[istart:iend])
if arrowside in (:head,:both)
gr_set_arrowstyle(arrowstyle)
GR.drawarrow(x[iend-1], y[iend-1], z[iend-1], x[iend], y[iend], z[iend])
end
if arrowside in (:tail,:both)
gr_set_arrowstyle(arrowstyle)
GR.drawarrow(x[istart+1], y[istart+1], z[istart+1], x[istart], y[istart], z[istart])
end
else
break
end
end
end
gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
function gr_inqtext(x, y, s)
@@ -249,18 +291,6 @@ gr_y_axislims(sp::Subplot) = axis_limits(sp, :y)
gr_z_axislims(sp::Subplot) = axis_limits(sp, :z)
gr_xy_axislims(sp::Subplot) = gr_x_axislims(sp)..., gr_y_axislims(sp)...
function gr_lims(sp::Subplot, axis::Axis, adjust::Bool, expand = nothing)
if expand !== nothing
expand_extrema!(axis, expand)
end
lims = axis_limits(sp, axis[:letter])
if adjust
GR.adjustrange(lims...)
else
lims
end
end
function gr_fill_viewport(vp::AVec{Float64}, c)
GR.savestate()
@@ -370,6 +400,12 @@ function gr_nans_to_infs!(z)
end
end
function gr_w3tondc(x, y, z)
xw, yw, zw = GR.wc3towc(x, y, z)
x, y = GR.wctondc(xw, yw)
return x, y
end
# --------------------------------------------------------------------------------------
# viewport plot area
@@ -388,16 +424,8 @@ function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, vi
viewport[2] = viewport_canvas[2] * (right(bb) / w)
viewport[3] = viewport_canvas[4] * (1.0 - bottom(bb) / h)
viewport[4] = viewport_canvas[4] * (1.0 - top(bb) / h)
if is3d(sp)
vp = viewport[:]
extent = min(vp[2] - vp[1], vp[4] - vp[3])
viewport[1] = 0.5 * (vp[1] + vp[2] - extent)
viewport[2] = 0.5 * (vp[1] + vp[2] + extent)
viewport[3] = 0.5 * (vp[3] + vp[4] - extent)
viewport[4] = 0.5 * (vp[3] + vp[4] + extent)
end
if hascolorbar(sp)
viewport[2] -= gr_colorbar_ratio
viewport[2] -= gr_colorbar_ratio * (1 + is3d(sp) / 2)
end
viewport
end
@@ -567,13 +595,13 @@ function gr_legend_pos(sp::Subplot, w, h)
if occursin("right", str)
if occursin("outer", str)
# As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525
xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_yaxis_width(sp)
xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_axis_width(sp, sp[:yaxis])
else
xpos = viewport_plotarea[2] - 0.05 - w
end
elseif occursin("left", str)
if occursin("outer", str)
xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_yaxis_width(sp)
xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_axis_width(sp, sp[:yaxis])
else
xpos = viewport_plotarea[1] + 0.11
end
@@ -582,13 +610,13 @@ function gr_legend_pos(sp::Subplot, w, h)
end
if occursin("top", str)
if s == :outertop
ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_xaxis_height(sp)
ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_axis_height(sp, sp[:xaxis])
else
ypos = viewport_plotarea[4] - 0.06
end
elseif occursin("bottom", str)
if s == :outerbottom
ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_xaxis_height(sp)
ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_axis_height(sp, sp[:xaxis])
else
ypos = viewport_plotarea[3] + h + 0.06
end
@@ -747,26 +775,24 @@ function gr_get_ticks_size(ticks, rot)
return w, h
end
function gr_xaxis_height(sp)
xaxis = sp[:xaxis]
xticks, yticks = axis_drawing_info(sp)[1:2]
gr_set_font(tickfont(xaxis))
h = (xticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(xticks, xaxis[:rotation])))
if xaxis[:guide] != ""
gr_set_font(guidefont(xaxis))
h += last(gr_text_size(xaxis[:guide]))
function gr_axis_height(sp, axis)
ticks = get_ticks(sp, axis)
gr_set_font(tickfont(axis))
h = (ticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(ticks, axis[:rotation])))
if axis[:guide] != ""
gr_set_font(guidefont(axis))
h += last(gr_text_size(axis[:guide]))
end
return h
end
function gr_yaxis_width(sp)
yaxis = sp[:yaxis]
xticks, yticks = axis_drawing_info(sp)[1:2]
gr_set_font(tickfont(yaxis))
w = (xticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(yticks, yaxis[:rotation])))
if yaxis[:guide] != ""
gr_set_font(guidefont(yaxis))
w += last(gr_text_size(yaxis[:guide]))
function gr_axis_width(sp, axis)
ticks = get_ticks(sp, axis)
gr_set_font(tickfont(axis))
w = (ticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(ticks, axis[:rotation])))
if axis[:guide] != ""
gr_set_font(guidefont(axis))
w += last(gr_text_size(axis[:guide]))
end
return w
end
@@ -790,48 +816,132 @@ function _update_min_padding!(sp::Subplot{GRBackend})
h = 1mm + gr_plot_size[2] * l * px
toppad += h
end
# Add margin for x and y ticks
xticks, yticks = axis_drawing_info(sp)[1:2]
if !(xticks in (nothing, false, :none))
flip, mirror = gr_set_xticks_font(sp)
l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
h = 1mm + gr_plot_size[2] * l * px
if mirror
toppad += h
else
bottompad += h
if is3d(sp)
xaxis, yaxis, zaxis = sp[:xaxis], sp[:yaxis], sp[:zaxis]
xticks, yticks, zticks = get_ticks(sp, xaxis), get_ticks(sp, yaxis), get_ticks(sp, zaxis)
# Add margin for x and y ticks
h = 0mm
if !(xticks in (nothing, false, :none))
gr_set_font(
tickfont(xaxis),
halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
valign = (xaxis[:mirror] ? :bottom : :top),
rotation = xaxis[:rotation]
)
l = 0.01 + last(gr_get_ticks_size(xticks, xaxis[:rotation]))
h = max(h, 1mm + gr_plot_size[2] * l * px)
end
end
if !(yticks in (nothing, false, :none))
flip, mirror = gr_set_yticks_font(sp)
l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
w = 1mm + gr_plot_size[1] * l * px
if mirror
rightpad += w
else
leftpad += w
if !(yticks in (nothing, false, :none))
gr_set_font(
tickfont(yaxis),
halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
valign = (yaxis[:mirror] ? :bottom : :top),
rotation = yaxis[:rotation]
)
l = 0.01 + last(gr_get_ticks_size(yticks, yaxis[:rotation]))
h = max(h, 1mm + gr_plot_size[2] * l * px)
end
end
# Add margin for x label
if sp[:xaxis][:guide] != ""
gr_set_font(guidefont(sp[:xaxis]))
l = last(gr_text_size(sp[:xaxis][:guide]))
h = 1mm + gr_plot_size[2] * l * px
if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true)
toppad += h
else
bottompad += h
if h > 0mm
if xaxis[:mirror] || yaxis[:mirror]
toppad += h
end
if !xaxis[:mirror] || !yaxis[:mirror]
bottompad += h
end
end
end
# Add margin for y label
if sp[:yaxis][:guide] != ""
gr_set_font(guidefont(sp[:yaxis]))
l = last(gr_text_size(sp[:yaxis][:guide]))
w = 1mm + gr_plot_size[2] * l * px
if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true)
rightpad += w
else
leftpad += w
if !(zticks in (nothing, false, :none))
gr_set_font(
tickfont(zaxis),
halign = (zaxis[:mirror] ? :left : :right),
valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
rotation = zaxis[:rotation]
)
l = 0.01 + first(gr_get_ticks_size(zticks, zaxis[:rotation]))
w = 1mm + gr_plot_size[1] * l * px
if zaxis[:mirror]
rightpad += w
else
leftpad += w
end
end
# Add margin for x or y label
h = 0mm
if xaxis[:guide] != ""
gr_set_font(guidefont(sp[:xaxis]))
l = last(gr_text_size(sp[:xaxis][:guide]))
h = max(h, 1mm + gr_plot_size[2] * l * px)
end
if yaxis[:guide] != ""
gr_set_font(guidefont(sp[:yaxis]))
l = last(gr_text_size(sp[:yaxis][:guide]))
h = max(h, 1mm + gr_plot_size[2] * l * px)
end
if h > 0mm
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
toppad += h
else
bottompad += h
end
end
# Add margin for z label
if zaxis[:guide] != ""
gr_set_font(guidefont(sp[:zaxis]))
l = last(gr_text_size(sp[:zaxis][:guide]))
w = 1mm + gr_plot_size[2] * l * px
if zaxis[:guide_position] == :right || (zaxis[:guide_position] == :auto && zaxis[:mirror] == true)
rightpad += w
else
leftpad += w
end
end
else
# Add margin for x and y ticks
xticks, yticks = get_ticks(sp, sp[:xaxis]), get_ticks(sp, sp[:yaxis])
if !(xticks in (nothing, false, :none))
flip, mirror = gr_set_xticks_font(sp)
l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
h = 1mm + gr_plot_size[2] * l * px
if mirror
toppad += h
else
bottompad += h
end
end
if !(yticks in (nothing, false, :none))
flip, mirror = gr_set_yticks_font(sp)
l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
w = 1mm + gr_plot_size[1] * l * px
if mirror
rightpad += w
else
leftpad += w
end
end
# Add margin for x label
if sp[:xaxis][:guide] != ""
gr_set_font(guidefont(sp[:xaxis]))
l = last(gr_text_size(sp[:xaxis][:guide]))
h = 1mm + gr_plot_size[2] * l * px
if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true)
toppad += h
else
bottompad += h
end
end
# Add margin for y label
if sp[:yaxis][:guide] != ""
gr_set_font(guidefont(sp[:yaxis]))
l = last(gr_text_size(sp[:yaxis][:guide]))
w = 1mm + gr_plot_size[2] * l * px
if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true)
rightpad += w
else
leftpad += w
end
end
end
if sp[:colorbar_title] != ""
@@ -908,7 +1018,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
leg_str = string(sp[:legend])
if occursin("outer", leg_str)
if occursin("right", leg_str)
viewport_plotarea[2] -= legendw + 0.11
viewport_plotarea[2] -= legendw + 0.12
elseif occursin("left", leg_str)
viewport_plotarea[1] += legendw + 0.11
elseif occursin("top", leg_str)
@@ -920,7 +1030,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# fill in the plot area background
bg = plot_color(sp[:background_color_inside])
gr_fill_viewport(viewport_plotarea, bg)
is3d(sp) || gr_fill_viewport(viewport_plotarea, bg)
# reduced from before... set some flags based on the series in this subplot
# TODO: can these be generic flags?
@@ -995,39 +1105,228 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
GR.setlinewidth(sp.plt[:thickness_scaling])
if is3d(sp)
# TODO do we really need a different clims computation here from the one
# computed above using get_clims(sp)?
zmin, zmax = gr_lims(sp, zaxis, true)
clims3d = sp[:clims]
if is_2tuple(clims3d)
isfinite(clims3d[1]) && (zmin = clims3d[1])
isfinite(clims3d[2]) && (zmax = clims3d[2])
end
zmin, zmax = axis_limits(sp, :z)
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...)
xtick = GR.tick(xmin, xmax) / 2
ytick = GR.tick(ymin, ymax) / 2
ztick = GR.tick(zmin, zmax) / 2
ticksize = 0.01 * (viewport_plotarea[2] - viewport_plotarea[1])
xticks, yticks, zticks, xaxis_segs, yaxis_segs, zaxis_segs, xtick_segs, ytick_segs, ztick_segs, xgrid_segs, ygrid_segs, zgrid_segs, xminorgrid_segs, yminorgrid_segs, zminorgrid_segs, xborder_segs, yborder_segs, zborder_segs = axis_drawing_info_3d(sp)
# fill the plot area
gr_set_fill(sp[:background_color_inside])
plot_area_x = [xmin, xmin, xmin, xmax, xmax, xmax, xmin]
plot_area_y = [ymin, ymin, ymax, ymax, ymax, ymin, ymin]
plot_area_z = [zmin, zmax, zmax, zmax, zmin, zmin, zmin]
x_bg, y_bg = unzip(GR.wc3towc.(plot_area_x, plot_area_y, plot_area_z))
GR.fillarea(x_bg, y_bg)
# draw the grid lines
if xaxis[:grid]
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
GR.grid3d(xtick, 0, 0, xmin, ymax, zmin, 2, 0, 0)
gr_polyline3d(coords(xgrid_segs)...)
end
if yaxis[:grid]
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
GR.grid3d(0, ytick, 0, xmin, ymax, zmin, 0, 2, 0)
gr_polyline3d(coords(ygrid_segs)...)
end
if zaxis[:grid]
gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid])
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha])
GR.grid3d(0, 0, ztick, xmin, ymax, zmin, 0, 0, 2)
gr_polyline3d(coords(zgrid_segs)...)
end
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
gr_set_transparency(xaxis[:foreground_color_axis])
GR.axes3d(xtick, 0, ztick, xmin, ymin, zmin, 2, 0, 2, -ticksize)
GR.axes3d(0, ytick, 0, xmax, ymin, zmin, 0, 2, 0, ticksize)
if xaxis[:minorgrid]
gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid])
gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha])
gr_polyline3d(coords(xminorgrid_segs)...)
end
if yaxis[:minorgrid]
gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid])
gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha])
gr_polyline3d(coords(yminorgrid_segs)...)
end
if zaxis[:minorgrid]
gr_set_line(zaxis[:minorgridlinewidth], zaxis[:minorgridstyle], zaxis[:foreground_color_minor_grid])
gr_set_transparency(zaxis[:foreground_color_minor_grid], zaxis[:minorgridalpha])
gr_polyline3d(coords(zminorgrid_segs)...)
end
gr_set_transparency(1.0)
# axis lines
if xaxis[:showaxis]
gr_set_line(1, :solid, xaxis[:foreground_color_border])
GR.setclip(0)
gr_polyline3d(coords(xaxis_segs)...)
end
if yaxis[:showaxis]
gr_set_line(1, :solid, yaxis[:foreground_color_border])
GR.setclip(0)
gr_polyline3d(coords(yaxis_segs)...)
end
if zaxis[:showaxis]
gr_set_line(1, :solid, zaxis[:foreground_color_border])
GR.setclip(0)
gr_polyline3d(coords(zaxis_segs)...)
end
GR.setclip(1)
# axis ticks
if xaxis[:showaxis]
if sp[:framestyle] in (:zerolines, :grid)
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0)
else
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
end
GR.setclip(0)
gr_polyline3d(coords(xtick_segs)...)
end
if yaxis[:showaxis]
if sp[:framestyle] in (:zerolines, :grid)
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0)
else
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
end
GR.setclip(0)
gr_polyline3d(coords(ytick_segs)...)
end
if zaxis[:showaxis]
if sp[:framestyle] in (:zerolines, :grid)
gr_set_line(1, :solid, zaxis[:foreground_color_grid])
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:tick_direction] == :out ? zaxis[:gridalpha] : 0)
else
gr_set_line(1, :solid, zaxis[:foreground_color_axis])
end
GR.setclip(0)
gr_polyline3d(coords(ztick_segs)...)
end
GR.setclip(1)
# tick marks
if !(xticks in (:none, nothing, false)) && xaxis[:showaxis]
# x labels
gr_set_font(
tickfont(xaxis),
halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
valign = (xaxis[:mirror] ? :bottom : :top),
rotation = xaxis[:rotation]
)
yt = if sp[:framestyle] == :origin
0
elseif xor(xaxis[:mirror], yaxis[:flip])
ymax
else
ymin
end
zt = if sp[:framestyle] == :origin
0
elseif xor(xaxis[:mirror], zaxis[:flip])
zmax
else
zmin
end
for (cv, dv) in zip(xticks...)
xi, yi = gr_w3tondc(cv, yt, zt)
if xaxis[:ticks] in (:auto, :native)
if xaxis[:formatter] in (:scientific, :auto)
# ensure correct dispatch in gr_text for automatic log ticks
if xaxis[:scale] in _logScales
dv = string(dv, "\\ ")
end
dv = convert_sci_unicode(dv)
end
end
xi += (yaxis[:mirror] ? 1 : -1) * 1e-2 * (xaxis[:tick_direction] == :out ? 1.5 : 1.0)
yi += (xaxis[:mirror] ? 1 : -1) * 5e-3 * (xaxis[:tick_direction] == :out ? 1.5 : 1.0)
gr_text(xi, yi, string(dv))
end
end
if !(yticks in (:none, nothing, false)) && yaxis[:showaxis]
# y labels
gr_set_font(
tickfont(yaxis),
halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
valign = (yaxis[:mirror] ? :bottom : :top),
rotation = yaxis[:rotation]
)
xt = if sp[:framestyle] == :origin
0
elseif xor(yaxis[:mirror], xaxis[:flip])
xmin
else
xmax
end
zt = if sp[:framestyle] == :origin
0
elseif xor(yaxis[:mirror], zaxis[:flip])
zmax
else
zmin
end
for (cv, dv) in zip(yticks...)
xi, yi = gr_w3tondc(xt, cv, zt)
if yaxis[:ticks] in (:auto, :native)
if xaxis[:formatter] in (:scientific, :auto)
# ensure correct dispatch in gr_text for automatic log ticks
if yaxis[:scale] in _logScales
dv = string(dv, "\\ ")
end
dv = convert_sci_unicode(dv)
end
end
gr_text(xi + (yaxis[:mirror] ? -1 : 1) * 1e-2 * (yaxis[:tick_direction] == :out ? 1.5 : 1.0), yi + (yaxis[:mirror] ? 1 : -1) * 5e-3 * (yaxis[:tick_direction] == :out ? 1.5 : 1.0), string(dv))
end
end
if !(zticks in (:none, nothing, false)) && zaxis[:showaxis]
# z labels
gr_set_font(
tickfont(zaxis),
halign = (zaxis[:mirror] ? :left : :right),
valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
rotation = zaxis[:rotation]
)
xt = if sp[:framestyle] == :origin
0
elseif xor(zaxis[:mirror], xaxis[:flip])
xmax
else
xmin
end
yt = if sp[:framestyle] == :origin
0
elseif xor(zaxis[:mirror], yaxis[:flip])
ymax
else
ymin
end
for (cv, dv) in zip(zticks...)
xi, yi = gr_w3tondc(xt, yt, cv)
if zaxis[:ticks] in (:auto, :native)
if zaxis[:formatter] in (:scientific, :auto)
# ensure correct dispatch in gr_text for automatic log ticks
if zaxis[:scale] in _logScales
dv = string(dv, "\\ ")
end
dv = convert_sci_unicode(dv)
end
end
gr_text(xi + (zaxis[:mirror] ? 1 : -1) * 1e-2 * (zaxis[:tick_direction] == :out ? 1.5 : 1.0), yi, string(dv))
end
end
#
# # border
# intensity = sp[:framestyle] == :semi ? 0.5 : 1.0
# if sp[:framestyle] in (:box, :semi)
# gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
# gr_set_transparency(xaxis[:foreground_color_border], intensity)
# gr_polyline3d(coords(xborder_segs)...)
# gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
# gr_set_transparency(yaxis[:foreground_color_border], intensity)
# gr_polyline3d(coords(yborder_segs)...)
# end
elseif ispolar(sp)
r = gr_set_viewport_polar()
@@ -1116,9 +1415,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# @show cv dv ymin xi yi flip mirror (flip $ mirror)
if xaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks
if xaxis[:scale] in _logScales
dv = string(dv, "\\ ")
elseif xaxis[:formatter] in (:scientific, :auto)
if xaxis[:formatter] in (:scientific, :auto)
if xaxis[:scale] in _logScales
dv = string(dv, "\\ ")
end
dv = convert_sci_unicode(dv)
end
end
@@ -1135,9 +1435,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# @show cv dv xmin xi yi
if yaxis[:ticks] in (:auto, :native)
# ensure correct dispatch in gr_text for automatic log ticks
if yaxis[:scale] in _logScales
dv = string(dv, "\\ ")
elseif yaxis[:formatter] in (:scientific, :auto)
if yaxis[:formatter] in (:scientific, :auto)
if yaxis[:scale] in _logScales
dv = string(dv, "\\ ")
end
dv = convert_sci_unicode(dv)
end
end
@@ -1177,12 +1478,54 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
gr_text(xpos, viewport_subplot[4], sp[:title])
end
if is3d(sp)
gr_set_font(guidefont(xaxis))
GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide])
else
xticks, yticks = axis_drawing_info(sp)[1:2]
if xaxis[:guide] != ""
h = 0.01 + gr_xaxis_height(sp)
gr_set_font(
guidefont(xaxis),
halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
valign = (xaxis[:mirror] ? :bottom : :top),
rotation = xaxis[:rotation]
)
yg = xor(xaxis[:mirror], yaxis[:flip]) ? ymax : ymin
zg = xor(xaxis[:mirror], zaxis[:flip]) ? zmax : zmin
xg = (xmin + xmax) / 2
xndc, yndc = gr_w3tondc(xg, yg, zg)
h = gr_axis_height(sp, xaxis)
gr_text(xndc - h, yndc - h, xaxis[:guide])
end
if yaxis[:guide] != ""
gr_set_font(
guidefont(yaxis),
halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
valign = (yaxis[:mirror] ? :bottom : :top),
rotation = yaxis[:rotation]
)
xg = xor(yaxis[:mirror], xaxis[:flip]) ? xmin : xmax
yg = (ymin + ymax) / 2
zg = xor(yaxis[:mirror], zaxis[:flip]) ? zmax : zmin
xndc, yndc = gr_w3tondc(xg, yg, zg)
h = gr_axis_height(sp, yaxis)
gr_text(xndc + h, yndc - h, yaxis[:guide])
end
if zaxis[:guide] != ""
gr_set_font(
guidefont(zaxis),
halign = (:left, :hcenter, :right)[sign(zaxis[:rotation]) + 2],
valign = (zaxis[:mirror] ? :bottom : :top),
rotation = zaxis[:rotation]
)
xg = xor(zaxis[:mirror], xaxis[:flip]) ? xmax : xmin
yg = xor(zaxis[:mirror], yaxis[:flip]) ? ymax : ymin
zg = (zmin + zmax) / 2
xndc, yndc = gr_w3tondc(xg, yg, zg)
w = gr_axis_width(sp, zaxis)
GR.setcharup(-1, 0)
gr_text(xndc - w, yndc, zaxis[:guide])
end
else
if xaxis[:guide] != ""
h = 0.01 + gr_axis_height(sp, xaxis)
gr_set_font(guidefont(xaxis))
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
@@ -1194,7 +1537,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end
if yaxis[:guide] != ""
w = 0.02 + gr_yaxis_width(sp)
w = 0.02 + gr_axis_width(sp, yaxis)
gr_set_font(guidefont(yaxis))
GR.setcharup(-1, 0)
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
@@ -1573,7 +1916,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
for ann in sp[:annotations]
x, y, val = locate_annotation(sp, ann...)
x, y = if is3d(sp)
# GR.wc3towc(x, y, z)
gr_w3tondc(x, y, z)
else
GR.wctondc(x, y)
end
+63 -43
View File
@@ -1,4 +1,5 @@
using Contour: Contour
using UUIDs
Base.@kwdef mutable struct PGFPlotsXPlot
is_created::Bool = false
was_shown::Bool = false
@@ -8,25 +9,21 @@ Base.@kwdef mutable struct PGFPlotsXPlot
# tikz libraries
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{arrows.meta}")
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usetikzlibrary{backgrounds}")
PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
"""
\\pgfkeys{/tikz/.cd,
background color/.initial=white,
background color/.get=\\backcol,
background color/.store in=\\backcol,
}
\\tikzset{background rectangle/.style={
fill=\\backcol,
},
use background/.style={
show background rectangle
}
}
"""
)
# pgfplots libraries
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{patchplots}")
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{fillbetween}")
# compatibility fixes
# add background layer to standard layers
PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
raw"""
\pgfplotsset{
/pgfplots/layers/axis on top/.define layer set={
background, axis background,pre main,main,axis grid,axis ticks,axis lines,axis tick labels,
axis descriptions,axis foreground
}{/pgfplots/layers/standard},
}
"""
)
pgfx_plot
end
end
@@ -73,9 +70,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
cstr = plot_color(bgc)
a = alpha(cstr)
push!(the_plot.options,
"draw opacity" => a,
"background color" => cstr,
"use background" => nothing,
"/tikz/background rectangle/.style" => PGFPlotsX.Options(
"fill" => cstr,
"draw opacity" => a,
),
"show background rectangle" => nothing,
)
end
@@ -89,22 +88,22 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
"horizontal sep" => string(maximum(sp -> sp.minpad[1], plt.subplots)),
"vertical sep" => string(maximum(sp -> sp.minpad[2], plt.subplots)),
),
"height" => pl_height > 0 ? string(pl_height)*"px" : "{}",
"width" => pl_width > 0 ? string(pl_width)*"px" : "{}",
"height" => pl_height > 0 ? string(pl_height * px) : "{}",
"width" => pl_width > 0 ? string(pl_width * px) : "{}",
)
)
)
end
for sp in plt.subplots
bb = bbox(sp)
sp_width = width(bb)
sp_height = height(bb)
cstr = plot_color(sp[:background_color_legend])
a = alpha(cstr)
fg_alpha = alpha(plot_color(sp[:foreground_color_legend]))
title_cstr = plot_color(sp[:titlefontcolor])
title_a = alpha(title_cstr)
axis_opt = PGFPlotsX.Options(
"height" => string(height(bb)),
"width" => string(width(bb)),
"title" => sp[:title],
"title style" => PGFPlotsX.Options(
"font" => pgfx_font(sp[:titlefontsize], pgfx_thickness_scaling(sp)),
@@ -121,8 +120,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
),
"axis background/.style" => PGFPlotsX.Options(
"fill" => sp[:background_color_inside]
)
),
"axis on top" => nothing,
)
sp_width > 0*mm ? push!(axis_opt, "width" => string(sp_width)) : nothing
sp_height > 0*mm ? push!(axis_opt, "height" => string(sp_height)) : nothing
# legend position
if sp[:legend] isa Tuple
x, y = sp[:legend]
@@ -233,24 +235,18 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
segment_opt = merge( segment_opt, pgfx_marker(opt, i) )
end
if st == :shape ||
isfilledcontour(series) ||
series[:ribbon] !== nothing
isfilledcontour(series)
segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
end
# add fillrange
if series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
pgfx_fillrange_series!( axis, series, series_func, i, _cycle(series[:fillrange], rng), rng)
# add to legend?
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
io = IOBuffer()
PGFPlotsX.print_tex(io, pgfx_fillstyle(opt, i))
style = strip(String(take!(io)),['[',']', ' '])
push!( segment_opt, "legend image code/.code" => """{
\\draw[$style] (0cm,-0.1cm) rectangle (0.6cm,0.1cm);
}""" )
pgfx_filllegend!(series_opt, opt)
end
end
# series
#
coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng )
segment_plot = series_func(
merge(series_opt, segment_opt),
@@ -264,7 +260,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
end
# add to legend?
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
legend = PGFPlotsX.LegendEntry(PGFPlotsX.Options(), opt[:label], true)
leg_opt = PGFPlotsX.Options()
if ribbon !== nothing
pgfx_filllegend!(axis.contents[end-3].options, opt)
end
legend = PGFPlotsX.LegendEntry(leg_opt, opt[:label], false)
push!( axis, legend )
end
# add series annotations
@@ -499,6 +499,15 @@ function pgfx_arrow( arr::Arrow )
return "every arrow/.append style={$(components)}"
end
function pgfx_filllegend!( series_opt, opt )
io = IOBuffer()
PGFPlotsX.print_tex(io, pgfx_fillstyle(opt))
style = strip(String(take!(io)),['[',']', ' '])
push!( series_opt, "legend image code/.code" => """{
\\draw[$style] (0cm,-0.1cm) rectangle (0.6cm,0.1cm);
}""" )
end
function pgfx_colormap(grad::ColorGradient)
join(map(grad.colors) do c
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c), blue(c))
@@ -607,30 +616,41 @@ function pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_inde
ribbon_y = series[:ribbon]
opt = series.plotattributes
if ribbon_y isa AVec
ribbon_n = length(opt[:y]) ÷ length(ribbon)
ribbon_y = repeat(ribbon, outer = ribbon_n)
ribbon_n = length(opt[:y]) ÷ length(ribbon_y)
ribbon_yp = ribbon_ym = repeat(ribbon_y, outer = ribbon_n)
elseif ribbon_y isa Tuple
ribbon_ym, ribbon_yp = ribbon_y
ribbon_nm = length(opt[:y]) ÷ length(ribbon_ym)
ribbon_ym = repeat(ribbon_ym, outer = ribbon_nm)
ribbon_np = length(opt[:y]) ÷ length(ribbon_yp)
ribbon_yp = repeat(ribbon_yp, outer = ribbon_np)
else
ribbon_yp = ribbon_ym = ribbon_y
end
# upper ribbon
ribbon_name_plus = "plots_rib_p$series_index"
rib_uuid = uuid4()
ribbon_name_plus = "plots_rib_p$rib_uuid"
ribbon_opt_plus = merge(segment_plot.options, PGFPlotsX.Options(
"name path" => ribbon_name_plus,
"color" => opt[:fillcolor],
"draw opacity" => opt[:fillalpha]
"draw opacity" => opt[:fillalpha],
"forget plot" => nothing
))
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .+ ribbon_y)
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .+ ribbon_yp)
ribbon_plot_plus = series_func(
ribbon_opt_plus,
coordinates_plus
)
push!(axis, ribbon_plot_plus)
# lower ribbon
ribbon_name_minus = "plots_rib_m$series_index"
ribbon_name_minus = "plots_rib_m$rib_uuid"
ribbon_opt_minus = merge(segment_plot.options, PGFPlotsX.Options(
"name path" => ribbon_name_minus,
"color" => opt[:fillcolor],
"draw opacity" => opt[:fillalpha]
"draw opacity" => opt[:fillalpha],
"forget plot" => nothing
))
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .- ribbon_y)
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] .- ribbon_ym)
ribbon_plot_plus = series_func(
ribbon_opt_minus,
coordinates_plus
@@ -638,7 +658,7 @@ function pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_inde
push!(axis, ribbon_plot_plus)
# fill
push!(axis, series_func(
pgfx_fillstyle(opt, series_index),
merge(pgfx_fillstyle(opt, series_index), PGFPlotsX.Options("forget plot" => nothing)),
"fill between [of=$(ribbon_name_plus) and $(ribbon_name_minus)]"
))
return axis
+20 -3
View File
@@ -469,7 +469,7 @@ function layout_args(plotattributes::KW)
end
function layout_args(plotattributes::KW, n_override::Integer)
layout, n = layout_args(get(plotattributes, :layout, n_override))
layout, n = layout_args(n_override, get(plotattributes, :layout, n_override))
if n != n_override
error("When doing layout, n ($n) != n_override ($(n_override)). You're probably trying to force existing plots into a layout that doesn't fit them.")
end
@@ -481,12 +481,27 @@ function layout_args(n::Integer)
GridLayout(nr, nc), n
end
function layout_args(sztup::NTuple{2,I}) where I<:Integer
function layout_args(sztup::NTuple{2, Integer})
nr, nc = sztup
GridLayout(nr, nc), nr*nc
end
function layout_args(sztup::NTuple{3,I}) where I<:Integer
layout_args(n_override::Integer, n::Integer) = layout_args(n)
layout_args(n, sztup::NTuple{2, Integer}) = layout_args(sztup)
function layout_args(n, sztup::Tuple{Colon, Integer})
nc = sztup[2]
nr = ceil(Int, n / nc)
GridLayout(nr, nc), n
end
function layout_args(n, sztup::Tuple{Integer, Colon})
nr = sztup[1]
nc = ceil(Int, n / nr)
GridLayout(nr, nc), n
end
function layout_args(sztup::NTuple{3, Integer})
n, nr, nc = sztup
nr, nc = compute_gridsize(n, nr, nc)
GridLayout(nr, nc), n
@@ -499,6 +514,8 @@ function layout_args(layout::GridLayout)
layout, n
end
layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout)
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
+862 -862
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -4,7 +4,7 @@
Specify the colour theme for plots.
"""
function theme(s::Symbol; kw...)
defaults = PlotThemes._themes[s].defaults
defaults = copy(PlotThemes._themes[s].defaults)
_theme(s, defaults; kw...)
end
@@ -120,7 +120,8 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
subplot := 4
seriestype := :heatmap
seriescolor := colorgradient
ticks := -5:5:5
xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
x, y, z
end
@@ -128,12 +129,14 @@ _get_showtheme_args(thm::Symbol, func::Symbol) = thm, get(_color_functions, func
subplot := 5
seriestype := :surface
seriescolor := colorgradient
xticks := (-2π:2π:2π, string.(-2:2:2, "π"))
yticks := (-2π:2π:2π, string.(-2:2:2, "π"))
x, y, z
end
n = 100
ts = range(0, stop = 10π, length = n)
x = ts .* cos.(ts)
x = (0.1ts) .* cos.(ts)
y = (0.1ts) .* sin.(ts)
z = 1:n
+3 -1
View File
@@ -145,16 +145,18 @@ end
Segments() = Segments(Float64)
Segments(::Type{T}) where {T} = Segments(T[])
Segments(p::Int) = Segments(NTuple{2,Float64}[])
Segments(p::Int) = Segments(NTuple{p, Float64}[])
# Segments() = Segments(zeros(0))
to_nan(::Type{Float64}) = NaN
to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
to_nan(::Type{NTuple{3,Float64}}) = (NaN, NaN, NaN)
coords(segs::Segments{Float64}) = segs.pts
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
coords(segs::Segments{NTuple{3,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts], Float64[p[3] for p in segs.pts]
function Base.push!(segments::Segments{T}, vs...) where T
if !isempty(segments.pts)
+33 -3
View File
@@ -16,6 +16,9 @@ end
Plots._update_plot_object(pgfx_plot)
@test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument
@test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing
axis = Plots.pgfx_axes(pgfx_plot.o)[1]
@test count( x-> x isa PGFPlotsX.Plot, axis.contents ) == 1
@test !haskey(axis.contents[1].options.dict, "fill")
@testset "3D docs example" begin
n = 100
@@ -124,13 +127,40 @@ end
u = ones(length(x))
v = cos.(x)
plot( x, y, quiver = (u, v), arrow = true )
arrow_plot = plot( x, y, quiver = (u, v), arrow = true )
# TODO: could adjust limits to fit arrows if too long, but how?
# TODO: get latex available on CI
# mktempdir() do path
# @test_nowarn savefig(arrow_plot, path*"arrow.pdf")
# end
end # testset
@testset "Annotations" begin
y = rand(10)
plot(y, annotations=(3, y[3], Plots.text("this is \\#3", :left)), leg=false)
annotate!([(5, y[5], Plots.text("this is \\#5", 16, :red, :center)), (10, y[10], Plots.text("this is \\#10", :right, 20, "courier"))])
scatter!(range(2, stop=8, length=6), rand(6), marker=(50, 0.2, :orange), series_annotations=["series", "annotations", "map", "to", "series", Plots.text("data", :green)])
annotation_plot = scatter!(range(2, stop=8, length=6), rand(6), marker=(50, 0.2, :orange), series_annotations=["series", "annotations", "map", "to", "series", Plots.text("data", :green)])
# mktempdir() do path
# @test_nowarn savefig(annotation_plot, path*"annotation.pdf")
# end
end # testset
end # testset
@testset "Ribbon" begin
aa = rand(10)
bb = rand(10)
cc = rand(10)
conf = [aa-cc bb-cc]
ribbon_plot = plot(collect(1:10),fill(1,10), ribbon=(conf[:,1],conf[:,2]))
Plots._update_plot_object(ribbon_plot)
axis = Plots.pgfx_axes(ribbon_plot.o)[1]
plots = filter(x->x isa PGFPlotsX.Plot, axis.contents)
@test length(plots) == 4
@test !haskey(plots[1].options.dict, "fill")
@test !haskey(plots[2].options.dict, "fill")
@test !haskey(plots[3].options.dict, "fill")
@test haskey(plots[4].options.dict, "fill")
@test ribbon_plot.o !== nothing
@test ribbon_plot.o.the_plot !== nothing
# mktempdir() do path
# @test_nowarn savefig(ribbon_plot, path*"ribbon.svg")
# end
end # testset
end # testset