walls_RectangularWorldBoundary.js
const Wall = require("./Wall");
/**
* `RectangularWorldBoundary` is a rectangular bounding box that constrains all particles *within* the boundaries.
* The implementation uses a strict uni-directional constraint, and particles cannot escape the world boundaries.
* Since the boundary is strict, the current implementation checks **all** particles contained in the boundaries, not
* just particles surrounding the edge.
* @extends {Wall}
*/
class RectangularWorldBoundary extends Wall {
/**
* @param {Number} minW left x position (smaller value)
* @param {Number} maxW right x position (larger value)
* @param {Number} minH top y position (smaller value)
* @param {Number} maxH bottom y position (larger value)
* @constructor
*/
constructor(minW, maxW, minH, maxH) {
super();
this.minW = minW;
this.maxW = maxW;
this.minH = minH;
this.maxH = maxH;
}
/**
* @override
* @param {Particle[]} particles
* @param {Number} timeStep
*/
resolveCollisions(particles, timeStep) {
for (let particle of particles) {
const posX = particle.pos.x;
const posY = particle.pos.y;
const radius = particle.radius;
const bounce = particle.bounciness;
const velX = particle.vel.x;
const velY = particle.vel.y;
if (posX > this.maxW - radius) {
particle.vel.x = velX * -1 * bounce;
particle.pos.x = posX + 2 * velX * -1 * bounce * timeStep;
}
if (posX < this.minW + radius) {
particle.vel.x = velX * -1 * bounce;
particle.pos.x = posX + 2 * velX * -1 * bounce * timeStep;
}
if (posY > this.maxH - radius) {
particle.vel.y = velY * -1 * bounce;
particle.pos.y = posY + 2 * velY * -1 * bounce * timeStep;
}
if (posY < this.minH + radius) {
particle.vel.y = velY * -1 * bounce;
particle.pos.y = posY + 2 * velY * -1 * bounce * timeStep;
}
}
}
/**
* @override
* @param {Particle[]} particles
*/
applyCorrection(particles) {
for (let particle of particles) {
const radius = particle.radius;
if (particle.pos.x > this.maxW - radius) {
particle.pos.x = this.maxW - radius;
}
if (particle.pos.x < this.minW + radius) {
particle.pos.x = this.minW + radius;
}
if (particle.pos.y > this.maxH - radius) {
particle.pos.y = this.maxH - radius;
}
if (particle.pos.y < this.minH + radius) {
particle.pos.y = this.minH + radius;
}
}
}
/**
* Checks if a Particle is colliding with the Wall
* @param {Particle} particle
* @returns {Boolean} true if particle is colliding with wall
* @public
*/
isCollide(particle) {
const posX = particle.pos.x;
const posY = particle.pos.y;
const radius = particle.radius;
return (posX >= this.maxW - radius) || (posX <= this.minW + radius) ||
(posY >= this.maxH - radius) || (posY <= this.minH + radius) ||
(particle.pos.x >= this.maxW - radius) || (particle.pos.x <= this.minW + radius) ||
(particle.pos.y >= this.maxH - radius) || (particle.pos.y <= this.minH + radius)
}
/**
* @override
* @returns {Number[]}
*/
getHashPos() {
return [(this.maxW + this.minW) / 2, (this.maxH + this.minH) / 2];
}
/**
* @override
* @returns {Number[]}
*/
getHashDimensions() {
return [this.maxW - this.minW + 1, this.maxH - this.minH + 1];
}
/**
* @override
* @returns {Vector2D[]}
*/
vertices() {
return [];
}
}
module.exports = RectangularWorldBoundary;