use glam::DVec3;
use astrodyn::atmosphere::{run_atmosphere_stage, AtmosphereBodyInputs};
use astrodyn::gravity::{run_gravity_stage, GravityBodyInputs};
use astrodyn::IntegOrigin;
use astrodyn::SelfPlanet;
use super::super::Simulation;
impl Simulation {
pub(super) fn update_environment(&mut self, body_integ_origins: &[IntegOrigin]) {
let gravity_data = &self.gravity_data;
let source_frame_ids = &self.source_frame_ids;
let frame_tree = &self.frame_tree;
let root_fid = self.root_frame_id;
let resolve_source =
|_body_idx: usize, source_id: usize| -> Option<astrodyn::ResolvedSource<'_>> {
let grav = gravity_data.get(source_id)?;
let sfids = &source_frame_ids[source_id];
let src_node = frame_tree.get(sfids.inertial);
let position = if sfids.inertial == root_fid {
DVec3::ZERO
} else {
src_node.state.trans.position
};
let rotation = sfids
.pfix
.map(|pfix_id| &frame_tree.get(pfix_id).state.rot.t_parent_this);
Some(astrodyn::ResolvedSource {
source: &grav.source,
rotation,
position,
delta_c20: grav.delta_c20,
has_delta_coeffs: grav.tidal_config.is_some(),
})
};
let resolve_rel_source =
|_body_idx: usize, source_id: usize| -> Option<astrodyn::ResolvedRelativisticSource> {
let grav = gravity_data.get(source_id)?;
let sfids = &source_frame_ids[source_id];
let position = if sfids.inertial == root_fid {
DVec3::ZERO
} else {
frame_tree.get(sfids.inertial).state.trans.position
};
Some(astrodyn::ResolvedRelativisticSource {
mu: grav.source.mu,
position,
velocity: grav.velocity,
})
};
let body_iter = self.bodies.iter_mut().enumerate().map(|(body_idx, body)| {
let inputs = GravityBodyInputs {
position: body.trans.position,
velocity: body.trans.velocity,
integ_origin: body_integ_origins[body_idx],
controls: &body.gravity_controls,
};
let gravity_accel_slot = &mut body.gravity_accel;
let store =
move |result: astrodyn::GravityAccelerationTyped<astrodyn::RootInertial>| {
*gravity_accel_slot = result;
};
(body_idx, inputs, store)
});
run_gravity_stage(body_iter, resolve_source, resolve_rel_source);
if let Some(ref atmos_config) = self.atmosphere {
let t_pfix = self
.atmosphere_planet_source
.and_then(|idx| self.source_frame_ids.get(idx))
.and_then(|sfids| sfids.pfix)
.map(|pfix_id| &self.frame_tree.get(pfix_id).state.rot.t_parent_this);
let tai_tjt = Some(self.time.tai_tjt);
let body_iter =
self.bodies
.iter_mut()
.enumerate()
.filter(|(_, body)| body.drag.is_some())
.map(|(body_idx, body)| {
let inputs = AtmosphereBodyInputs {
position: astrodyn::Position::<astrodyn::PlanetInertial<SelfPlanet>>::from_raw_si(body.trans.position.raw_si()), };
let slot = &mut body.atmospheric_state;
let store = move |result: astrodyn::AtmosphereState<SelfPlanet>| {
*slot = result;
};
(body_idx, inputs, store)
});
run_atmosphere_stage::<SelfPlanet, _, _, _>(body_iter, atmos_config, t_pfix, tai_tjt);
}
}
}