function move_particles(particles, force_constant) { for (let particle of particles) { particle.acceleration.setMag(0); } for (let i = 0; i < particles.length; i += 1) { for (let j = 0; j < i; j += 1) { const displacement = p5.Vector.sub( particles[i].position, particles[j].position, ); const force_mag = ( particles[i].charge * particles[j].charge / displacement.magSq() * force_constant ); // XXX possible extension: divide by charge's mass const ai_mag = force_mag; const aj_mag = force_mag; let ai; let aj; if (force_mag === Infinity) { ai = p5.Vector.random3D(); aj = p5.Vector.random3D(); } else { ai = displacement.copy().normalize(); aj = ai.copy().mult(-1); ai.mult(ai_mag); aj.mult(aj_mag); } project_onto_plane(ai, particles[i].position); project_onto_plane(aj, particles[j].position); particles[i].acceleration.add(ai); particles[j].acceleration.add(aj); } } for (let particle of particles) { particle.velocity = particle.velocity.add(particle.acceleration); particle.position = particle.position.add(particle.velocity); particle.position.normalize(); } } function project_onto_unit_vector(v, unit_vector) { let size = p5.Vector.dot(v, unit_vector); return p5.Vector.mult(unit_vector, size); } /// Project `v` onto the plane normal to `unit_vector` /// Mutates `v` function project_onto_plane(v, unit_vector) { let v_proj = project_onto_unit_vector(v, unit_vector); v.sub(v_proj) }