use crate::coordinate::CoordinateState;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum PhaseFunction {
HG = 0,
HG1G2 = 1,
HG12 = 2,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Orbit {
pub orbit_id: Option<String>,
pub object_id: Option<String>,
pub state: CoordinateState,
pub a1: f64,
pub a2: f64,
pub a3: f64,
pub ng_alpha: f64,
pub ng_r0: f64,
pub ng_m: f64,
pub ng_n: f64,
pub ng_k: f64,
pub non_grav_dt: Option<f64>,
pub ng_covariance: Option<[[f64; 3]; 3]>,
pub phot_system: Option<PhaseFunction>,
pub h_mag: f64,
pub slope1: f64,
pub slope2: f64,
}
impl Orbit {
pub fn new(state: CoordinateState) -> Self {
Self {
orbit_id: None,
object_id: None,
state,
a1: 0.0,
a2: 0.0,
a3: 0.0,
ng_alpha: 0.0,
ng_r0: 0.0,
ng_m: 0.0,
ng_n: 0.0,
ng_k: 0.0,
non_grav_dt: None,
ng_covariance: None,
phot_system: None,
h_mag: f64::NAN,
slope1: 0.0,
slope2: 0.0,
}
}
pub fn with_orbit_id(mut self, id: impl Into<String>) -> Self {
self.orbit_id = Some(id.into());
self
}
pub fn with_object_id(mut self, id: impl Into<String>) -> Self {
self.object_id = Some(id.into());
self
}
pub fn with_nongrav(mut self, a1: f64, a2: f64, a3: f64) -> Self {
self.a1 = a1;
self.a2 = a2;
self.a3 = a3;
self
}
pub fn with_g_function(mut self, alpha: f64, r0: f64, m: f64, n: f64, k: f64) -> Self {
self.ng_alpha = alpha;
self.ng_r0 = r0;
self.ng_m = m;
self.ng_n = n;
self.ng_k = k;
self
}
pub fn with_non_grav_dt(mut self, dt: Option<f64>) -> Self {
self.non_grav_dt = dt;
self
}
pub fn with_nongrav_covariance(mut self, covariance: Option<[[f64; 3]; 3]>) -> Self {
self.ng_covariance = covariance;
self
}
pub fn with_photometry(
mut self,
phot_system: PhaseFunction,
h: f64,
slope1: f64,
slope2: f64,
) -> Self {
self.phot_system = Some(phot_system);
self.h_mag = h;
self.slope1 = slope1;
self.slope2 = slope2;
self
}
pub fn with_hg(self, h: f64, g: f64) -> Self {
self.with_photometry(PhaseFunction::HG, h, g, 0.0)
}
pub(crate) fn to_ffi_with_keep(
&self,
) -> crate::error::Result<(empyrean_sys::EmpyreanOrbit, OrbitFfiKeep)> {
use std::ffi::CString;
let (phase_int, h, s1, s2) = match self.phot_system {
Some(pf) => (pf as i32, self.h_mag, self.slope1, self.slope2),
None => (-1, f64::NAN, 0.0, 0.0),
};
let orbit_id_cstr =
CString::new(self.orbit_id.as_deref().unwrap_or("")).unwrap_or_default();
let object_id_cstr =
CString::new(self.object_id.as_deref().unwrap_or("")).unwrap_or_default();
let orbit_id_ptr = orbit_id_cstr.as_ptr();
let object_id_ptr = object_id_cstr.as_ptr();
let ffi = empyrean_sys::EmpyreanOrbit {
state: self.state.to_ffi()?,
orbit_id: orbit_id_ptr,
object_id: object_id_ptr,
a1: self.a1,
a2: self.a2,
a3: self.a3,
ng_alpha: self.ng_alpha,
ng_r0: self.ng_r0,
ng_m: self.ng_m,
ng_n: self.ng_n,
ng_k: self.ng_k,
non_grav_dt: self.non_grav_dt.unwrap_or(f64::NAN),
has_non_grav_covariance: u8::from(self.ng_covariance.is_some()),
non_grav_covariance: self.ng_covariance.unwrap_or([[0.0; 3]; 3]),
phot_system: phase_int,
h_mag: h,
slope1: s1,
slope2: s2,
};
let keep = OrbitFfiKeep {
_orbit_id: orbit_id_cstr,
_object_id: object_id_cstr,
};
Ok((ffi, keep))
}
}
pub(crate) struct OrbitFfiKeep {
_orbit_id: std::ffi::CString,
_object_id: std::ffi::CString,
}