diff --git a/Readme.md b/Readme.md index 40ba8ab..751e1e8 100644 --- a/Readme.md +++ b/Readme.md @@ -8,11 +8,11 @@ Uses `npm` for `eslint`. Screenshots ----------- -![A binary pair orbiting a larger partner](./gravity-simulator-4.png "Gravity Simulator Screenshot 4") +![A binary pair orbiting a larger partner](./screenshots/gravity-simulator-4.png "Gravity Simulator Screenshot 4") -![A greater mass attracts others which had been on escape trajectories](./gravity-simulator-5.png "Gravity Simulator Screenshot 5") +![A greater mass attracts others which had been on escape trajectories](./screenshots/gravity-simulator-5.png "Gravity Simulator Screenshot 5") -![A small object orbits a more massive binary pair](./gravity-simulator-6.png "Gravity Simulator Screenshot 6") +![A small object orbits a more massive binary pair](./screenshots/gravity-simulator-6.png "Gravity Simulator Screenshot 6") TODO diff --git a/gravity-simulator-5.png b/gravity-simulator-5.png deleted file mode 100644 index f69c4d6..0000000 Binary files a/gravity-simulator-5.png and /dev/null differ diff --git a/panning.js b/panning.js index 6f7dbb2..31227bf 100644 --- a/panning.js +++ b/panning.js @@ -69,8 +69,6 @@ export class Panning { // Additional scaling factor velocity = mult(velocity, this.sim.getOption('display.panningSpeed')); - // TODO: Make it easier to slow down the camera - // Add pointer velocity to current panning velocity this.velocity = add(this.velocity, velocity); } @@ -82,10 +80,6 @@ export class Panning { this.velocity = zero; } this.touchStart = undefined; - - if (this.sim.getOption('compensate.fastPanning')) { - this.velocity = zero; - } } } diff --git a/gravity-simulator-2.png b/screenshots/gravity-simulator-2.png similarity index 100% rename from gravity-simulator-2.png rename to screenshots/gravity-simulator-2.png diff --git a/gravity-simulator-3.png b/screenshots/gravity-simulator-3.png similarity index 100% rename from gravity-simulator-3.png rename to screenshots/gravity-simulator-3.png diff --git a/gravity-simulator-4.png b/screenshots/gravity-simulator-4.png similarity index 100% rename from gravity-simulator-4.png rename to screenshots/gravity-simulator-4.png diff --git a/screenshots/gravity-simulator-5.png b/screenshots/gravity-simulator-5.png new file mode 100644 index 0000000..fbe3e35 Binary files /dev/null and b/screenshots/gravity-simulator-5.png differ diff --git a/gravity-simulator-6.png b/screenshots/gravity-simulator-6.png similarity index 100% rename from gravity-simulator-6.png rename to screenshots/gravity-simulator-6.png diff --git a/sim-options.js b/sim-options.js index c79a310..27f2ddc 100644 --- a/sim-options.js +++ b/sim-options.js @@ -10,18 +10,19 @@ export const simOptions = { traces: ['Path Traces', 'boolean', true], dashedTraces: ['Dashed', 'boolean', false, {tall: true, showIf: 'display.traces'}], velocityScale: ['Velocity
Vec Scale', 'number', 80, {showIf: 'display.velocity'}], - accelerationScale: ['Accel
Vec Scale', 'number', 800, {showIf: 'display.acceleration'}], + accelerationScale: ['Accel
Vec Scale', 'number', 80, {showIf: 'display.acceleration'}], zoomVectors: ['Zoom Vectors', 'boolean', true], panningSpeed: ['Pan
Speed', 'number', 0.1], }, compensate: { timeScale: ['Time Scale Compensator', 'boolean', false, {wide: true}], - fastPanning: ['Fast Panning', 'boolean', false], }, param: { gravity: ['Gravity', 'number', 1], timeScale: ['Time Scale', 'number', 0.1], massCreationRate: ['Mass Creation Rate', 'number', 1], + elasticity: ['Elasticity', 'number', 0.7, {min: 0, max: 1}], + mergeThreshold: ['Merge Threshold', 'number', 0.1, {min: 0, max: 1}], }, debug: { objectsInfo: ['Objects Info', 'boolean', false], diff --git a/system.js b/system.js index d4ddb49..995b8eb 100644 --- a/system.js +++ b/system.js @@ -400,10 +400,13 @@ export class System { bounceObjects(i, j) { const A = this.object(i); const B = this.object(j); + const totalMass = A.mass + B.mass; // TODO: Handle scenario where an object overlaps more than one other object - // const elasticity = 1; + const autoMerge = true; + + const Z = this.sim.getOption('param.elasticity'); // Elasticity: 0 = inelastic, 1 = elastic const r = sub(A.position, B.position); const normal = div(r, magnitude(r)); const tangent = {x: -normal.y, y: normal.x}; @@ -421,21 +424,30 @@ export class System { // Are these objects sticking together? // One way to determine this is, // does either object have enough KE to escape their gravitational potential? - // const vRel = sub(A.velocity, B.velocity); - // const G = this.sim.getOption('param.gravity'); - // if (square(vRel) < 0.1 * G * (A.mass + B.mass) / magnitude(r)) { - // // Neither object looks like it can escape! - // this.mergeObjects(i, j); - // return; - // } + if (autoMerge) { + // const vSquared = Math.abs(vAn - vBn) ** 2; + const vSquared = square(sub(A.velocity, B.velocity)); + const G = this.sim.getOption('param.gravity'); + const mergeThreshold = this.sim.getOption('param.mergeThreshold'); + if (vSquared < mergeThreshold * G * totalMass / magnitude(r)) { + // Neither object looks like it can escape! + this.mergeObjects(i, j); + return; + } + } + + // Calculate the collision + const Zscaled = Math.sqrt(Z); + const vAnNew = (vAn * (A.mass - Zscaled * B.mass) + vBn * (1 + Zscaled) * B.mass) / totalMass; - // Continue with rebound calculations - const vAnNew = (vAn * (A.mass - B.mass) + vBn * 2 * B.mass) / (A.mass + B.mass); const vA = add(mult(tangent, vAt), mult(normal, vAnNew)); - const vB = div(add(mult(A.velocity, A.mass), mult(B.velocity, B.mass), mult(vA, -1 * A.mass)), B.mass); + const vB = div(add(mult(A.velocity, A.mass), mult(B.velocity, B.mass), mult(vA, -A.mass)), B.mass); + // const Ki = A.kineticEnergy + B.kineticEnergy; A.velocity = vA; B.velocity = vB; + // const Kf = A.kineticEnergy + B.kineticEnergy; + // console.log('Collision: Zscaled', Zscaled, 'Energy before', Ki, 'Energy after', Kf, 'Fraction change', (Kf - Ki) / Ki); } mergeObjects(i, j) { diff --git a/tool/options.js b/tool/options.js index 83ac97f..86cf065 100644 --- a/tool/options.js +++ b/tool/options.js @@ -126,6 +126,13 @@ export class OptionsTool extends Tool { input.addEventListener('change', () => { this.sim.setOption(path, input.value); + // Enforce min/max if provided + if (item.max !== undefined && this.sim.getOption(path) > item.max) { + this.sim.setOption(path, item.max); + } + if (item.min !== undefined && this.sim.getOption(path) < item.min) { + this.sim.setOption(path, item.min); + } }); this.sim.onOptionSet(path, ({value}) => {