Growth
A circle with a random radius and colour is drawn on the canvas and positioned next to the circle that is closest to it.Creating the First Circle
A circle object created from the class Circle
has the following properties. This class takes values for the
x and y coordinates and the radius. The colour of the circle is taken from a defined colour palette.
class Circle {
constructor(_x, _y, _r) {
this.coordinates = createVector(_x, _y);
this.radius = _r;
this.colour = colorPalette[1];
}
}
The first circle is positioned at the centre of the canvas. This object is inserted into the circles
array which is used
to store all the circles that are drawn on the canvas.
let circles;
let minRadius = 5;
let maxRadius = 10;
let circle0;
function setup() {
[...]
circle0 = new Circle(width/2, height/2, maxRadius);
circles.push(circle0);
}
Creating the Other Circles
The addCircle()
function creates a new circle object each time draw()
runs. At first,
the circles that are created are given random x
and y
positions.
function draw() {
background(217, 0, 100);
addCircle();
}
function addCircle() {
let randX = random(width);
let randY = random(height);
let randR = floor(random(minR, maxR));
// Create a circle
let newC = new Circle(randX, randY, randR);
circles.push(newC);
}
Drawing the Circles
The render()
method of class Circle
draws an ellipse and is called
on each circle object.
class Circle {
[...]
render() {
noStroke();
fill(this.colour);
ellipse(this.coordinates.x, this.coordinates.y, this.radius*2, this.radius*2);
}
}
function draw() {
[...]
circles.forEach(circle => {
circle.render();
});
}
Since the algorithm that places the circle to the shape nearest to it has not been applied yet, the circles are positioned randomly on the canvas.
Finding the Closest Circle
The Euclidean Distance is used to find the closest circle. The distance between the points of the circle newC
and
the other circle otherC
is calculated using p5.Vector.dist()
. The circle with the lowest distance is the
closest circle. The following code is added before adding the new circle to the array.
function addCircle() {
[...]
let closestDistance;
let closestIndex;
for (let i = 0; i < circles.length; i++) {
let otherC = circles[i];
// Calculate Euclidean Distance between two points
let distance = newC.coordinates.dist(otherC.coordinates);
if (closestDistance == undefined || distance < closestDistance) {
closestIndex = i;
closestDistance = distance;
}
}
}
After looping through the circles
array, the dock()
method is called on newC
to update its
x and y coordinates, placing it to the closest circle.
class Circle {
[...]
dock(_other) {
// Get distances between the coordinates of this circle and the other circle
let distanceVect = p5.Vector.sub(this.coordinates, _other.coordinates);
// Get angle of rotation for this vector
let angle = distanceVect.heading();
let moveDistance = distanceVect.mag() - this.radius - _other.radius;
// Update x and y coordinates of this circle
this.coordinates.x = this.coordinates.x - cos(angle) * moveDistance;
this.coordinates.y = this.coordinates.y - sin(angle) * moveDistance;
}
}
function addCircle() {
[...]
newC.dock(circles[closestIndex]);
circles.push(newC);
}
The circle that is created each time draw()
runs is now placed next to the
circle that is closest to it.