constraints_ForceDistanceConstraint.js
const Constraint = require("./Constraint");
const Particle = require("../core/Particle");
const Vector2D = require("../utils/Vector2D");
/**
* `ForceDistanceConstraint` is a `Constraint` that constrains the distance between two particles.
* It uses a force-based implementation and can be thought of as a spring between two particles.
* In general, energy conservation is better at lower stiffness, and it can behave unstable or
* energetically inconsistent at higher stiffness.
* @extends {Constraint}
*/
class ForceDistanceConstraint extends Constraint {
/**
* Instantiates new `ForceDistanceConstraint`
* @param {Particle} c1 - particle 1
* @param {Particle} c2 - particle 2
* @param {Number} len - constrained length
* @param {Number} stiffness - the "spring constant", higher values are more stiff
* @param {Number} breakForce - force at which the constraint breaks
* @param {Number} dampening - damping force on constraint, must be greater than 0
* @constructor
*/
constructor(c1, c2, len, stiffness, breakForce = Infinity, dampening = 0) {
super();
if (c1 === null || c2 === null) {
throw new Error("One of the particles is null!");
}
this.c1 = c1;
this.c2 = c2;
this.breakForce = breakForce;
this.dampening = dampening;
this.stiffness = stiffness;
this.len = len;
}
/**
* @override
* @param {Number} timeStep
*/
update(timeStep) {
let dp = this.c1.pos.sub(this.c2.pos);
let dpMag = dp.mag();
dp.multTo(1 / dpMag);
let dxMag = dpMag - this.len;
let dv = this.c1.vel.sub(this.c2.vel);
let damp = this.dampening * dv.dot(dp);
this.force = dp.mult(-this.stiffness * dxMag - damp);
const a1 = this.force.mult(1 / this.c1.mass);
const a2 = this.force.mult(-1 / this.c2.mass);
a1.multTo(timeStep * timeStep);
a2.multTo(timeStep * timeStep);
//this.c1.pos = this.c1.pos.add(x1);
this.c1.pos.addTo(a1);
//this.c1.vel = this.c1.vel.add(a1.mult(timeStep));
//this.c2.pos = this.c2.pos.add(x2);
this.c2.pos.addTo(a2);
//this.c2.vel = this.c2.vel.add(a2.mult(timeStep));
}
/**
* @override
* @returns {Vector2D[]}
*/
vertices() {
return [this.c1.pos, this.c2.pos];
}
/**
* @override
* @returns {Particle[]}
*/
particles() {
return [this.c1, this.c2];
}
/**
* @override
* @param {Number} timeStep
*/
applyCorrection(timeStep) {
return;
}
}
module.exports = ForceDistanceConstraint;