use crate::physics::basic::{AngularMomentum, AngularMomentumType, Coef, Vector3};
use crate::utils::float;
impl Vector3<AngularMomentum> {
pub fn limit_float(&self, threshold: f64, angular_momentum_type: AngularMomentumType) -> Self {
let (x, y, z) = match angular_momentum_type {
AngularMomentumType::KgM2perSecond => (
float::limit_float(self.x.as_kg_m2_per_second(), threshold),
float::limit_float(self.y.as_kg_m2_per_second(), threshold),
float::limit_float(self.z.as_kg_m2_per_second(), threshold),
),
AngularMomentumType::KgKm2perSecond => (
float::limit_float(self.x.as_kg_km2_per_second(), threshold),
float::limit_float(self.y.as_kg_km2_per_second(), threshold),
float::limit_float(self.z.as_kg_km2_per_second(), threshold),
),
AngularMomentumType::Nms => (
float::limit_float(self.x.as_nms(), threshold),
float::limit_float(self.y.as_nms(), threshold),
float::limit_float(self.z.as_nms(), threshold),
),
AngularMomentumType::MillNms => (
float::limit_float(self.x.as_mill_nms(), threshold),
float::limit_float(self.y.as_mill_nms(), threshold),
float::limit_float(self.z.as_mill_nms(), threshold),
),
AngularMomentumType::MicroNms => (
float::limit_float(self.x.as_micro_nms(), threshold),
float::limit_float(self.y.as_micro_nms(), threshold),
float::limit_float(self.z.as_micro_nms(), threshold),
),
AngularMomentumType::NanoNms => (
float::limit_float(self.x.as_nano_nms(), threshold),
float::limit_float(self.y.as_nano_nms(), threshold),
float::limit_float(self.z.as_nano_nms(), threshold),
),
};
Self {
x: AngularMomentum { v: x, default_type: angular_momentum_type },
y: AngularMomentum { v: y, default_type: angular_momentum_type },
z: AngularMomentum { v: z, default_type: angular_momentum_type },
}
}
pub fn to_vector3_coef(&self, angular_momentum_type: AngularMomentumType) -> Vector3<Coef> {
match angular_momentum_type {
AngularMomentumType::KgM2perSecond => {
let (x, y, z) = (self.x.as_kg_m2_per_second(), self.y.as_kg_m2_per_second(), self.z.as_kg_m2_per_second());
Vector3::<Coef>::from_array([x, y, z])
}
AngularMomentumType::KgKm2perSecond => {
let (x, y, z) = (self.x.as_kg_km2_per_second(), self.y.as_kg_km2_per_second(), self.z.as_kg_km2_per_second());
Vector3::<Coef>::from_array([x, y, z])
}
AngularMomentumType::Nms => {
let (x, y, z) = (self.x.as_nms(), self.y.as_nms(), self.z.as_nms());
Vector3::<Coef>::from_array([x, y, z])
}
AngularMomentumType::MillNms => {
let (x, y, z) = (self.x.as_mill_nms(), self.y.as_mill_nms(), self.z.as_mill_nms());
Vector3::<Coef>::from_array([x, y, z])
}
AngularMomentumType::MicroNms => {
let (x, y, z) = (self.x.as_micro_nms(), self.y.as_micro_nms(), self.z.as_micro_nms());
Vector3::<Coef>::from_array([x, y, z])
}
AngularMomentumType::NanoNms => {
let (x, y, z) = (self.x.as_nano_nms(), self.y.as_nano_nms(), self.z.as_nano_nms());
Vector3::<Coef>::from_array([x, y, z])
}
}
}
pub fn from_vector_coef(coef: Vector3<Coef>, angular_momentum_type: AngularMomentumType) -> Vector3<AngularMomentum> {
let x = AngularMomentum {
v: coef.x.v,
default_type: angular_momentum_type,
};
let y = AngularMomentum {
v: coef.y.v,
default_type: angular_momentum_type,
};
let z = AngularMomentum {
v: coef.z.v,
default_type: angular_momentum_type,
};
Vector3::new(x, y, z)
}
pub fn from_array_with_unit(array: [f64; 3], angular_momentum_type: AngularMomentumType) -> Vector3<AngularMomentum> {
let [x, y, z] = array;
let x = AngularMomentum {
v: x,
default_type: angular_momentum_type,
};
let y = AngularMomentum {
v: y,
default_type: angular_momentum_type,
};
let z = AngularMomentum {
v: z,
default_type: angular_momentum_type,
};
Vector3::new(x, y, z)
}
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_relative_eq;
#[test]
fn test_limit_float() {
let v = Vector3::new(
AngularMomentum::from_kg_m2_per_second(1.0),
AngularMomentum::from_kg_m2_per_second(-5.0),
AngularMomentum::from_kg_m2_per_second(3.0),
);
let result = v.limit_float(3.0, AngularMomentumType::KgM2perSecond);
assert_relative_eq!(result.x.as_kg_m2_per_second(), 1.0);
assert_relative_eq!(result.y.as_kg_m2_per_second(), -3.0);
assert_relative_eq!(result.z.as_kg_m2_per_second(), 3.0);
let result = v.limit_float(1e10, AngularMomentumType::KgKm2perSecond);
assert_relative_eq!(result.x.as_kg_km2_per_second(), 0.000001);
assert_relative_eq!(result.y.as_kg_km2_per_second(), -0.000005);
assert_relative_eq!(result.z.as_kg_km2_per_second(), 0.000003);
let result = v.limit_float(1e10, AngularMomentumType::Nms);
assert_relative_eq!(result.x.as_nms(), 1.0);
assert_relative_eq!(result.y.as_nms(), -5.0);
assert_relative_eq!(result.z.as_nms(), 3.0);
let result = v.limit_float(1e10, AngularMomentumType::MillNms);
assert_relative_eq!(result.x.as_mill_nms(), 1000.0);
assert_relative_eq!(result.y.as_mill_nms(), -5000.0);
assert_relative_eq!(result.z.as_mill_nms(), 3000.0);
let result = v.limit_float(1e10, AngularMomentumType::MicroNms);
assert_relative_eq!(result.x.as_micro_nms(), 1000000.0);
assert_relative_eq!(result.y.as_micro_nms(), -5000000.0);
assert_relative_eq!(result.z.as_micro_nms(), 3000000.0);
let result = v.limit_float(1e10, AngularMomentumType::NanoNms);
assert_relative_eq!(result.x.as_nano_nms(), 1000000000.0);
assert_relative_eq!(result.y.as_nano_nms(), -5000000000.0);
assert_relative_eq!(result.z.as_nano_nms(), 3000000000.0);
}
#[test]
fn test_to_vector3_coef_kg_m2_s() {
let angular_momentum_vec = Vector3::new(
AngularMomentum::from_kg_m2_per_second(5.0),
AngularMomentum::from_kg_m2_per_second(10.0),
AngularMomentum::from_kg_m2_per_second(15.0),
);
let coef_vec = angular_momentum_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
assert_relative_eq!(coef_vec.x, 5.0);
assert_relative_eq!(coef_vec.y, 10.0);
assert_relative_eq!(coef_vec.z, 15.0);
}
#[test]
fn test_to_vector3_coef_kg_km2_s() {
let angular_momentum_vec = Vector3::new(
AngularMomentum::from_kg_m2_per_second(1e6), AngularMomentum::from_kg_m2_per_second(2e6), AngularMomentum::from_kg_m2_per_second(3e6), );
let coef_vec = angular_momentum_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
assert_relative_eq!(coef_vec.x, 1.0);
assert_relative_eq!(coef_vec.y, 2.0);
assert_relative_eq!(coef_vec.z, 3.0);
}
#[test]
fn test_from_vector_coef_kg_m2_s() {
let coef_vec = Vector3::new(
Coef::new(5.0),
Coef::new(10.0),
Coef::new(15.0),
);
let angular_momentum_vec = Vector3::<AngularMomentum>::from_vector_coef(coef_vec, AngularMomentumType::KgM2perSecond);
assert_relative_eq!(angular_momentum_vec.x.as_kg_m2_per_second(), 5.0);
assert_relative_eq!(angular_momentum_vec.y.as_kg_m2_per_second(), 10.0);
assert_relative_eq!(angular_momentum_vec.z.as_kg_m2_per_second(), 15.0);
}
#[test]
fn test_from_vector_coef_kg_km2_s() {
let coef_vec = Vector3::new(
Coef::new(1.0),
Coef::new(2.0),
Coef::new(3.0),
);
let angular_momentum_vec = Vector3::<AngularMomentum>::from_vector_coef(coef_vec, AngularMomentumType::KgKm2perSecond);
assert_relative_eq!(angular_momentum_vec.x.as_kg_km2_per_second(), 1.0);
assert_relative_eq!(angular_momentum_vec.y.as_kg_km2_per_second(), 2.0);
assert_relative_eq!(angular_momentum_vec.z.as_kg_km2_per_second(), 3.0);
}
#[test]
fn test_from_vector_coef_roundtrip() {
let original_angular_momentum_vec = Vector3::new(
AngularMomentum::from_kg_m2_per_second(5.0),
AngularMomentum::from_kg_m2_per_second(10.0),
AngularMomentum::from_kg_m2_per_second(15.0),
);
let coef_vec = original_angular_momentum_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let reconstructed_angular_momentum_vec = Vector3::<AngularMomentum>::from_vector_coef(coef_vec, AngularMomentumType::KgM2perSecond);
assert_relative_eq!(original_angular_momentum_vec.x.as_kg_m2_per_second(), reconstructed_angular_momentum_vec.x.as_kg_m2_per_second());
assert_relative_eq!(original_angular_momentum_vec.y.as_kg_m2_per_second(), reconstructed_angular_momentum_vec.y.as_kg_m2_per_second());
assert_relative_eq!(original_angular_momentum_vec.z.as_kg_m2_per_second(), reconstructed_angular_momentum_vec.z.as_kg_m2_per_second());
}
#[test]
fn test_angular_momentum_comprehensive_as_methods() {
let angular_momentum_vec = Vector3::new(
AngularMomentum::from_kg_m2_per_second(1.0),
AngularMomentum::from_kg_m2_per_second(2.0),
AngularMomentum::from_kg_m2_per_second(3.0),
);
let coef_kg_m2_s = angular_momentum_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_kg_km2_s = angular_momentum_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_nms = angular_momentum_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_mill_nms = angular_momentum_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_micro_nms = angular_momentum_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_nano_nms = angular_momentum_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_kg_m2_s.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_kg_km2_s.x.get_value(), 0.000001, epsilon = 1e-10);
assert_relative_eq!(coef_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_mill_nms.x.get_value(), 1000.0, epsilon = 1e-10);
assert_relative_eq!(coef_micro_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_nano_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
let kg_km2_s_vec = Vector3::new(
AngularMomentum::from_kg_km2_per_second(1.0),
AngularMomentum::from_kg_km2_per_second(2.0),
AngularMomentum::from_kg_km2_per_second(3.0),
);
let coef_from_kg_km2_s = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_from_kg_km2_s_km2 = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_from_kg_km2_s_nms = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_from_kg_km2_s_mill_nms = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_from_kg_km2_s_micro_nms = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_from_kg_km2_s_nano_nms = kg_km2_s_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_from_kg_km2_s.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_kg_km2_s_km2.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_kg_km2_s_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_kg_km2_s_mill_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_kg_km2_s_micro_nms.x.get_value(), 1000000000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_kg_km2_s_nano_nms.x.get_value(), 1000000000000000.0, epsilon = 1e-10);
let nms_vec = Vector3::new(
AngularMomentum::from_nms(1.0),
AngularMomentum::from_nms(2.0),
AngularMomentum::from_nms(3.0),
);
let coef_from_nms = nms_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_from_nms_km2 = nms_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_from_nms_nms = nms_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_from_nms_mill_nms = nms_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_from_nms_micro_nms = nms_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_from_nms_nano_nms = nms_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_from_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nms_km2.x.get_value(), 0.000001, epsilon = 1e-10);
assert_relative_eq!(coef_from_nms_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nms_mill_nms.x.get_value(), 1000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nms_micro_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nms_nano_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
let mill_nms_vec = Vector3::new(
AngularMomentum::from_mill_nms(1000.0),
AngularMomentum::from_mill_nms(2000.0),
AngularMomentum::from_mill_nms(3000.0),
);
let coef_from_mill_nms = mill_nms_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_from_mill_nms_km2 = mill_nms_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_from_mill_nms_nms = mill_nms_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_from_mill_nms_mill_nms = mill_nms_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_from_mill_nms_micro_nms = mill_nms_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_from_mill_nms_nano_nms = mill_nms_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_from_mill_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_mill_nms_km2.x.get_value(), 0.000001, epsilon = 1e-10);
assert_relative_eq!(coef_from_mill_nms_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_mill_nms_mill_nms.x.get_value(), 1000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_mill_nms_micro_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_mill_nms_nano_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
let micro_nms_vec = Vector3::new(
AngularMomentum::from_micro_nms(1000000.0),
AngularMomentum::from_micro_nms(2000000.0),
AngularMomentum::from_micro_nms(3000000.0),
);
let coef_from_micro_nms = micro_nms_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_from_micro_nms_km2 = micro_nms_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_from_micro_nms_nms = micro_nms_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_from_micro_nms_mill_nms = micro_nms_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_from_micro_nms_micro_nms = micro_nms_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_from_micro_nms_nano_nms = micro_nms_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_from_micro_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_micro_nms_km2.x.get_value(), 0.000001, epsilon = 1e-10);
assert_relative_eq!(coef_from_micro_nms_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_micro_nms_mill_nms.x.get_value(), 1000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_micro_nms_micro_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_micro_nms_nano_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
let nano_nms_vec = Vector3::new(
AngularMomentum::from_nano_nms(1000000000.0),
AngularMomentum::from_nano_nms(2000000000.0),
AngularMomentum::from_nano_nms(3000000000.0),
);
let coef_from_nano_nms = nano_nms_vec.to_vector3_coef(AngularMomentumType::KgM2perSecond);
let coef_from_nano_nms_km2 = nano_nms_vec.to_vector3_coef(AngularMomentumType::KgKm2perSecond);
let coef_from_nano_nms_nms = nano_nms_vec.to_vector3_coef(AngularMomentumType::Nms);
let coef_from_nano_nms_mill_nms = nano_nms_vec.to_vector3_coef(AngularMomentumType::MillNms);
let coef_from_nano_nms_micro_nms = nano_nms_vec.to_vector3_coef(AngularMomentumType::MicroNms);
let coef_from_nano_nms_nano_nms = nano_nms_vec.to_vector3_coef(AngularMomentumType::NanoNms);
assert_relative_eq!(coef_from_nano_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nano_nms_km2.x.get_value(), 0.000001, epsilon = 1e-10);
assert_relative_eq!(coef_from_nano_nms_nms.x.get_value(), 1.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nano_nms_mill_nms.x.get_value(), 1000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nano_nms_micro_nms.x.get_value(), 1000000.0, epsilon = 1e-10);
assert_relative_eq!(coef_from_nano_nms_nano_nms.x.get_value(), 1000000000.0, epsilon = 1e-10);
}
#[test]
fn test_from_array_with_unit() {
let array = [1.0, 2.0, 3.0];
let angular_momentum_vec = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::KgM2perSecond);
assert_relative_eq!(angular_momentum_vec.x.as_kg_m2_per_second(), 1.0);
assert_relative_eq!(angular_momentum_vec.y.as_kg_m2_per_second(), 2.0);
assert_relative_eq!(angular_momentum_vec.z.as_kg_m2_per_second(), 3.0);
let angular_momentum_vec_km2 = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::KgKm2perSecond);
assert_relative_eq!(angular_momentum_vec_km2.x.as_kg_km2_per_second(), 1.0);
assert_relative_eq!(angular_momentum_vec_km2.y.as_kg_km2_per_second(), 2.0);
assert_relative_eq!(angular_momentum_vec_km2.z.as_kg_km2_per_second(), 3.0);
let angular_momentum_vec_nms = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::Nms);
assert_relative_eq!(angular_momentum_vec_nms.x.as_nms(), 1.0);
assert_relative_eq!(angular_momentum_vec_nms.y.as_nms(), 2.0);
assert_relative_eq!(angular_momentum_vec_nms.z.as_nms(), 3.0);
let angular_momentum_vec_mill_nms = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::MillNms);
assert_relative_eq!(angular_momentum_vec_mill_nms.x.as_mill_nms(), 1.0);
assert_relative_eq!(angular_momentum_vec_mill_nms.y.as_mill_nms(), 2.0);
assert_relative_eq!(angular_momentum_vec_mill_nms.z.as_mill_nms(), 3.0);
let angular_momentum_vec_micro_nms = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::MicroNms);
assert_relative_eq!(angular_momentum_vec_micro_nms.x.as_micro_nms(), 1.0);
assert_relative_eq!(angular_momentum_vec_micro_nms.y.as_micro_nms(), 2.0);
assert_relative_eq!(angular_momentum_vec_micro_nms.z.as_micro_nms(), 3.0);
let angular_momentum_vec_nano_nms = Vector3::<AngularMomentum>::from_array_with_unit(array, AngularMomentumType::NanoNms);
assert_relative_eq!(angular_momentum_vec_nano_nms.x.as_nano_nms(), 1.0);
assert_relative_eq!(angular_momentum_vec_nano_nms.y.as_nano_nms(), 2.0);
assert_relative_eq!(angular_momentum_vec_nano_nms.z.as_nano_nms(), 3.0);
}
}