Hello, I am trying to visualize Diffusion Limited Aggregation and some of my circles are overlapping. I tried repositioning them but they still overlap. How can I fix this? My code is below:
import java.lang.Math;
ArrayList<Particle> brownianTree = new ArrayList<Particle>();
ArrayList<Particle> particles = new ArrayList<Particle>();
int initialParticles = 100; // initial number of mobile partilces on screen
int max = 600; // maximum number of particles on screen
float d = 15; // diameter of circles
float hue = 0; // hue value
int hueStart; // starting value of hue
int noOfTimes = 100; // speed indicator of particles
int maxNoOfTimes = 400; // maximum speed of particles
int minNoOfTimes = 10; //minimum speed of particles
float ratio = 1.001; // rate of decrease of circles' radii
void setup() {
size(1280,720);
brownianTree.add(new Particle(new PVector(width/2, height/2), true));
d /= ratio;
generatePosition();
}
void draw() {
background(0);
for (int i = 0; i < brownianTree.size(); i ++) {
// change hue of particles as they are added to the list
hue = map(i, 0, max, hueStart, 255);
brownianTree.get(i).display();
}
for (int i = 0; i < particles.size(); i ++) {
particles.get(i).displayParticles();
}
for (int k = 0; k < noOfTimes; k ++) { // make particle move faster
for (int i = 0; i < particles.size(); i ++) {
particles.get(i).move();
if (particles.get(i).isAttached()) {
Particle currentParticle = particles.get(i);
brownianTree.add(currentParticle);//add particle to tree
particles.remove(currentParticle); // remove particle from the 'particles' list
}
}
}
}
// particles generated around the edge
void generatePosition() {
for (int i = 0; i < initialParticles/4; i ++) {
particles.add(new Particle(new PVector(random(width), 0), false));
d /= ratio;
}
for (int i = 0; i < initialParticles/4; i ++) {
particles.add(new Particle(new PVector(random(width), height), false));
d /= ratio;
}
for (int i = 0; i < initialParticles/4; i ++) {
particles.add(new Particle(new PVector(0, random(height)), false));
d /= ratio;
}
for (int i = 0; i < initialParticles/4; i ++) {
particles.add(new Particle(new PVector(width, random(height)), false));
d /= ratio;
}
}
/*
USER INTERACTIONS
*/
void keyPressed() {
if (key == '2') {
//initialise arrays
brownianTree = new ArrayList<Particle>();
particles = new ArrayList<Particle>();
max = 1000;
ratio = 1.0005;
initialParticles = 100;
d = 15; // 'reset' value of diameter
// add tree to bottom
for (int x = 0; x < width; x += d) {
brownianTree.add(new Particle(new PVector(x, height), true));
d /= ratio;
}
// add particles to top
for (int i = 0; i < initialParticles; i ++) {
particles.add(new Particle(new PVector(random(width),0), false));
d /= ratio;
}
}
if (key == '3') {
brownianTree = new ArrayList<Particle>();
particles = new ArrayList<Particle>();
max = 1450;
ratio = 1.0001;
initialParticles = 50;
d = 15;
// add circles on the boundaries of the sketch
for (int x = 0; x < width; x += d) {
brownianTree.add(new Particle(new PVector(x, height), true));
d /= ratio;
}
for (int x = 0; x < width; x += d) {
brownianTree.add(new Particle(new PVector(x, 0), true));
d /= ratio;
}
for (int y = 0; y < width; y += d) {
brownianTree.add(new Particle(new PVector(0, y), true));
d /= ratio;
}
for (int y = 0; y < width; y += d) {
brownianTree.add(new Particle(new PVector(width, y), true));
d /= ratio;
}
for (int i = 0; i < initialParticles; i ++) {
particles.add(new Particle(new PVector(width/2, height/2,0), false));
d /= ratio;
}
}
if (key == '1') {
brownianTree = new ArrayList<Particle>();
particles = new ArrayList<Particle>();
max = 600;
ratio = 1.001;
initialParticles = 100;
d = 15;
brownianTree.add(new Particle(new PVector(width/2, height/2), true));
d /= ratio;
generatePosition();
}
if (key == 'r') {
hueStart = 2; // start with red circles
}
if (key == 'b') {
hueStart = 170; // start with blue circles
}
if (key == 'g') {
hueStart = 85; // start with green circles
}
if (key == CODED) {
if (keyCode == UP) {
if (noOfTimes < maxNoOfTimes) {
noOfTimes += 10; // increase speed of particles
}
}
}
if (key == CODED) {
if (keyCode == DOWN) {
if (noOfTimes > minNoOfTimes) {
noOfTimes -= 10; // decrease speed of particles
}
}
}
}
void mousePressed() {
int number = 5;
if (mousePressed && (mouseButton == LEFT)) {
// number of particles on screen does not exceed max
if (particles.size() + brownianTree.size() + number <= max) {
for (int i = 0; i < number; i ++) { //add 5 particles
particles.add(new Particle(new PVector(mouseX, mouseY), false));
d /= ratio;
}
}
}
if (mousePressed && (mouseButton == RIGHT)) {
if (particles.size() > number*2) { // moving particles on screen must be at least 10
for (int i = 0; i < number; i ++) { // remove 5 particles
Particle current = particles.get(i);
particles.remove(current);
d *= ratio;
}
}
}
}
class Particle {
PVector location;
boolean attached;
float size;
// constructor
public Particle(PVector position, boolean stuck) {
location = position;
attached = stuck;
size = d;
}
// move particles around the screen
void move() {
PVector velocity = PVector.random2D();
location.add(velocity);
// prevent particles from leaving the sketch
location.x = constrain(location.x, 0, width);
location.y = constrain(location.y, 0, height);
}
// Checks whether particles are attached or not
boolean isAttached() {
for (int i = 0; i < brownianTree.size(); i ++) {
Particle current = brownianTree.get(i);
float distance = calcDistance(location.x, location.y, current.location.x, current.location.y);
if (distance < (d/2+current.size/2)*(d/2+current.size/2)) {
// reposition circles so they do not overlap
float angle = atan2(location.y-current.location.y, location.x-current.location.x);
println("dy is: " + (location.y - current.location.y));
println("dx is: " + (location.x - current.location.x));
float distanceBetween = sqrt(calcDistance(location.x,location.y,current.location.x,current.location.y));
float distToMove = d/2+current.size/2 - distanceBetween;
if (distToMove > 0) { // if distToMove is equal to 0, do not reposition circles
PVector displacement = new PVector(cos(angle)*distToMove, cos(angle)*distToMove);
location.add(displacement);
println("Distance to move is: " + distToMove);
println("Distance between is: " + distanceBetween);
println("Angle is: " + angle);
println("Displacement is: " + cos(angle)*distToMove);
}
attached = true;
return true;
}
}
return false;
}
// display tree-particles
void display() {
strokeWeight(0.5);
colorMode(HSB);
fill(hue, 255, 255);
ellipse(location.x, location.y, size, size);
}
/* Calculates the square of the distance betweeen 2 particles.
Also avoids using square root so program runs faster */
float calcDistance(float a1, float b1, float a2, float b2) {
float adj = a2 - a1;
float opp = b2 - b1;
float distSquared = adj*adj+opp*opp; // calculates hypotenuse*hypotenuse
return distSquared;
}
// display moving particles
void displayParticles() {
strokeWeight(0.5);
colorMode(RGB);
fill(255, 255, 255);
ellipse(location.x, location.y, size, size);
}
}