class Node {
constructor(x, y, mF, mS, dS, sCR) {
this.prePosition = new Vector(x, y);
this.position = new Vector(x, y);
this.velocity = new Vector(0, 0);
this.velocity.random2d();
this.acceleration = new Vector(0, 0);
this.maxForce = mF;
this.maxSpeed = mS;
this.desiredSeparation = dS;
this.separationCohesionRation = sCR;
}
run(nodes, generation) {
this.prePosition = this.position.clone();
this.differentiate(nodes);
this.update();
}
applyForce(force) {
this.acceleration.add(force);
}
differentiate(nodes) {
let separation = this.separate(nodes);
let cohesion = this.edgeCohesion(nodes);
separation.mult(this.separationCohesionRation);
this.applyForce(separation);
this.applyForce(cohesion);
}
update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
seek(target) {
let desired = target.sub(this.position);
desired = desired.setMag(this.maxSpeed);
let steer = desired.sub(this.velocity);
steer = steer.limit(this.maxForce);
return steer;
}
separate(nodes) {
let steer = new Vector(0, 0);
let count = 0;
for (let other of nodes) {
let d = this.position.dist(other.position);
if (d > 0 && d < this.desiredSeparation) {
let diff = this.position.clone().sub(other.position);
diff.normalize();
diff.divide(d);
steer.add(diff);
count++;
}
}
if (count > 0) {
steer.divide(count);
}
if (steer.magnitude() > 0) {
steer.setMag(this.maxSpeed);
steer.sub(this.velocity);
steer.limit(this.maxForce);
}
return steer;
}
edgeCohesion(nodes) {
let sum = new Vector(0, 0);
let this_index = nodes.indexOf(this);
if (this_index != 0 && this_index != nodes.length - 1) {
sum = sum.add(nodes[this_index - 1].position);
sum = sum.add(nodes[this_index + 1].position);
} else if (this_index == 0) {
sum = sum.add(nodes[nodes.length - 1].position);
sum = sum.add(nodes[this_index + 1].position);
} else if (this_index == nodes.length - 1) {
sum = sum.add(nodes[this_index - 1].position);
sum = sum.add(nodes[0].position);
}
sum = sum.divide(2);
return this.seek(sum);
}
}