add ribbons

This commit is contained in:
Simon Christ 2019-11-25 14:18:25 +01:00
parent f53b070d79
commit acf4cb4e5b

View File

@ -26,6 +26,7 @@ Base.@kwdef mutable struct PGFPlotsXPlot
) )
# pgfplots libraries # pgfplots libraries
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{patchplots}") PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{patchplots}")
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, "\\usepgfplotslibrary{fillbetween}")
pgfx_plot pgfx_plot
end end
end end
@ -147,116 +148,122 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
end end
@label colorbar_end @label colorbar_end
push!(axis_opt, "colorbar style" => PGFPlotsX.Options( push!(axis_opt, "colorbar style" => PGFPlotsX.Options(
"title" => sp[:colorbar_title], "title" => sp[:colorbar_title],
"point meta max" => get_clims(sp)[2], "point meta max" => get_clims(sp)[2],
"point meta min" => get_clims(sp)[1] "point meta min" => get_clims(sp)[1]
) )
) )
if is3d(sp) if is3d(sp)
azim, elev = sp[:camera] azim, elev = sp[:camera]
push!( axis_opt, "view" => (azim, elev) ) push!( axis_opt, "view" => (azim, elev) )
end end
axisf = if sp[:projection] == :polar axisf = if sp[:projection] == :polar
# push!(axis_opt, "xmin" => 90) # push!(axis_opt, "xmin" => 90)
# push!(axis_opt, "xmax" => 450) # push!(axis_opt, "xmax" => 450)
PGFPlotsX.PolarAxis PGFPlotsX.PolarAxis
else else
PGFPlotsX.Axis PGFPlotsX.Axis
end end
axis = axisf( axis = axisf(
axis_opt axis_opt
) )
for (series_index, series) in enumerate(series_list(sp)) for (series_index, series) in enumerate(series_list(sp))
opt = series.plotattributes opt = series.plotattributes
st = series[:seriestype] st = series[:seriestype]
series_opt = PGFPlotsX.Options( series_opt = PGFPlotsX.Options(
"color" => single_color(opt[:linecolor]), "color" => single_color(opt[:linecolor]),
) )
if is3d(series) || st == :heatmap #|| isfilledcontour(series) 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 && !isfilledcontour(series) 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
push!(axis.options, push!(axis.options,
"view" => "{0}{90}", "view" => "{0}{90}",
"shader" => "flat corner", "shader" => "flat corner",
) )
end end
# treat segments # treat segments
segments = if st in (:wireframe, :heatmap, :contour, :surface, :contour3d) 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)
end end
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 if opt[:markershape] != :none
marker = opt[:markershape] marker = opt[:markershape]
if marker isa Shape if marker isa Shape
x = marker.x x = marker.x
y = marker.y y = marker.y
scale_factor = 0.025 scale_factor = 0.025
mark_size = opt[:markersize] * scale_factor mark_size = opt[:markersize] * scale_factor
path = join(["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], " -- ") path = join(["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], " -- ")
c = get_markercolor(series, i) c = get_markercolor(series, i)
a = get_markeralpha(series, i) a = get_markeralpha(series, i)
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
""" """
\\pgfdeclareplotmark{PlotsShape$(series_index)}{ \\pgfdeclareplotmark{PlotsShape$(series_index)}{
\\filldraw \\filldraw
$path; $path;
} }
""" """
) )
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 || if st == :shape ||
(series[:fillrange] !== nothing && !isfilledcontour(series)) (series[:fillrange] !== nothing && !isfilledcontour(series)) &&
segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) ) series[:ribbon] === nothing
end segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng ) end
segment_plot = series_func( coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng )
merge(series_opt, segment_opt), segment_plot = series_func(
coordinates, merge(series_opt, segment_opt),
(series[:fillrange] !== nothing && !isfilledcontour(series)) ? "\\closedcycle" : "{}" coordinates,
) (series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing) ? "\\closedcycle" : "{}"
push!(axis, segment_plot) )
# add to legend? push!(axis, segment_plot)
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series) # add ribbons?
push!( axis, PGFPlotsX.LegendEntry( opt[:label] ) ribbon = series[:ribbon]
) if ribbon !== nothing
end pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
# add series annotations end
anns = series[:series_annotations] # add to legend?
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y]) if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
pgfx_add_annotation!(axis, xi, yi, PlotText(str, fnt), pgfx_thickness_scaling(series)) push!( axis, PGFPlotsX.LegendEntry( opt[:label] )
end )
end end
# add subplot annotations # add series annotations
anns = sp.attr[:annotations] anns = series[:series_annotations]
for (xi,yi,txt) in anns for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
pgfx_add_annotation!(axis, xi, yi, txt) pgfx_add_annotation!(axis, xi, yi, PlotText(str, fnt), pgfx_thickness_scaling(series))
end end
end end
if ispolar(sp) # add subplot annotations
axes = the_plot anns = sp.attr[:annotations]
else for (xi,yi,txt) in anns
axes = the_plot.elements[1] pgfx_add_annotation!(axis, xi, yi, txt)
end end
push!( axes, axis ) end
if length(plt.o.the_plot.elements) > 0 if ispolar(sp)
plt.o.the_plot.elements[1] = the_plot axes = the_plot
else else
push!(plt.o, the_plot) axes = the_plot.elements[1]
end end
end push!( axes, axis )
if length(plt.o.the_plot.elements) > 0
plt.o.the_plot.elements[1] = the_plot
else
push!(plt.o, the_plot)
end
end
pgfx_plot.is_created = true pgfx_plot.is_created = true
end end
end end
@ -570,6 +577,45 @@ function pgfx_add_annotation!(o, x, y, val, thickness_scaling = 1)
"{$(val.str).};" "{$(val.str).};"
]) ])
end end
function pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
ribbon = series[:ribbon]
opt = series.plotattributes
ribbon_n = length(opt[:y]) ÷ length(ribbon)
ribbon_y = repeat(ribbon, outer = ribbon_n)
# upper ribbon
ribbon_name_plus = "plots_rib_p$series_index"
ribbon_opt_plus = merge(segment_plot.options, PGFPlotsX.Options(
"name path" => ribbon_name_plus,
"color" => opt[:fillcolor],
"draw opacity" => opt[:fillalpha]
))
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] + ribbon_y)
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_opt_minus = merge(segment_plot.options, PGFPlotsX.Options(
"name path" => ribbon_name_minus,
"color" => opt[:fillcolor],
"draw opacity" => opt[:fillalpha]
))
coordinates_plus = PGFPlotsX.Coordinates(opt[:x], opt[:y] - ribbon_y)
ribbon_plot_plus = series_func(
ribbon_opt_minus,
coordinates_plus
)
push!(axis, ribbon_plot_plus)
# fill
push!(axis, series_func(
pgfx_fillstyle(opt, series_index),
"fill between [of=$(ribbon_name_plus) and $(ribbon_name_minus)]"
))
return axis
end
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
axis = sp[Symbol(letter,:axis)] axis = sp[Symbol(letter,:axis)]