<script src="d3.min.js"></script>
<script src="cubehelix.min.js"></script>
var sample = bestCandidateSampler(width, height, 10, 10000),
while (s = sample()) samples.push(s);
var voronoi = d3.geom.voronoi()
.clipExtent([[0, 0], [width, height]]); // TODO overdraw
var color = d3.scale.cubehelix()
.range([d3.hsl(96, .6, 1), d3.hsl(276, .6, 0)])
d3.select("body").append("svg")
.style("fill", function(d) { return color(d3.geom.polygon(d).area()); })
.attr("d", function(d) { return "M" + d.join("L") + "Z"; });
function bestCandidateSampler(width, height, numCandidates, numSamplesMax) {
var quadtree = d3.geom.quadtree()
.extent([[0, 0], [width, height]])
([[Math.random() * width, Math.random() * height]]);
if (++numSamples > numSamplesMax) return;
var bestCandidate, bestDistance = 0;
for (var i = 0; i < numCandidates; ++i) {
var c = [Math.random() * width, Math.random() * height],
d = distance(quadtree.find(c[0], c[1]), c);
quadtree.add(bestCandidate);
function distance(a, b) {
return dx * dx + dy * dy;