From 8cdef406e04a51f4c6df2a41da5fe0c5301e471d Mon Sep 17 00:00:00 2001 From: t-bltg Date: Wed, 2 Feb 2022 15:45:01 +0100 Subject: [PATCH 1/4] UnicodePlots 3d support --- src/backends.jl | 14 +++++++--- src/backends/unicodeplots.jl | 54 ++++++++++++++++++++++++------------ src/examples.jl | 5 +--- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index 3ed11b5bb..fa19a2ac5 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -914,7 +914,7 @@ const _unicodeplots_attr = merge_with_base_supported([ :annotations, :bins, :guide, - # :grid, + :grid, :label, :layout, :legend, @@ -928,18 +928,27 @@ const _unicodeplots_attr = merge_with_base_supported([ :seriesalpha, :seriescolor, :scale, + :flip, :title, + # :marker_z, + :line_z, ]) const _unicodeplots_seriestype = [ :path, + :path3d, :scatter, + :scatter3d, :straightline, # :bar, :shape, :histogram2d, :heatmap, :contour, + # :contour3d, :spy, + :surface, + :wireframe, + # :mesh3d, ] const _unicodeplots_style = [:auto, :solid] const _unicodeplots_marker = [ @@ -972,9 +981,6 @@ const _unicodeplots_marker = [ ] const _unicodeplots_scale = [:identity, :ln, :log2, :log10] -# Additional constants -const _up_colormap = Ref(:none) - # ------------------------------------------------------------------------------ # hdf5 diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 2e8c13980..5aebf343f 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -16,7 +16,6 @@ const _canvas_map = ( # do all the magic here... build it all at once, # since we need to know about all the series at the very beginning function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) - plt.attr[:warn_on_unsupported] = false plt.o = UnicodePlots.Plot[] has_layout = prod(size(plt.layout)) > 1 @@ -25,24 +24,26 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) yaxis = sp[:yaxis] xlim = collect(axis_limits(sp, :x)) ylim = collect(axis_limits(sp, :y)) + zlim = collect(axis_limits(sp, :z)) F = float(eltype(xlim)) # We set x/y to have a single point, # since we need to create the plot with some data. # Since this point is at the bottom left corner of the plot, # it should be hidden by consecutive plotting commands. - x = F[xlim[1]] - y = F[ylim[1]] + x = Vector{F}(xlim) + y = Vector{F}(ylim) + z = Vector{F}(zlim) # create a plot window with xlim/ylim set, # but the X/Y vectors are outside the bounds - canvas = if (up_c = get(sp[:extra_kwargs], :canvas, :auto)) == :auto + canvas = if (up_c = get(sp[:extra_kwargs], :canvas, :auto)) === :auto isijulia() ? :ascii : :braille else up_c end - border = if (up_b = get(sp[:extra_kwargs], :border, :auto)) == :auto + border = if (up_b = get(sp[:extra_kwargs], :border, :auto)) === :auto isijulia() ? :ascii : :solid else up_b @@ -52,6 +53,7 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) width = has_layout && isempty(series_list(sp)) ? 0 : UnicodePlots.DEFAULT_WIDTH[] height = UnicodePlots.DEFAULT_HEIGHT[] + plot_3d = is3d(sp) blend = get(sp[:extra_kwargs], :blend, true) grid = xaxis[:grid] && yaxis[:grid] quiver = contour = false @@ -70,6 +72,8 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) grid &= !(quiver || contour) blend &= !(quiver || contour) + plot_3d && (xlim = ylim = (0, 0)) # determined using projection + kw = ( compact = true, title = texmath2unicode(sp[:title]), @@ -84,11 +88,15 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) border = border, xlim = xlim, ylim = ylim, + # 3d + projection = plot_3d ? :orthographic : nothing, + azimuth = -50, + up = sp[:zaxis][:flip] ? :mz : :pz, ) - o = UnicodePlots.Plot(x, y, _canvas_map[canvas]; kw...) + o = UnicodePlots.Plot(x, y, plot_3d ? z : nothing, _canvas_map[canvas]; kw...) for series in series_list(sp) - o = addUnicodeSeries!(sp, o, kw, series, sp[:legend_position] != :none) + o = addUnicodeSeries!(sp, o, kw, series, sp[:legend_position] !== :none, plot_3d) end for ann in sp[:annotations] @@ -125,6 +133,7 @@ function addUnicodeSeries!( kw, series, addlegend::Bool, + plot_3d::Bool ) st = series[:seriestype] @@ -134,7 +143,7 @@ function addUnicodeSeries!( elseif st === :shape shape_data(series) else - float(series[:x]), float(series[:y]) + series[:x], series[:y] end # special handling (src/interface) @@ -142,12 +151,13 @@ function addUnicodeSeries!( if st === :histogram2d return UnicodePlots.densityplot(x, y; kw...) elseif st === :spy - return UnicodePlots.spy(series[:z].surf; fix_ar = fix_ar, kw...) - elseif st in (:contour, :heatmap) + return UnicodePlots.spy(Array(series[:z]); fix_ar = fix_ar, kw...) + elseif st in (:contour, :heatmap) # 2D + colormap = get(series[:extra_kwargs], :colormap, :none) kw = ( kw..., zlabel = sp[:colorbar_title], - colormap = (cm = _up_colormap[] === :none) ? up_cmap(series) : cm, + colormap = colormap === :none ? up_cmap(series) : colormap, colorbar = hascolorbar(sp), ) if st === :contour @@ -156,21 +166,30 @@ function addUnicodeSeries!( return UnicodePlots.contourplot( x, y, - series[:z].surf; + Array(series[:z]); kw..., levels = series[:levels], ) elseif st === :heatmap - return UnicodePlots.heatmap(series[:z].surf; fix_ar = fix_ar, kw...) - # zlim = collect(axis_limits(sp, :z)) + return UnicodePlots.heatmap(Array(series[:z]); fix_ar = fix_ar, kw...) end + elseif st in (:wireframe, :surface) # 3D + colormap = get(series[:extra_kwargs], :colormap, :none) + kw = ( + kw..., + zlabel = sp[:colorbar_title], + colormap = colormap === :none ? up_cmap(series) : colormap, + colorbar = hascolorbar(sp), + color = st === :wireframe ? up_color(get_linecolor(series, 1)) : nothing + ) + return UnicodePlots.surfaceplot(x, y, Array(series[:z]); kw...) end # now use the ! functions to add to the plot - if st in (:path, :straightline, :shape) + if st in (:path, :path3d, :straightline, :shape) func = UnicodePlots.lineplot! series_kw = (; head_tail = series[:arrow] isa Arrow ? series[:arrow].side : nothing) - elseif st === :scatter || series[:markershape] != :none + elseif st in (:scatter, :scatter3d) || series[:markershape] !== :none func = UnicodePlots.scatterplot! series_kw = (; marker = series[:markershape]) else @@ -185,7 +204,8 @@ function addUnicodeSeries!( up = func( up, x[rng], - y[rng]; + y[rng], + plot_3d ? series[:z][rng] : nothing; color = up_color(lc), name = n == 1 ? label : "", series_kw..., diff --git a/src/examples.jl b/src/examples.jl index 1dcfae1b5..0d4fcb9be 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -1302,7 +1302,6 @@ _backend_skips = Dict( 6, # embedded images unsupported 16, # nested layout unsupported 21, # custom markers unsupported - 24, # 3D unsupported 26, # nested layout unsupported 27, # polar plots unsupported 29, # nested layout unsupported @@ -1313,10 +1312,8 @@ _backend_skips = Dict( 45, # error bars 47, # mesh3D unsupported 49, # polar heatmap - 50, # 3D surface unsupported 51, # embedded images unsupported - 52, # 3D quiver unsupported - 55, # 3D unsupported + 55, # mirror unsupported, resolution too low 56, # barplots ], :gaston => [ From a29ed28a0e82ce1d48ca64f75026dd101ca37147 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Thu, 3 Feb 2022 17:33:20 +0100 Subject: [PATCH 2/4] add `:mesh3d` --- src/backends.jl | 2 +- src/backends/unicodeplots.jl | 15 +++++++++++---- src/examples.jl | 1 - 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/backends.jl b/src/backends.jl index fa19a2ac5..e426cda07 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -948,7 +948,7 @@ const _unicodeplots_seriestype = [ :spy, :surface, :wireframe, - # :mesh3d, + :mesh3d, ] const _unicodeplots_style = [:auto, :solid] const _unicodeplots_marker = [ diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 5aebf343f..70fef1dcd 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -90,8 +90,10 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) ylim = ylim, # 3d projection = plot_3d ? :orthographic : nothing, - azimuth = -50, up = sp[:zaxis][:flip] ? :mz : :pz, + # PyPlot: azimuth = -60 & elevation = 30 + azimuth = -45, + elevation = 30, ) o = UnicodePlots.Plot(x, y, plot_3d ? z : nothing, _canvas_map[canvas]; kw...) @@ -173,20 +175,25 @@ function addUnicodeSeries!( elseif st === :heatmap return UnicodePlots.heatmap(Array(series[:z]); fix_ar = fix_ar, kw...) end - elseif st in (:wireframe, :surface) # 3D + elseif st in (:surface, :wireframe) # 3D colormap = get(series[:extra_kwargs], :colormap, :none) kw = ( kw..., zlabel = sp[:colorbar_title], colormap = colormap === :none ? up_cmap(series) : colormap, colorbar = hascolorbar(sp), - color = st === :wireframe ? up_color(get_linecolor(series, 1)) : nothing + color = st === :wireframe ? up_color(get_linecolor(series, 1)) : nothing, + lines = st === :wireframe, ) return UnicodePlots.surfaceplot(x, y, Array(series[:z]); kw...) + elseif st === :mesh3d + return UnicodePlots.lineplot!( + up, mesh3d_triangles(x, y, series[:z], series[:connections])... + ) end # now use the ! functions to add to the plot - if st in (:path, :path3d, :straightline, :shape) + if st in (:path, :path3d, :straightline, :shape, :mesh3d) func = UnicodePlots.lineplot! series_kw = (; head_tail = series[:arrow] isa Arrow ? series[:arrow].side : nothing) elseif st in (:scatter, :scatter3d) || series[:markershape] !== :none diff --git a/src/examples.jl b/src/examples.jl index 0d4fcb9be..2524d3918 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -1310,7 +1310,6 @@ _backend_skips = Dict( 37, # ribbons / filled unsupported 43, # heatmap with DateTime 45, # error bars - 47, # mesh3D unsupported 49, # polar heatmap 51, # embedded images unsupported 55, # mirror unsupported, resolution too low From ed50b7fcb4e7b4d59724ad5f07f2f5617d3c5b28 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 7 Feb 2022 19:43:27 +0100 Subject: [PATCH 3/4] bump UnicodePlots version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 16c95dd2a..fdd5a3f01 100644 --- a/Project.toml +++ b/Project.toml @@ -55,7 +55,7 @@ Scratch = "1" Showoff = "0.3.1, 1.0" StatsBase = "0.32 - 0.33" UnicodeFun = "0.4" -UnicodePlots = "2.6" +UnicodePlots = "2.8" Unzip = "0.1" julia = "1.6" From 44b81fa94dbc7077e47ff0ad824d91c22498d324 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Mon, 7 Feb 2022 19:58:24 +0100 Subject: [PATCH 4/4] format --- src/backends/unicodeplots.jl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 70fef1dcd..039e16ebd 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -98,7 +98,14 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) o = UnicodePlots.Plot(x, y, plot_3d ? z : nothing, _canvas_map[canvas]; kw...) for series in series_list(sp) - o = addUnicodeSeries!(sp, o, kw, series, sp[:legend_position] !== :none, plot_3d) + o = addUnicodeSeries!( + sp, + o, + kw, + series, + sp[:legend_position] !== :none, + plot_3d, + ) end for ann in sp[:annotations] @@ -135,7 +142,7 @@ function addUnicodeSeries!( kw, series, addlegend::Bool, - plot_3d::Bool + plot_3d::Bool, ) st = series[:seriestype] @@ -188,7 +195,8 @@ function addUnicodeSeries!( return UnicodePlots.surfaceplot(x, y, Array(series[:z]); kw...) elseif st === :mesh3d return UnicodePlots.lineplot!( - up, mesh3d_triangles(x, y, series[:z], series[:connections])... + up, + mesh3d_triangles(x, y, series[:z], series[:connections])..., ) end