Created
March 19, 2012 01:33
-
-
Save louismullie/2089431 to your computer and use it in GitHub Desktop.
Space-filling with an arbitrary number of circles with predefined radii
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* 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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How would one call this on an HTML page?