dretty sure this is not the best code example on how to do this.
but the idea seems to be good.
Use some circle packing, check the color of a black and white image (numbers or something similar) to color the circles red or green... works pretty well.
Here is the code. Like i said, i just quickly hacked it together using some code from somebody else but you get the idea.
- /*
Circle packing demo using the algorithm described here:
http://en.wiki.mcneel.com/default.aspx/McNeel/2DCirclePacking
Sean McCullough
banksean at gmail
June 17, 2007
*/
PImage img;
int circleNumber = 290;
ArrayList circles;
long iterationCounter = 0;
void setup() {
size( 900, 900 );
smooth();
fill( 0 );
frameRate( 30 );
circles = createRandomCircles(circleNumber);
background(255);
img = loadImage("7.gif");
}
void draw() {
background( 255 );
randomSeed(2);
for (int i=0; i<circles.size(); i++) {
getCircle(i).draw();
}
for (int i=1; i<50; i++) {
iterateLayout(40);
}
}
Comparator comp = new Comparator() {
public int compare(Object p1, Object p2) {
Circle a = (Circle)p1;
Circle b = (Circle)p2;
if (a.distanceToCenter() < b.distanceToCenter())
return 1;
else if (a.distanceToCenter() > b.distanceToCenter())
return -1;
else
return 0;
}
};
void iterateLayout(int iterationCounter) {
Object circs[] = circles.toArray();
Arrays.sort(circs, comp);
//fix overlaps
Circle ci, cj;
PVector v = new PVector();
for (int i=0; i<circs.length; i++) {
ci = (Circle)circs[i];
for (int j=i+1; j<circs.length; j++) {
if (i != j) {
cj = (Circle)circs[j];
float dx = cj.x - ci.x;
float dy = cj.y - ci.y;
float r = ci.radius + cj.radius;
float d = (dx*dx) + (dy*dy);
if (d < (r * r) - 0.01 ) {
v.x = dx;
v.y = dy;
v.normalize();
v.mult((r-sqrt(d))*0.5);
if (cj != dragCircle) {
cj.x += v.x;
cj.y += v.y;
}
if (ci != dragCircle) {
ci.x -= v.x;
ci.y -= v.y;
}
}
}
}
}
//Contract
float damping = 0.1/(float)(iterationCounter);
for (int i=0; i<circs.length; i++) {
Circle c = (Circle)circs[i];
if (c != dragCircle) {
v.x = c.x-width/2;
v.y = c.y-height/2;
v.mult(damping);
c.x -= v.x;
c.y -= v.y;
}
}
}
void mouseClicked() {
Circle c = new Circle(mouseX, mouseY, random(5,40));
c.myColor = color(random(255), 128, 200, 128);
c.myColor = color(100,100);
circles.add(c);
}
ArrayList createRandomCircles(int n) {
ArrayList circles = new ArrayList();
while (n-- > 0) {
Circle c = new Circle(random(width), random(height), random(5,30));
c.myColor = color(random(255), 128, 200, 128);
c.myColor = color(100,100);
circles.add(c);
}
colorMode(RGB,255);
return circles;
}
Circle getCircle(int i) {
return (Circle)circles.get(i);
}
Circle dragCircle = null;
void keyPressed() {
if (key == 'r' || key == 'R')
circles = createRandomCircles(circleNumber);
}
void mousePressed() {
dragCircle = null;
for(int i=0; i<circles.size(); i++) {
Circle c = getCircle(i);
if (c.contains(mouseX, mouseY)) {
dragCircle = c;
}
}
}
void mouseDragged() {
if (dragCircle != null) {
dragCircle.x = mouseX;
dragCircle.y = mouseY;
}
}
void mouseReleased() {
dragCircle = null;
}
class Circle {
public float x, y, radius;
public color myColor;
public Circle(float x, float y, float radius) {
this.x = x;
this.y = y;
this.radius = radius;
myColor = color(64,64,64,64);
}
public void draw() {
// fill(myColor);
noFill();
stroke(myColor);
strokeWeight(1);
fill(0,random(200,255),random(200,255));
if(img.get((int)x, (int)y)==color(0))fill(255,random(0,155),random(0,155));
ellipse((int)x, (int)y, (int)radius*2-5, (int)radius*2-5);
}
public boolean contains(float x, float y) {
float dx = this.x - x;
float dy = this.y - y;
return sqrt(dx*dx + dy*dy) <= radius;
}
public float distanceToCenter() {
float dx = x - WIDTH/2;
float dy = y - HEIGHT/2;
return (sqrt(dx*dx + dy*dy));
}
public boolean intersects(Circle c) {
float dx = c.x - x;
float dy = c.y - y;
float d = sqrt(dx*dx + dy*dy);
return d < radius || d < c.radius;
}
}