diff --git a/docs/src/gallery/geometries.md b/docs/src/gallery/geometries.md index 073d47035..43d103418 100644 --- a/docs/src/gallery/geometries.md +++ b/docs/src/gallery/geometries.md @@ -407,16 +407,26 @@ plot(x=[0, 1, 1, 2, 2, 3, 3, 2, 2, 1, 1, 0, 4, 5, 5, 4], ``` -## [`Geom.rect`](@ref), [`Geom.rectbin`](@ref) +## [`Geom.rect`](@ref) ```@example -using Gadfly, Colors, DataFrames, RDatasets -set_default_plot_size(21cm, 8cm) +using Gadfly, Colors, DataFrames +set_default_plot_size(14cm, 8cm) theme1 = Theme(default_color=RGBA(0, 0.75, 1.0, 0.5)) -D = DataFrame(x=[0.5,1], y=[0.5,1], x1=[0,0.5], y1=[0,0.5], x2=[1,1.5], y2=[1,1.5]) -pa = plot(D, x=:x, y=:y, Geom.rectbin, theme1) -pb = plot(D, xmin=:x1, ymin=:y1, xmax=:x2, ymax=:y2, Geom.rect, theme1) -hstack(pa, pb) +D = DataFrame(x1=[0,0.5], y1=[0,0.5], x2=[1,1.5], y2=[1,1.5]) +plot(D, xmin=:x1, ymin=:y1, xmax=:x2, ymax=:y2, Geom.rect, theme1) + +``` + +## [`Geom.rectbin`](@ref) + +```@example +using Gadfly, Colors, DataFrames +set_default_plot_size(14cm, 8cm) +theme1 = Theme(default_color=RGBA(0, 0.75, 1.0, 0.5)) +D = DataFrame(x=[0.5,1], y=[0.5,1]) +plot(D, x=:x, y=:y, Geom.rectbin, theme1) + ``` ```@example diff --git a/src/geom/rect.jl b/src/geom/rect.jl new file mode 100644 index 000000000..b66130ccf --- /dev/null +++ b/src/geom/rect.jl @@ -0,0 +1,99 @@ +using Compose: x_measure, y_measure + +struct RectangularGeometry <: Gadfly.GeometryElement + default_statistic::Gadfly.StatisticElement + tag::Symbol +end + +function RectangularGeometry( + default_statistic::Gadfly.StatisticElement=Gadfly.Stat.identity(); + tag=empty_tag) + RectangularGeometry(default_statistic, tag) +end + +""" + Geom.rect + +Draw colored rectangles with the corners specified by the +`xmin`, `xmax`, `ymin` and `ymax` aesthetics. Optionally +specify their `color`. +""" +const rect = RectangularGeometry + +default_statistic(geom::RectangularGeometry) = geom.default_statistic + +element_aesthetics(::RectangularGeometry) = + [:xmin, :xmax, :ymin, :ymax, :color] + +# Render rectangle geometry. +# +# Args: +# geom: rect geometry +# theme: the plot's theme +# aes: some aesthetics +# +# Returns +# A compose form. +# +function render(geom::RectangularGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics) + + default_aes = Gadfly.Aesthetics() + default_aes.color = discretize_make_ia(RGBA{Float32}[theme.default_color]) + aes = inherit(aes, default_aes) + + Gadfly.assert_aesthetics_defined("RectangularGeometry", aes, :xmin, :xmax, :ymin, :ymax) + Gadfly.assert_aesthetics_equal_length("RectangularGeometry", aes, :xmin, :xmax, :ymin, :ymax) + + xmin = aes.xmin + xmax = aes.xmax + ymin = aes.ymin + ymax = aes.ymax + + n = length(xmin) + + if length(aes.color) == n + cs = aes.color + else + cs = Vector{RGBA{Float32}}(undef, n) + for i in 1:n + cs[i] = aes.color[((i - 1) % length(aes.color)) + 1] + end + end + + allvisible = true + for c in cs + if c == nothing + allvisible = false + break + end + end + + if !allvisible + visibility = cs .!= nothing + cs = cs[visibility] + xmin = xmin[visibility] + xmax = xmax[visibility] + ymin = ymin[visibility] + ymax = ymax[visibility] + end + + polys = Vector{Vector{Tuple{Measure, Measure}}}(undef, length(xmin)) + for i in 1:length(xmin) + x0 = x_measure(xmin[i]) + x1 = x_measure(xmax[i]) + y0 = y_measure(ymin[i]) + y1 = y_measure(ymax[i]) + polys[i] = Tuple{Measure, Measure}[(x0, y0), (x0, y1), (x1, y1), (x1, y0)] + end + + properties = ( + stroke(nothing), #TODO: Apply theme attributes. + svgclass("geometry"), + svgattribute("shape-rendering", "crispEdges")) + + return compose!( + context(), + Compose.polygon(polys, geom.tag), + fill(cs), + properties...) +end diff --git a/src/geom/rectbin.jl b/src/geom/rectbin.jl index 9b64363ff..ca56aaf54 100644 --- a/src/geom/rectbin.jl +++ b/src/geom/rectbin.jl @@ -1,4 +1,3 @@ -### should refactor to RectangleGeometry with Identity as the default Stat. struct RectangularBinGeometry <: Gadfly.GeometryElement default_statistic::Gadfly.StatisticElement tag::Symbol @@ -18,15 +17,6 @@ specify their `color`. """ const rectbin = RectangularBinGeometry -""" - Geom.rect - -Draw colored rectangles with the corners specified by the -`xmin`, `xmax`, `ymin` and `ymax` aesthetics. Optionally -specify their `color`. -""" -rect() = RectangularBinGeometry(Gadfly.Stat.Identity()) - """ Geom.histogram2d[(; xbincount=nothing, xminbincount=3, xmaxbincount=150, ybincount=nothing, yminbincount=3, ymaxbincount=150)] @@ -39,12 +29,12 @@ information. function histogram2d(; xbincount=nothing, xminbincount=3, xmaxbincount=150, ybincount=nothing, yminbincount=3, ymaxbincount=150) RectangularBinGeometry( - Gadfly.Stat.histogram2d(xbincount=xbincount, - xminbincount=xminbincount, - xmaxbincount=xmaxbincount, - ybincount=ybincount, - yminbincount=yminbincount, - ymaxbincount=ymaxbincount)) + Gadfly.Stat.histogram2d(xbincount = xbincount, + xminbincount = xminbincount, + xmaxbincount = xmaxbincount, + ybincount = ybincount, + yminbincount = yminbincount, + ymaxbincount = ymaxbincount)) end default_statistic(geom::RectangularBinGeometry) = geom.default_statistic @@ -76,11 +66,11 @@ function render(geom::RectangularBinGeometry, theme::Gadfly.Theme, aes::Gadfly.A n = nx xmin = aes.xmin - xwidths = [(x1 - x0)*cx - theme.bar_spacing + xwidths = [(x1 - x0) * cx - theme.bar_spacing for (x0, x1) in zip(aes.xmin, aes.xmax)] ymin = aes.ymin - ywidths = [(y1 - y0)*cy - theme.bar_spacing + ywidths = [(y1 - y0) * cy - theme.bar_spacing for (y0, y1) in zip(aes.ymin, aes.ymax)] if length(aes.color) == n diff --git a/src/geometry.jl b/src/geometry.jl index f695b81fb..eb335d09c 100644 --- a/src/geometry.jl +++ b/src/geometry.jl @@ -59,6 +59,7 @@ include("geom/hvband.jl") include("geom/label.jl") include("geom/line.jl") include("geom/point.jl") +include("geom/rect.jl") include("geom/rectbin.jl") include("geom/subplot.jl") include("geom/ribbon.jl") diff --git a/test/testscripts/rect.jl b/test/testscripts/rect.jl new file mode 100644 index 000000000..cb75a759b --- /dev/null +++ b/test/testscripts/rect.jl @@ -0,0 +1,11 @@ +using DataFrames, Gadfly + +set_default_plot_size(21cm, 8cm) + +Da = DataFrame(x1 = [0, 0.5], y1 = [0, 0.5], x2 = [0.5, 1], y2 = [0.5, 1]) +pa = plot(Da, xmin = :x1, ymin = :y1, xmax = :x2, ymax = :y2, Geom.rect) # Shared corner coordinate. + +Db = DataFrame(x1 = [0, 0.5], y1 = [0, 0.5], x2 = [1, 1.5], y2 = [1, 1.5]) +pb = plot(Db, xmin = :x1, ymin = :y1, xmax = :x2, ymax = :y2, Geom.rect) # Overlapping rects. + +hstack(pa,pb) diff --git a/test/testscripts/rectbin.jl b/test/testscripts/rectbin.jl index 2bce23b2c..606415244 100644 --- a/test/testscripts/rectbin.jl +++ b/test/testscripts/rectbin.jl @@ -5,7 +5,5 @@ set_default_plot_size(6inch, 3inch) # using RDatasets # plot(dataset("Zelig", "macro"), x="Year", y="Country", color="GDP", Geom.rectbin) -D = DataFrame(x=[0.5,1], y=[0.5,1], x1=[0,0.5], y1=[0,0.5], x2=[1,1.5], y2=[1,1.5]) -pa = plot(D, x=:x, y=:y, Geom.rectbin) -pb = plot(D, xmin=:x1, ymin=:y1, xmax=:x2, ymax=:y2, Geom.rect) -hstack(pa,pb) +D = DataFrame(x=[0.5,1], y=[0.5,1]) +plot(D, x=:x, y=:y, Geom.rectbin)