# Pretty Circles

The functions in this class require Underscore's library, and it should be loaded on the HTML page prior to including this module.

We can't pass an operator into Underscore's `reduce`

function, so we
simply create an `add`

function:

add = (x, y) -> x + y

The `sum`

function use's Underscore's `reduce`

function calling the
`add`

function on each element in our `lst`

.

sum = (lst) -> _.reduce(lst, add, 0)

A `roll`

function takes `how_many`

dice to roll, and also the number
of `sides`

those dice have. Basically, the range for the random
numbers.

roll = (how_many, sides) -> dice = -> _.random(1,sides) sum( _.times(how_many, dice) )

We now use the `roll`

function to skew the results towards a
particular `goal`

within a `range`

:

goal_roll = (goal, range) -> steep = 20 # Number of dice to roll sides = (range + steep) / steep # Number of sides on the dice delta = goal - range / 2 results = roll(steep, sides) - steep + delta console.log "Roll:", results, sides, goal, delta if (results > range) return results - range else return results

We now pick a random color (hue, actually) that clusters around a
particular `goal`

between 1 and 100:

get_color = (goal) -> hue = goal_roll(goal, 100) / 100 sat = _.random(.8, .9) lit = _.random(.5, .6) hslToRgb(hue, sat, lit)

Converts an HSL color value to RGB. Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space. Assumes h, s, and l are contained in the set [0, 1] and returns r, g, and b in the set [0, 255].

hslToRgb = (h, s, l) -> if (s == 0) r = g = b = l # achromatic else hue2rgb = (p, q, t) -> if (t < 0) then t += 1 if (t > 1) then t -= 1 if (t < 1/6) p + (q - p) * 6 * t else if (t < 1/2) q else if (t < 2/3) p + (q - p) * (2/3 - t) * 6 else p q = if l < 0.5 then l * (1 + s) else l + s - l * s p = 2 * l - q r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); # return [r * 255, g * 255, b * 255]; "#" + dec2hex(r*255) + dec2hex(g*255) + dec2hex(b*255);

Since our RGB color values need to be 0 padded when they are converted to hex, we have this lovely little function:

dec2hex = (v) -> if (v < 16) "0" + Math.floor(v).toString(16) else Math.floor(v).toString(16);

While the HTML5 canvas is nice, it good use a little helper function to draw a circle with a single command:

disk = (canvas, color, x, y, radius) -> canvas.fillStyle = color canvas.beginPath() canvas.arc(x, y, radius, 0, Math.PI*2, true) canvas.closePath() canvas.fill()

Now it is time to acquire a drawing canvas and go to work, but not
until the HTML has been loaded with the `window.onload`

event:

window.onload = -> drawingCanvas = document.getElementById('pretty-circles') # Check the element is in the DOM and the browser supports canvas if drawingCanvas.getContext # Initaliaze a 2-dimensional drawing context context = drawingCanvas.getContext('2d') hue = _.random(1,100) for x in [10..490] by 20 for y in [10..490] by 20 disk context, get_color(hue), x, y, _.random(2,10)