From 9266d3db653adfb931af9e8253b99ab47e09975c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sun, 24 Mar 2019 10:37:10 +1100 Subject: [PATCH 1/7] Develop RectangularGeometry --- src/geom/rect.jl | 93 ++++++++++++++++++++++++++++++++++++++++ src/geom/rectbin.jl | 26 ++++------- src/geometry.jl | 1 + test/testscripts/rect.jl | 6 +++ 4 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 src/geom/rect.jl create mode 100644 test/testscripts/rect.jl diff --git a/src/geom/rect.jl b/src/geom/rect.jl new file mode 100644 index 000000000..683867798 --- /dev/null +++ b/src/geom/rect.jl @@ -0,0 +1,93 @@ +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) + + nx = length(aes.xmin) + ny = length(aes.ymin) + n = nx + + xmin = aes.xmin + xwidths = [(x1 - x0) * cx + for (x0, x1) in zip(aes.xmin, aes.xmax)] + + ymin = aes.ymin + ywidths = [(y1 - y0) * cy + for (y0, y1) in zip(aes.ymin, aes.ymax)] + + 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 + + return compose!( + context(), + rectangle(xmin, ymin, xwidths, ywidths, geom.tag), + fill(cs), + stroke(nothing), + svgclass("geometry"), + svgattribute("shape-rendering", "crispEdges")) + +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..0ab761be8 --- /dev/null +++ b/test/testscripts/rect.jl @@ -0,0 +1,6 @@ +using DataFrames, Gadfly + +set_default_plot_size(6inch, 3inch) + +D = DataFrame(x1 = [0, 0.5], y1 = [0, 0.5], x2 = [1, 1.5], y2 = [1, 1.5]) +pb = plot(D, xmin = :x1, ymin = :y1, xmax = :x2, ymax = :y2, Geom.rect) From a769495ffcfd4cf28964b35f61dce3ef13e1eab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sat, 16 Mar 2019 14:46:41 +1100 Subject: [PATCH 2/7] Correct visibility logic --- src/geom/rect.jl | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/geom/rect.jl b/src/geom/rect.jl index 683867798..19aa01204 100644 --- a/src/geom/rect.jl +++ b/src/geom/rect.jl @@ -44,17 +44,12 @@ function render(geom::RectangularGeometry, theme::Gadfly.Theme, aes::Gadfly.Aest Gadfly.assert_aesthetics_defined("RectangularGeometry", aes, :xmin, :xmax, :ymin, :ymax) Gadfly.assert_aesthetics_equal_length("RectangularGeometry", aes, :xmin, :xmax, :ymin, :ymax) - nx = length(aes.xmin) - ny = length(aes.ymin) - n = nx - xmin = aes.xmin - xwidths = [(x1 - x0) * cx - for (x0, x1) in zip(aes.xmin, aes.xmax)] - + xmax = aes.xmax ymin = aes.ymin - ywidths = [(y1 - y0) * cy - for (y0, y1) in zip(aes.ymin, aes.ymax)] + ymax = aes.ymax + + n = length(xmin) if length(aes.color) == n cs = aes.color @@ -82,6 +77,12 @@ function render(geom::RectangularGeometry, theme::Gadfly.Theme, aes::Gadfly.Aest ymax = ymax[visibility] end + xwidths = [(x1 - x0) * cx + for (x0, x1) in zip(xmin, xmax)] + + ywidths = [(y1 - y0) * cy + for (y0, y1) in zip(ymin, ymax)] + return compose!( context(), rectangle(xmin, ymin, xwidths, ywidths, geom.tag), From 3b529fffa716a0f608f9e2615bb5cd81e8918a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sat, 16 Mar 2019 14:49:46 +1100 Subject: [PATCH 3/7] Use Compose.polygon --- src/geom/rect.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/geom/rect.jl b/src/geom/rect.jl index 19aa01204..7b823e0a4 100644 --- a/src/geom/rect.jl +++ b/src/geom/rect.jl @@ -77,18 +77,20 @@ function render(geom::RectangularGeometry, theme::Gadfly.Theme, aes::Gadfly.Aest ymax = ymax[visibility] end - xwidths = [(x1 - x0) * cx - for (x0, x1) in zip(xmin, xmax)] - - ywidths = [(y1 - y0) * cy - for (y0, y1) in zip(ymin, ymax)] + 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 return compose!( context(), - rectangle(xmin, ymin, xwidths, ywidths, geom.tag), + Compose.polygon(polys), fill(cs), stroke(nothing), svgclass("geometry"), svgattribute("shape-rendering", "crispEdges")) - end From 134e935f3c409f85e3e956655ebc891863e20237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Sun, 24 Mar 2019 09:09:15 +1100 Subject: [PATCH 4/7] Develop RectangularGeometry return --- src/geom/rect.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/geom/rect.jl b/src/geom/rect.jl index 7b823e0a4..b66130ccf 100644 --- a/src/geom/rect.jl +++ b/src/geom/rect.jl @@ -86,11 +86,14 @@ function render(geom::RectangularGeometry, theme::Gadfly.Theme, aes::Gadfly.Aest 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), + Compose.polygon(polys, geom.tag), fill(cs), - stroke(nothing), - svgclass("geometry"), - svgattribute("shape-rendering", "crispEdges")) + properties...) end From 1185c44ee1819a753352195a301a7458eb7011f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 8 Apr 2019 20:58:19 +1000 Subject: [PATCH 5/7] Separate Geom.rect and Geom.rectbin gallery examples --- docs/src/gallery/geometries.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) 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 From a7fce1fd09b30e3dabfd9014eb7f1a76e52e4abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Mon, 8 Apr 2019 22:34:34 +1000 Subject: [PATCH 6/7] Remove Geom.rect from Geom.rectbin test --- test/testscripts/rectbin.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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) From 8d72b8598e1a5c7dc5cd6897215eda441bb89a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20O=27Mara?= Date: Tue, 16 Apr 2019 10:34:11 +1000 Subject: [PATCH 7/7] Develop rect test to determine overlap --- test/testscripts/rect.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/testscripts/rect.jl b/test/testscripts/rect.jl index 0ab761be8..cb75a759b 100644 --- a/test/testscripts/rect.jl +++ b/test/testscripts/rect.jl @@ -1,6 +1,11 @@ using DataFrames, Gadfly -set_default_plot_size(6inch, 3inch) +set_default_plot_size(21cm, 8cm) -D = DataFrame(x1 = [0, 0.5], y1 = [0, 0.5], x2 = [1, 1.5], y2 = [1, 1.5]) -pb = plot(D, xmin = :x1, ymin = :y1, xmax = :x2, ymax = :y2, Geom.rect) +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)