78 lines
1.8 KiB
Rust
78 lines
1.8 KiB
Rust
|
|
use crate::body::Body;
|
||
|
|
|
||
|
|
const G: f64 = 6.67430e-11;
|
||
|
|
|
||
|
|
pub struct Simulator {
|
||
|
|
pub bodies: Vec<Body>,
|
||
|
|
pub time: f64,
|
||
|
|
pub timestep: f64,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn distance_squared(a: [f64; 2], b: [f64; 2]) -> f64 {
|
||
|
|
let dx = a[0] - b[0];
|
||
|
|
let dy = a[1] - b[1];
|
||
|
|
dx * dx + dy * dy
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Simulator {
|
||
|
|
pub fn new(timestep: f64) -> Self {
|
||
|
|
Self {
|
||
|
|
bodies: Vec::new(),
|
||
|
|
time: 0.0,
|
||
|
|
timestep,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn add_body(&mut self, body: Body) {
|
||
|
|
self.bodies.push(body);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn step(&mut self) {
|
||
|
|
let n = self.bodies.len();
|
||
|
|
let dt = self.timestep;
|
||
|
|
|
||
|
|
let mut accelerations = vec![[0.0, 0.0]; n];
|
||
|
|
|
||
|
|
for i in 0..n {
|
||
|
|
for j in 0..n {
|
||
|
|
if i == j {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
let (bi, bj) = (&self.bodies[i], &self.bodies[j]);
|
||
|
|
|
||
|
|
let dx = bj.position[0] - bi.position[0];
|
||
|
|
let dy = bj.position[1] - bi.position[1];
|
||
|
|
let dist_sq = distance_squared(bi.position, bj.position);
|
||
|
|
let dist = dist_sq.sqrt();
|
||
|
|
|
||
|
|
if dist < 1e-3 {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
let force = G * bi.mass * bj.mass / dist_sq;
|
||
|
|
let accel = force / bi.mass;
|
||
|
|
|
||
|
|
let ax = accel * dx / dist;
|
||
|
|
let ay = accel * dy / dist;
|
||
|
|
|
||
|
|
accelerations[i][0] += ax;
|
||
|
|
accelerations[i][1] += ay;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for i in 0..n {
|
||
|
|
let a = accelerations[i];
|
||
|
|
let body = &mut self.bodies[i];
|
||
|
|
|
||
|
|
body.velocity[0] += a[0] * dt;
|
||
|
|
body.velocity[1] += a[1] * dt;
|
||
|
|
|
||
|
|
body.position[0] += body.velocity[0] * dt;
|
||
|
|
body.position[1] += body.velocity[1] * dt;
|
||
|
|
}
|
||
|
|
|
||
|
|
self.time += dt;
|
||
|
|
}
|
||
|
|
}
|