diff --git a/src/geom/shape.jl b/src/geom/shape.jl new file mode 100644 index 000000000..ccb4b144d --- /dev/null +++ b/src/geom/shape.jl @@ -0,0 +1,82 @@ + + +# Geometry which displays arbitrary shapes at given (x, y) positions. +immutable ShapeGeometry{T} <: Gadfly.GeometryElement + vertices::T + tag::Symbol +end + +function ShapeGeometry(shape; tag::Symbol=Gadfly.Geom.empty_tag) + ShapeGeometry(shape, tag) +end + +const shape = ShapeGeometry + + +function Gadfly.element_aesthetics(::ShapeGeometry) + [:x, :y, :size, :color] +end + + +# Generate a form for a shape geometry. +# +# Args: +# geom: shape geometry. +# theme: the plot's theme. +# aes: aesthetics. +# +# Returns: +# A compose Form. +# +function Gadfly.render(geom::ShapeGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics) + + Gadfly.assert_aesthetics_defined("Geom.shape", aes, :x, :y) + Gadfly.assert_aesthetics_equal_length("Geom.shape", aes, + element_aesthetics(geom)...) + + default_aes = Gadfly.Aesthetics() + default_aes.color = Gadfly.DataFrames.PooledDataArray(RGBA{Float32}[theme.default_color]) + default_aes.size = Compose.Measure[theme.default_point_size] + aes = Gadfly.inherit(aes, default_aes) + + lw_hover_scale = 10 + lw_ratio = theme.line_width / aes.size[1] + + aes_x, aes_y = Gadfly.concretize(aes.x, aes.y) + + ctx = Compose.compose!( + Compose.context(), + make_polygon(geom, aes.x, aes.y, aes.size), + Compose.fill(aes.color), + Compose.linewidth(theme.highlight_width)) + + if aes.color_key_continuous != nothing && aes.color_key_continuous + Compose.compose!(ctx, + Compose.stroke(map(theme.continuous_highlight_color, aes.color))) + else + Compose.compose!(ctx, + Compose.stroke(map(theme.discrete_highlight_color, aes.color)), + Compose.svgclass([Gadfly.svg_color_class_from_label(Gadfly.escape_id(aes.color_label([c])[1])) + for c in aes.color])) + end + + return Compose.compose!(Compose.context(order=4), Compose.svgclass("geometry"), ctx) +end + + +# create a Compose context given a ShapeGeometry and the xs/ys/sizes +function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray, rs::AbstractArray) + n = max(length(xs), length(ys), length(rs)) + T = Tuple{Compose.Measure, Compose.Measure} + polys = Array(Vector{T}, n) + for i in 1:n + x = Compose.x_measure(xs[mod1(i, length(xs))]) + y = Compose.y_measure(ys[mod1(i, length(ys))]) + r = rs[mod1(i, length(rs))] + polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in geom.vertices] + end + Gadfly.polygon(polys, geom.tag) +end + + +# --------------------------------------------------------------------------------------------- diff --git a/src/geometry.jl b/src/geometry.jl index ea6a1e97a..1fb645ec8 100644 --- a/src/geometry.jl +++ b/src/geometry.jl @@ -70,5 +70,6 @@ include("geom/ribbon.jl") include("geom/violin.jl") include("geom/polygon.jl") include("geom/beeswarm.jl") +include("geom/shape.jl") end # module Geom