Drawing histograms
When I last showed how one might draw lots of different kinds of charts in Lua Carousel, I mentioned that histograms were still an open question. I think I have a reasonable way now to work in support for them.
A suitable point of take-off is the `boxes` chart I showed earlier.
function boxes(data, i, x, y, w) local w = optional(w, data, i, 5) local y = y(data, i) rect('fill', vx(x(data, i)-w/2), vy(y), scale(w), vy(0) - vy(y)) end
You call it like this:
color(0.7,0.7,1) plot(data, boxes, col(1), col(2), 4)
on some test data like this:
data = {} for i=1,16 do table.insert(data, {i*5, rand(60), rand(60)}) end
And you get a picture like this:
(I'm glossing over 40 lines of code, but they're almost identical to my previous post. You can see them at the bottom.)
A histogram is similar, but shows bars in clusters. Here's a new chart type:
function hbox(data, i, cluster, ncluster, y, w) local w = optional(w, data, i, 5) local clusterw = ncluster*w local x = (i-1)*clusterw + cluster*w local y = y(data, i) rect('fill', vx(x), vy(y), scale(w), vy(0) - vy(y)) end
This draws just one bar in each cluster, but it lets you string clusters together. For example, consider some example data containing 4 different (labeled) measures in each row:
data = {} for i=1,3 do table.insert(data, {a=rand(30), b=rand(30), c=rand(30), d=rand(30)}) end
(A realistic example might name the measures say 'revenue', 'costs' and 'profit' rather than a/b/c/d.)
We can plot this data as a histogram like so:
color(0.7,0.7,1) plot(data, hbox, 1,5, col('a')) color(0.5,0.8,0.8) plot(data, hbox, 2,5, col('b')) color(0.6,0.9,0.6) plot(data, hbox, 3,5, col('c')) color(1,0.7,0.7) plot(data, hbox, 4,5, col('d'))
Each set of bars gets an offset from 1 to 4, and 5 is left empty between clusters. The result looks like the image up top:For stacking bars atop one another we need to make hbox stateful as follows:
function hbox(data, i, cluster, ncluster, y, w) local w = optional(w, data, i, 5) local clusterw = ncluster*w local x = (i-1)*clusterw + cluster*w local y = y(data, i) local base = data[i].offsets[cluster] or 0 y = y + base rect('fill', vx(x), vy(y), scale(w), vy(base) - vy(y)) data[i].offsets[cluster] = y end
We're accumulating each stack as we render it, which allows us to draw clusters like this:
function clear_stack(data) for i=1,#data do data[i].offsets = {} end end clear_stack(data) color(0.7,0.7,1) plot(data, hbox, 1,4, col('a')) color(0.5,0.85,85) plot(data, hbox, 1,4, col('b')) color(0.6,0.9,0.6) plot(data, hbox, 2,4, col('c')) color(1,0.7,0.7) plot(data, hbox, 3,4, col('d'))
Repeated calls to `plot(..., 1,4, ...)` will continue to stack up until an intervening call to `clear_stack()`. The result looks like this:
Here's all of the code for drawing histograms with stacked support, including the usual Carousel abbreviations I use. Importantly, we had to make no changes to helpers like `plot` and `col` from the previous post.
g = love.graphics line, rect = g.line, g.rectangle color = g.setColor rand = math.random -- decide how large a 80:60 image you can fit H = Safe_height-Menu_bottom if Safe_width/80 < H/60 then -- landscape v = {left=50, right=Safe_width-50} local h = (v.right-v.left)/80*60 v.top = Menu_bottom + (H-h)/2 v.bottom = v.top + h else -- portrait v = {top=Menu_bottom+50, bottom=Safe_height-50} local w = (v.bottom-v.top)/60*80 v.left = (Safe_width-w)/2 v.right = v.left + w end -- at this point, 80/(v.right-v.left) == 60/(v.bottom-v.top) line(v.left, v.top, v.left, v.bottom) line(v.left, v.bottom, v.right, v.bottom) function vx(x) return v.left + scale(x) end function vy(y) return v.bottom - scale(y) end function scale(d) return d/80*(v.right-v.left) end function col(c) return function(data, i) return data[i][c] end end function plot(data, f, ...) for i=1,#data do f(data, i, ...) end end function optional(f, data, i, default) if f == nil then return default end if type(f) == 'function' then return f(data, i) end return f end data = {} for i=1,3 do table.insert(data, {a=rand(30), b=rand(30), c=rand(30), d=rand(30)}) end function clear_stack(data) for i=1,#data do data[i].offsets = {} end end function hbox(data, i, cluster, ncluster, y, w) local w = optional(w, data, i, 5) local clusterw = ncluster*w local x = (i-1)*clusterw + cluster*w local y = y(data, i) local base = data[i].offsets[cluster] or 0 y = y + base rect('fill', vx(x), vy(y), scale(w), vy(base) - vy(y)) data[i].offsets[cluster] = y end clear_stack(data) color(0.7,0.7,1) plot(data, hbox, 1,4, col('a')) color(0.5,0.85,85) plot(data, hbox, 1,4, col('b')) color(0.6,0.9,0.6) plot(data, hbox, 2,4, col('c')) color(1,0.7,0.7) plot(data, hbox, 3,4, col('d'))
Get Lua Carousel
Lua Carousel
Write programs on desktop and mobile
Status | In development |
Category | Tool |
Author | Kartik Agaram |
Tags | LÖVE |
More posts
- New version after 3 days26 days ago
- New version after 40 days29 days ago
- Turn your phone or tablet into a chess clock43 days ago
- Guest program: bouncing balls59 days ago
- New version after 3 months, and turtle graphics70 days ago
- Interactively zooming in to the Mandelbrot set on a touchscreen89 days ago
- A little timer app90 days ago
- New version after 4 monthsJun 28, 2024
- Visualizing the digits of πMay 04, 2024
Leave a comment
Log in with itch.io to leave a comment.