Skip to content

Instantly share code, notes, and snippets.

@louismullie
Created March 19, 2012 01:33
Show Gist options
  • Save louismullie/2089431 to your computer and use it in GitHub Desktop.
Save louismullie/2089431 to your computer and use it in GitHub Desktop.
Space-filling with an arbitrary number of circles with predefined radii
/*
*
* Space-filling with circles
*
* Authors: Kris Van Bael.
* Small modifications by Louis Mullie.
*
*
* Usage:
*
* drawCircles(paper, circles, colors)
* - Paper is a Raphael Paper object.
* - Circles is an array of radii.
* - Colors is an array of colors.
*
* Example:
* var paper = Raphael(10, 50, 800, 600);
* var colors = ['#99cccc', '#99ccff', '#ff6633', '#cccc66'];
* var radii = [90, 50, 60, 100, 60, 40, 90, 50, 60, 100, 60, 40];
*
* drawCircles(paper, radii, colors);
*
* Requires Raphael (http://raphaeljs.com/).
*/
function createGrid(columns, rows, size) {
var grid = [];
var y = size / 2.0;
for (row = 0; row < rows; row++) {
var distanceFromTop = y;
var distanceFromBottom = height - y;
for (col = 0; col < columns; col++) {
var i = row * columns + col;
grid[i] = (distanceFromTop <  distanceFromBottom) ?
distanceFromTop : distanceFromBottom;
}
y += size;
}
var x = size / 2.0;
for (col = 0; col < columns; col++) {
var distanceFromLeft = x;
var distanceFromRight = width - x;
for (row = 0; row < rows; row++) {
var i = row * columns + col;
if (grid[i] > distanceFromLeft) {
grid[i] = distanceFromLeft;
}
if (grid[i] > distanceFromRight) { 
grid[i] = distanceFromRight;
}
}
x += size;
}
return grid;
}
function drawCircles(paper, circles, colors) {
var size = Math.sqrt(paper.width * paper.height / 1000);
var columns = Math.ceil(paper.width / size);
var rows = Math.ceil(paper.height / size);
var grid = createGrid(columns, rows, size);
var json = [];
circles = circles.sort().reverse();
for (circle = 0; circle < circles.length; circle++) {
// We assume circles are sorted large to small!
var radius = circles[circle];
// Find gridpoint with largest distance from anything
var i = 0;
var maxR = 0;
var maxC = 0;
var maxDist = grid[0];
for (row = 0; row < rows; row++) {
for (col = 0; col < columns; col++) {
if (maxDist < grid[i]) {
maxR = row;
maxC = col;
maxDist = grid[i];
}
i++;
}
}
var k = Math.random() * colors.length;
var c = colors[Math.floor(k)];
var x = size / 2.0 + maxC * size;
var y = size / 2.0 + maxR * size;
var offset = (maxDist - radius) / 2.0;
x += Math.random() * offset;
y += Math.random() * offset;
json.push({
type: "circle",
cx: x,
cy: y,
r: radius,
stroke: Raphael.rgb2hsb(c),
fill: '#ffffff'
});
// Update Distance array with new circle;
i = 0;
var yy = size / 2.0;
for (r = 0; r < rows; r++) {
var xx = size / 2.0;
for (c = 0; c < columns; c++) {
var d2 = (xx - x) * (xx - x) + (yy - y) * (yy - y);
var prev2 = grid[i] + radius;
prev2 *= prev2;
if (prev2 > d2) {
var d = Math.sqrt(d2) - radius;
if (grid[i] > d) {
grid[i] = d;
}
}
xx += size;
i++;
}
yy += size;
}
}
paper.add(json);
}
@tackdetack
Copy link

How would one call this on an HTML page?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment