extern crate toml;
use super::serde_derive::Deserialize;
use crate::celestia::Frame;
use std::collections::HashMap;
#[derive(Clone, Deserialize)]
pub struct FramesSerde {
pub frames: HashMap<String, FrameSerde>,
}
#[derive(Clone, Deserialize)]
pub struct FrameSerde {
orientation: i32,
center: i32,
pub base: Option<String>,
gm: f64,
parent_orientation: Option<i32>,
parent_center: Option<i32>,
flattening: f64,
equatorial_radius: f64,
semi_major_radius: f64,
pub rotation: RotationToml,
}
impl FrameSerde {
pub fn to_frame(&self) -> Frame {
Frame::Geoid {
axb_id: self.orientation,
exb_id: self.center,
gm: self.gm,
parent_axb_id: self.parent_orientation,
parent_exb_id: self.parent_center,
flattening: self.flattening,
equatorial_radius: self.equatorial_radius,
semi_major_radius: self.semi_major_radius,
}
}
pub fn update_from(&mut self, src: &Frame) {
if self.gm < 0.0 {
self.gm = src.gm();
}
if self.flattening < 0.0 {
self.flattening = src.flattening();
}
if self.equatorial_radius < 0.0 {
self.equatorial_radius = src.equatorial_radius();
}
if self.semi_major_radius < 0.0 {
self.semi_major_radius = src.semi_major_radius();
}
if let Some(p_axb) = self.parent_orientation {
if p_axb == -1 {
self.parent_orientation = src.parent_axb_id();
}
}
if let Some(p_exb) = self.parent_center {
if p_exb == -1 {
self.parent_center = src.parent_exb_id();
}
}
}
pub fn as_frame(&self) -> Frame {
Frame::Geoid {
axb_id: self.orientation,
exb_id: self.center,
gm: self.gm,
parent_axb_id: self.parent_orientation,
parent_exb_id: self.parent_center,
flattening: self.flattening,
equatorial_radius: self.equatorial_radius,
semi_major_radius: self.semi_major_radius,
}
}
}
#[derive(Clone, Deserialize)]
pub struct RotationToml {
pub right_asc: String,
pub declin: String,
pub w: String,
pub angle_unit: Option<String>,
pub context: Option<HashMap<String, String>>,
}
#[test]
fn test_deser_frame_toml() {
let frames: FramesSerde = toml::from_str(
r#"
[frames.iau_sun]
orientation = 10
center = 10
gm = 132712440041.93938
parent_orientation = 0
parent_center = 0
flattening = 0
equatorial_radius = 696342.0
semi_major_radius = 696342.0
[frames.iau_sun.rotation]
right_asc = "289.13"
declin = "63.87"
w = "84.176 + 14.18440000*d"
angle_unit = "degrees"
[frames.iau_sun.rotation.context]
t_prime = "1.0" # Must be encasted in quote even if just a floating point value
[frames.iau_sun2]
orientation = 10
center = 10
base = "Sun J2000"
gm = -1
parent_orientation = -1
parent_center = -1
flattening = -1
equatorial_radius = -1
semi_major_radius = -1
[frames.iau_sun2.rotation]
right_asc = "289.13"
declin = "63.87"
w = "84.176 + 14.18440000*d"
angle_unit = "degrees"
"#,
)
.unwrap();
let iau_sun = &frames.frames["iau_sun"];
assert_eq!(iau_sun.orientation, 10);
assert_eq!(iau_sun.center, 10);
assert!((iau_sun.gm - 132_712_440_041.939_38).abs() < std::f64::EPSILON);
assert_eq!(iau_sun.parent_orientation.unwrap(), 0);
assert_eq!(iau_sun.parent_center.unwrap(), 0);
assert!((iau_sun.equatorial_radius - 696_342.0).abs() < std::f64::EPSILON);
assert!((iau_sun.semi_major_radius - 696_342.0).abs() < std::f64::EPSILON);
let iau_sun_rot = &iau_sun.rotation;
assert_eq!(iau_sun_rot.right_asc, "289.13");
assert_eq!(iau_sun_rot.declin, "63.87");
assert_eq!(iau_sun_rot.w, "84.176 + 14.18440000*d");
assert_eq!(iau_sun_rot.angle_unit.as_ref().unwrap(), "degrees");
let iau_sun = &frames.frames["iau_sun2"];
assert_eq!(iau_sun.orientation, 10);
assert_eq!(iau_sun.center, 10);
assert_eq!(iau_sun.base.as_ref().unwrap(), "Sun J2000");
assert!((iau_sun.gm - -1.0).abs() < std::f64::EPSILON);
assert_eq!(iau_sun.parent_orientation.unwrap(), -1);
assert_eq!(iau_sun.parent_center.unwrap(), -1);
assert!((iau_sun.equatorial_radius - -1.0).abs() < std::f64::EPSILON);
assert!((iau_sun.semi_major_radius - -1.0).abs() < std::f64::EPSILON);
let iau_sun_rot = &iau_sun.rotation;
assert_eq!(iau_sun_rot.right_asc, "289.13");
assert_eq!(iau_sun_rot.declin, "63.87");
assert_eq!(iau_sun_rot.w, "84.176 + 14.18440000*d");
assert_eq!(iau_sun_rot.angle_unit.as_ref().unwrap(), "degrees");
}