use crate::{BodyId, CelestialBody, Vec3};
use sciforge::hub::domain::common::constants::G;
#[derive(Clone, Debug)]
pub struct State3D {
pub id: BodyId,
pub position: Vec3,
}
#[derive(Clone, Debug)]
pub struct State5D {
pub id: BodyId,
pub position: Vec3,
pub speed: f64,
pub mass: f64,
}
#[derive(Clone, Debug)]
pub struct State6D {
pub id: BodyId,
pub position: Vec3,
pub velocity: Vec3,
}
#[derive(Clone, Debug)]
pub struct State7D {
pub id: BodyId,
pub position: Vec3,
pub velocity: Vec3,
pub mass: f64,
}
#[derive(Clone, Debug)]
pub struct State8D {
pub id: BodyId,
pub position: Vec3,
pub velocity: Vec3,
pub mass: f64,
pub radius: f64,
}
#[derive(Clone, Debug)]
pub struct FullState {
pub id: BodyId,
pub name: &'static str,
pub position: Vec3,
pub velocity: Vec3,
pub acceleration: Vec3,
pub mass: f64,
pub radius: f64,
pub gravitational_parameter: f64,
pub kinetic_energy: f64,
pub speed: f64,
pub distance_from_origin: f64,
}
pub fn extract_3d(bodies: &[CelestialBody]) -> Vec<State3D> {
bodies
.iter()
.map(|b| State3D {
id: b.id,
position: b.position,
})
.collect()
}
pub fn extract_5d(bodies: &[CelestialBody]) -> Vec<State5D> {
bodies
.iter()
.map(|b| State5D {
id: b.id,
position: b.position,
speed: b.velocity.magnitude(),
mass: b.mass,
})
.collect()
}
pub fn extract_6d(bodies: &[CelestialBody]) -> Vec<State6D> {
bodies
.iter()
.map(|b| State6D {
id: b.id,
position: b.position,
velocity: b.velocity,
})
.collect()
}
pub fn extract_7d(bodies: &[CelestialBody]) -> Vec<State7D> {
bodies
.iter()
.map(|b| State7D {
id: b.id,
position: b.position,
velocity: b.velocity,
mass: b.mass,
})
.collect()
}
pub fn extract_8d(bodies: &[CelestialBody]) -> Vec<State8D> {
bodies
.iter()
.map(|b| State8D {
id: b.id,
position: b.position,
velocity: b.velocity,
mass: b.mass,
radius: b.radius,
})
.collect()
}
pub fn extract_full(bodies: &[CelestialBody]) -> Vec<FullState> {
bodies
.iter()
.map(|b| FullState {
id: b.id,
name: b.name,
position: b.position,
velocity: b.velocity,
acceleration: b.acceleration,
mass: b.mass,
radius: b.radius,
gravitational_parameter: G * b.mass,
kinetic_energy: b.kinetic_energy(),
speed: b.velocity.magnitude(),
distance_from_origin: b.position.magnitude(),
})
.collect()
}
pub fn extract_positions_flat(bodies: &[CelestialBody]) -> Vec<f64> {
let mut out = Vec::with_capacity(bodies.len() * 3);
for b in bodies {
out.push(b.position.x);
out.push(b.position.y);
out.push(b.position.z);
}
out
}
pub fn extract_state_vectors_flat(bodies: &[CelestialBody]) -> Vec<f64> {
let mut out = Vec::with_capacity(bodies.len() * 6);
for b in bodies {
out.push(b.position.x);
out.push(b.position.y);
out.push(b.position.z);
out.push(b.velocity.x);
out.push(b.velocity.y);
out.push(b.velocity.z);
}
out
}
pub fn extract_full_flat(bodies: &[CelestialBody]) -> Vec<f64> {
let mut out = Vec::with_capacity(bodies.len() * 8);
for b in bodies {
out.push(b.position.x);
out.push(b.position.y);
out.push(b.position.z);
out.push(b.velocity.x);
out.push(b.velocity.y);
out.push(b.velocity.z);
out.push(b.mass);
out.push(b.radius);
}
out
}
pub fn extract_by_id(bodies: &[CelestialBody], id: BodyId) -> Option<FullState> {
bodies.iter().find(|b| b.id == id).map(|b| FullState {
id: b.id,
name: b.name,
position: b.position,
velocity: b.velocity,
acceleration: b.acceleration,
mass: b.mass,
radius: b.radius,
gravitational_parameter: G * b.mass,
kinetic_energy: b.kinetic_energy(),
speed: b.velocity.magnitude(),
distance_from_origin: b.position.magnitude(),
})
}
pub fn extract_trajectory(
snapshots: &[(f64, Vec<CelestialBody>)],
id: BodyId,
) -> Vec<(f64, Vec3, Vec3)> {
snapshots
.iter()
.filter_map(|(t, bodies)| {
bodies
.iter()
.find(|b| b.id == id)
.map(|b| (*t, b.position, b.velocity))
})
.collect()
}
pub fn extract_pairwise_distances(bodies: &[CelestialBody]) -> Vec<(BodyId, BodyId, f64)> {
let mut pairs = Vec::new();
for i in 0..bodies.len() {
for j in (i + 1)..bodies.len() {
pairs.push((
bodies[i].id,
bodies[j].id,
bodies[i].position.distance(&bodies[j].position),
));
}
}
pairs
}
pub fn relative_state(
bodies: &[CelestialBody],
target: BodyId,
reference: BodyId,
) -> Option<State6D> {
let t = bodies.iter().find(|b| b.id == target)?;
let r = bodies.iter().find(|b| b.id == reference)?;
Some(State6D {
id: target,
position: t.position - r.position,
velocity: t.velocity - r.velocity,
})
}