nyx_space/cosmic/
eclipse.rs1use anise::almanac::Almanac;
20use anise::analysis::prelude::Event;
21use anise::astro::Occultation;
22use anise::constants::frames::{EARTH_J2000, MOON_J2000, SUN_J2000};
23use anise::errors::AlmanacResult;
24use serde::{Deserialize, Serialize};
25use serde_dhall::StaticType;
26
27pub use super::{Frame, Orbit, Spacecraft};
28use std::fmt;
29use std::sync::Arc;
30
31#[derive(Clone, Debug, Serialize, Deserialize, StaticType)]
32pub struct ShadowModel {
33 pub light_source: Frame,
34 pub shadow_bodies: Vec<Frame>,
35}
36
37impl fmt::Display for ShadowModel {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 let shadow_bodies: Vec<String> = self
40 .shadow_bodies
41 .iter()
42 .map(|b| format!("{b:x}"))
43 .collect();
44 write!(
45 f,
46 "light-source: {:x}, shadows casted by: {}",
47 self.light_source,
48 shadow_bodies.join(", ")
49 )
50 }
51}
52
53impl ShadowModel {
54 pub fn cislunar(almanac: Arc<Almanac>) -> Self {
57 let eme2k = almanac.frame_info(EARTH_J2000).unwrap();
58 let moon_j2k = almanac.frame_info(MOON_J2000).unwrap();
59 Self {
60 light_source: almanac.frame_info(SUN_J2000).unwrap(),
61 shadow_bodies: vec![eme2k, moon_j2k],
62 }
63 }
64
65 pub fn compute(&self, observer: Orbit, almanac: Arc<Almanac>) -> AlmanacResult<Occultation> {
67 let mut state = Occultation {
68 epoch: observer.epoch,
69 back_frame: SUN_J2000,
70 front_frame: observer.frame,
71 percentage: 0.0,
72 };
73 for eclipsing_body in &self.shadow_bodies {
74 let this_state = almanac.solar_eclipsing(*eclipsing_body, observer, None)?;
75 if this_state.percentage > state.percentage {
76 state = this_state;
77 }
78 }
79 Ok(state)
80 }
81
82 pub fn to_umbra_events(&self) -> Vec<Event> {
85 self.shadow_bodies
86 .iter()
87 .copied()
88 .map(Event::total_eclipse)
89 .collect()
90 }
91
92 pub fn to_penumbra_events(&self) -> Vec<Event> {
95 self.shadow_bodies
96 .iter()
97 .copied()
98 .map(Event::eclipse)
99 .collect()
100 }
101}