filled contour (really)

This commit is contained in:
Simon Christ 2019-11-24 16:46:20 +01:00
parent 8553bef132
commit 8cb32b1f14
3 changed files with 59 additions and 31 deletions

View File

@ -708,7 +708,7 @@ const _pgfplotsx_attr = merge_with_base_supported([
const _pgfplotsx_seriestype = const _pgfplotsx_seriestype =
[:path, :scatter, :straightline, [:path, :scatter, :straightline,
:path3d, :scatter3d, :surface, :wireframe, :path3d, :scatter3d, :surface, :wireframe,
:heatmap, :contour, :histogram2d, :heatmap, :contour, :contour3d, :histogram2d,
:shape, :shape,
:steppre, :stepmid, :steppost, :ysticks, :xsticks] :steppre, :stepmid, :steppost, :ysticks, :xsticks]
const _pgfplotsx_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] const _pgfplotsx_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]

View File

@ -1,5 +1,4 @@
using Contour: Contour using Contour: Contour
using StatsBase: Histogram, fit
# PGFPlotsX.print_tex(io::IO, data::ColorGradient) = write(io, pgfx_colormap(data)) # PGFPlotsX.print_tex(io::IO, data::ColorGradient) = write(io, pgfx_colormap(data))
Base.@kwdef mutable struct PGFPlotsXPlot Base.@kwdef mutable struct PGFPlotsXPlot
is_created::Bool = false is_created::Bool = false
@ -140,13 +139,18 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
series_opt = PGFPlotsX.Options( series_opt = PGFPlotsX.Options(
"color" => single_color(opt[:linecolor]), "color" => single_color(opt[:linecolor]),
) )
if is3d(series) || st == :heatmap if is3d(series) || st == :heatmap #|| isfilledcontour(series)
series_func = PGFPlotsX.Plot3 series_func = PGFPlotsX.Plot3
else else
series_func = PGFPlotsX.Plot series_func = PGFPlotsX.Plot
end end
if series[:fillrange] !== nothing && st != :contour if isfilledcontour(series)
series_opt = merge(series_opt, pgfx_fillstyle(opt)) # push!(series_opt, "contour filled" => nothing)
# st = :surface
# axis_opt["view"] = (0, 90)
# push!(series_opt, "shader" => "interp")
end
if series[:fillrange] !== nothing && !isfilledcontour(series)
push!(series_opt, "area legend" => nothing) push!(series_opt, "area legend" => nothing)
end end
if st == :heatmap if st == :heatmap
@ -156,7 +160,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
) )
end end
# treat segments # treat segments
segments = if st in (:wireframe, :heatmap, :contour, :surface) segments = if st in (:wireframe, :heatmap, :contour, :surface, :contour3d)
iter_segments(surface_to_vecs(series[:x], series[:y], series[:z])...) iter_segments(surface_to_vecs(series[:x], series[:y], series[:z])...)
else else
iter_segments(series) iter_segments(series)
@ -164,7 +168,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
segment_opt = PGFPlotsX.Options() segment_opt = PGFPlotsX.Options()
for (i, rng) in enumerate(segments) for (i, rng) in enumerate(segments)
segment_opt = merge( segment_opt, pgfx_linestyle(opt, i) ) segment_opt = merge( segment_opt, pgfx_linestyle(opt, i) )
if opt[:markershape] != :none #|| !iscontour(series) && !(st == :heatmap) if opt[:markershape] != :none
marker = opt[:markershape] marker = opt[:markershape]
if marker isa Shape if marker isa Shape
x = marker.x x = marker.x
@ -182,23 +186,17 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
end end
segment_opt = merge( segment_opt, pgfx_marker(opt, i) ) segment_opt = merge( segment_opt, pgfx_marker(opt, i) )
end end
if st == :shape || series[:fillrange] !== nothing if st == :shape ||
(series[:fillrange] !== nothing && !isfilledcontour(series))
segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) ) segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
end end
if iscontour(series) coordinates = pgfx_series_coordinates!( sp,
if !isfilledcontour(series) isfilledcontour(series) ? :filledcontour : st,
push!(series_opt, segment_opt, opt, rng )
"contour prepared" => PGFPlotsX.Options(
"labels" => opt[:contour_labels],
)
)
end
end
coordinates = pgfx_series_coordinates!( sp, st, segment_opt, opt, rng )
segment_plot = series_func( segment_plot = series_func(
merge(series_opt, segment_opt), merge(series_opt, segment_opt),
coordinates, coordinates,
series[:fillrange] !== nothing ? "\\closedcycle" : "{}" (series[:fillrange] !== nothing && !isfilledcontour(series)) ? "\\closedcycle" : "{}"
) )
push!(axis, segment_plot) push!(axis, segment_plot)
# add to legend? # add to legend?
@ -236,10 +234,10 @@ end
## seriestype specifics ## seriestype specifics
@inline function pgfx_series_coordinates!(sp, st, segment_opt, opt, rng) @inline function pgfx_series_coordinates!(sp, st, segment_opt, opt, rng)
# function args # function args
args = if st == :contour args = if st in (:contour, :contour3d, :filledcontour)
opt[:x], opt[:y], opt[:z].surf' opt[:x], opt[:y], Array(opt[:z])'
elseif st in (:heatmap, :surface, :wireframe) elseif st in (:heatmap, :surface, :wireframe)
surface_to_vecs(opt[:x], opt[:y], opt[:z]) surface_to_vecs(opt[:x], opt[:y], opt[:z])
elseif is3d(st) elseif is3d(st)
opt[:x], opt[:y], opt[:z] opt[:x], opt[:y], opt[:z]
elseif st == :straightline elseif st == :straightline
@ -252,7 +250,7 @@ end
else else
opt[:x], opt[:y] opt[:x], opt[:y]
end end
seg_args = if st == :contour || st == :heatmap seg_args = if st in (:contour, :contour3d, :heatmap, :filledcontour)
args args
else else
(arg[rng] for arg in args) (arg[rng] for arg in args)
@ -305,8 +303,6 @@ function pgfx_series_coordinates!(st_val::Val{:xsticks}, segment_opt, opt, args)
return PGFPlotsX.Coordinates(args...) return PGFPlotsX.Coordinates(args...)
end end
function pgfx_series_coordinates!(st_val::Val{:surface}, segment_opt, opt, args) function pgfx_series_coordinates!(st_val::Val{:surface}, segment_opt, opt, args)
@show collect(args)[3] |> length
@show args
push!( segment_opt, "surf" => nothing, push!( segment_opt, "surf" => nothing,
"mesh/rows" => length(opt[:x]), "mesh/rows" => length(opt[:x]),
"mesh/cols" => length(opt[:y]), "mesh/cols" => length(opt[:y]),
@ -327,10 +323,42 @@ function pgfx_series_coordinates!(st_val::Val{:shape}, segment_opt, opt, args)
push!( segment_opt, "area legends" => nothing ) push!( segment_opt, "area legends" => nothing )
return PGFPlotsX.Coordinates(args...) return PGFPlotsX.Coordinates(args...)
end end
function pgfx_series_coordinates!(st_val::Val{:contour}, segment_opt, opt, args) function pgfx_series_coordinates!(st_val::Union{Val{:contour}, Val{:contour3d}}, segment_opt, opt, args)
push!(segment_opt,
"contour prepared" => PGFPlotsX.Options(
"labels" => opt[:contour_labels],
),
)
return PGFPlotsX.Table(Contour.contours(args..., opt[:levels])) return PGFPlotsX.Table(Contour.contours(args..., opt[:levels]))
end end
function pgfx_series_coordinates!(st_val::Val{:filledcontour}, segment_opt, opt, args)
xs, ys, zs = collect(args)
push!(segment_opt,
"contour filled" => PGFPlotsX.Options(
"labels" => opt[:contour_labels],
),
"point meta" => "explicit",
"shader" => "flat"
)
if opt[:levels] isa Number
push!(segment_opt["contour filled"],
"number" => opt[:levels],
)
elseif opt[:levels] isa AVec
push!(segment_opt["contour filled"],
"levels" => opt[:levels],
)
end
cs = join([
join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") for (i, y) in enumerate(ys)], "\n\n"
)
"""
coordinates {
$cs
};
"""
end
## ##
const _pgfplotsx_linestyles = KW( const _pgfplotsx_linestyles = KW(
:solid => "solid", :solid => "solid",
@ -428,10 +456,9 @@ pgfx_thickness_scaling(series) = pgfx_thickness_scaling(series[:subplot])
function pgfx_fillstyle(plotattributes, i = 1) function pgfx_fillstyle(plotattributes, i = 1)
cstr = get_fillcolor(plotattributes, i) cstr = get_fillcolor(plotattributes, i)
a = alpha(cstr) a = get_fillalpha(plotattributes, i)
fa = get_fillalpha(plotattributes, i) if a === nothing
if fa !== nothing a = alpha(single_color(cstr))
a = fa
end end
PGFPlotsX.Options("fill" => cstr, "fill opacity" => a) PGFPlotsX.Options("fill" => cstr, "fill opacity" => a)
end end

View File

@ -100,6 +100,7 @@ end
p2 = contour(x, y, Z) p2 = contour(x, y, Z)
p1 = contour(x, y, f, fill=true) p1 = contour(x, y, f, fill=true)
plot(p1, p2) plot(p1, p2)
# TODO: colorbar for filled contours
end # testset end # testset
@testset "Varying colors" begin @testset "Varying colors" begin
t = range(0, stop=1, length=100) t = range(0, stop=1, length=100)