xxxxxxxxxx
const nodeArray = [];
const nodeAmount = 320;
const friction = 0.9;
const forceMultiplier = 0.01;
const types = [
{
colour: "red",
gravity: { x: 0, y: 0 },
},
{
colour: "blue",
gravity: { x: 0, y: 0.25 },
},
];
function setup() {
createCanvas(640, 640);
while (nodeArray.length < nodeAmount) {
nodeArray.push(node());
}
}
function draw() {
background("white");
nodeArray.forEach((node) => {
node.update();
node.handleEdge();
});
gabrielGraph();
nodeArray.forEach((node) => node.show());
}
function node() {
const pos = createVector(random(width), random(height));
const vel = createVector(0, 0);
const acc = createVector(0, 0);
const type = random(types);
const handleEdge = () => {
if (pos.x < 0) {
pos.x = width;
pos.y = random(height);
} else if (pos.x > width) {
pos.x = 0;
pos.y = random(height);
}
if (pos.y < 0) {
pos.y = height;
pos.x = random(width);
} else if (pos.y > height) {
pos.y = 0;
pos.x = random(width);
}
};
const update = () => {
vel.add(acc);
vel.limit(3);
pos.add(vel);
vel.mult(friction);
acc.set(type.gravity.x, type.gravity.y);
};
const show = () => {
noStroke();
fill(type.colour);
ellipse(pos.x, pos.y, 6);
};
return {
pos,
acc,
type,
handleEdge,
update,
show,
};
}
const gabrielGraph = () => {
stroke("black");
nodeArray.forEach((current, i) => {
const rest = nodeArray.slice(i + 1);
rest.forEach((target) => {
const centre = current.pos.copy().add(target.pos).div(2);
const difference = current.pos.copy().sub(target.pos);
const distance = Math.hypot(difference.x, difference.y);
const sqRadius = (distance / 2) ** 2;
if (
nodeArray.some(
(extra) =>
extra !== current &&
extra !== target &&
sqRadius >
(extra.pos.x - centre.x) ** 2 + (extra.pos.y - centre.y) ** 2
)
) {
return;
}
const areTypesEqual = current.type === target.type;
areTypesEqual && line(current.pos.x, current.pos.y, target.pos.x, target.pos.y);
const threshold = areTypesEqual ? 20 : 40;
difference.mult(forceMultiplier).mult(distance < threshold ? -1 : 1);
current.acc.sub(difference);
target.acc.add(difference);
});
});
};