pub trait CoordinateSet: CoordinateMetadata {
fn len(&self) -> usize;
fn dim(&self) -> usize;
fn get_coord(&self, index: usize) -> Coor4D;
fn set_coord(&mut self, index: usize, value: &Coor4D);
fn is_empty(&self) -> bool {
self.len() == 0
}
fn set_xy(&mut self, index: usize, x: f64, y: f64) {
let mut coord = self.get_coord(index);
coord[0] = x;
coord[1] = y;
self.set_coord(index, &coord);
}
fn xy(&self, index: usize) -> (f64, f64) {
self.get_coord(index).xy()
}
fn set_xyz(&mut self, index: usize, x: f64, y: f64, z: f64) {
let mut coord = self.get_coord(index);
coord[0] = x;
coord[1] = y;
coord[2] = z;
self.set_coord(index, &coord);
}
fn xyz(&self, index: usize) -> (f64, f64, f64) {
self.get_coord(index).xyz()
}
fn set_xyzt(&mut self, index: usize, x: f64, y: f64, z: f64, t: f64) {
self.set_coord(index, &Coor4D([x, y, z, t]));
}
fn xyzt(&self, index: usize) -> (f64, f64, f64, f64) {
self.get_coord(index).xyzt()
}
fn stomp(&mut self) {
let nanny = Coor4D::nan();
for i in 0..self.len() {
self.set_coord(i, &nanny);
}
}
}
use super::*;
macro_rules! length {
(array) => {
fn len(&self) -> usize {
N
}
};
(slice) => {
fn len(&self) -> usize {
(**self).len()
}
};
(vec) => {
fn len(&self) -> usize {
self.len()
}
};
}
macro_rules! coordinate_set_impl_2d_subset {
($dim:expr, $len:ident) => {
length!($len);
fn dim(&self) -> usize {
$dim
}
fn xy(&self, index: usize) -> (f64, f64) {
self[index].xy()
}
fn set_xy(&mut self, index: usize, x: f64, y: f64) {
self[index].set_xy(x, y);
}
};
}
macro_rules! coordinate_set_impl_3d_subset {
($dim:expr, $len:ident) => {
coordinate_set_impl_2d_subset!($dim, $len);
fn xyz(&self, index: usize) -> (f64, f64, f64) {
self[index].xyz()
}
fn set_xyz(&mut self, index: usize, x: f64, y: f64, z: f64) {
self[index].set_xyz(x, y, z);
}
};
}
macro_rules! coordinate_set_impl_for_coor2d {
($kind:ident) => {
coordinate_set_impl_2d_subset!(2, $kind);
fn get_coord(&self, index: usize) -> Coor4D {
Coor4D([self[index][0], self[index][1], 0., f64::NAN])
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self[index] = Coor2D([value[0], value[1]]);
}
};
}
impl<const N: usize> CoordinateSet for [Coor2D; N] {
coordinate_set_impl_for_coor2d!(array);
}
impl CoordinateSet for &mut [Coor2D] {
coordinate_set_impl_for_coor2d!(slice);
}
impl CoordinateSet for Vec<Coor2D> {
coordinate_set_impl_for_coor2d!(vec);
}
macro_rules! coordinate_set_impl_for_coor32 {
($kind:ident) => {
coordinate_set_impl_2d_subset!(2, $kind);
fn get_coord(&self, index: usize) -> Coor4D {
Coor4D([self[index][0] as f64, self[index][1] as f64, 0., f64::NAN])
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self[index] = Coor32([value[0] as f32, value[1] as f32]);
}
};
}
impl<const N: usize> CoordinateSet for [Coor32; N] {
coordinate_set_impl_for_coor32!(array);
}
impl CoordinateSet for &mut [Coor32] {
coordinate_set_impl_for_coor32!(slice);
}
impl CoordinateSet for Vec<Coor32> {
coordinate_set_impl_for_coor32!(vec);
}
macro_rules! coordinate_set_impl_for_coor3d {
($kind:ident) => {
coordinate_set_impl_3d_subset!(3, $kind);
fn get_coord(&self, index: usize) -> Coor4D {
Coor4D([self[index][0], self[index][1], self[index][2], f64::NAN])
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self[index] = Coor3D([value[0], value[1], value[2]]);
}
};
}
impl<const N: usize> CoordinateSet for [Coor3D; N] {
coordinate_set_impl_for_coor3d!(array);
}
impl CoordinateSet for &mut [Coor3D] {
coordinate_set_impl_for_coor3d!(slice);
}
impl CoordinateSet for Vec<Coor3D> {
coordinate_set_impl_for_coor3d!(vec);
}
macro_rules! coordinate_set_impl_for_coor4d {
($kind:ident) => {
coordinate_set_impl_3d_subset!(4, $kind);
fn get_coord(&self, index: usize) -> Coor4D {
self[index]
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self[index] = *value;
}
fn xyzt(&self, index: usize) -> (f64, f64, f64, f64) {
self[index].xyzt()
}
fn set_xyzt(&mut self, index: usize, x: f64, y: f64, z: f64, t: f64) {
self[index].set_xyzt(x, y, z, t);
}
};
}
impl<const N: usize> CoordinateSet for [Coor4D; N] {
coordinate_set_impl_for_coor4d!(array);
}
impl CoordinateSet for &mut [Coor4D] {
coordinate_set_impl_for_coor4d!(slice);
}
impl CoordinateSet for Vec<Coor4D> {
coordinate_set_impl_for_coor4d!(vec);
}
impl<T> CoordinateSet for (T, f64, f64)
where
T: CoordinateSet,
{
fn len(&self) -> usize {
self.0.len()
}
fn dim(&self) -> usize {
4
}
fn get_coord(&self, index: usize) -> Coor4D {
let c = self.0.get_coord(index);
Coor4D([c[0], c[1], self.1, self.2])
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self.0.set_coord(index, value);
}
}
impl<T> CoordinateSet for (T, f64)
where
T: CoordinateSet,
{
fn len(&self) -> usize {
self.0.len()
}
fn dim(&self) -> usize {
4
}
fn get_coord(&self, index: usize) -> Coor4D {
let c = self.0.get_coord(index);
Coor4D([c[0], c[1], c[2], self.1])
}
fn set_coord(&mut self, index: usize, value: &Coor4D) {
self.0.set_coord(index, value);
}
}
impl MdIdentifier {
pub fn new() -> Self {
MdIdentifier(uuid::Uuid::new_v4())
}
}
impl Default for MdIdentifier {
fn default() -> Self {
MdIdentifier(uuid::Uuid::new_v4())
}
}
impl DataEpoch {
pub fn new() -> Self {
DataEpoch(f64::NAN)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn array() {
let mut operands = crate::test_data::coor4d();
assert_eq!(operands.len(), 2);
assert!(!operands.is_empty());
let cph = operands.get_coord(0);
assert_eq!(cph[0], 55.);
assert_eq!(cph[1], 12.);
let sth = operands.get_coord(1);
assert_eq!(sth[0], 59.);
assert_eq!(sth[1], 18.);
operands.set_coord(0, &sth);
let cph = operands.get_coord(0);
assert_eq!(cph[0], 59.);
assert_eq!(cph[1], 18.);
}
#[test]
fn vector() {
let mut operands = Vec::from(crate::test_data::coor2d());
assert_eq!(operands.len(), 2);
assert!(!operands.is_empty());
let cph = operands.get_coord(0);
assert_eq!(cph[0], 55.);
assert_eq!(cph[1], 12.);
let sth = operands.get_coord(1);
assert_eq!(sth[0], 59.);
assert_eq!(sth[1], 18.);
operands.set_coord(0, &sth);
let cph = operands.get_coord(0);
assert_eq!(cph[0], 59.);
assert_eq!(cph[1], 18.);
}
#[test]
fn angular() {
let operands = crate::test_data::coor2d();
let cph = operands.get_coord(0);
let cph = cph.to_radians();
assert_eq!(cph[0], operands.get_coord(0).to_radians()[0]);
assert_eq!(cph[1], operands.get_coord(0).to_radians()[1]);
assert_eq!(
cph[0].to_degrees() * 3600.,
operands.get_coord(0).to_radians().to_arcsec()[0]
);
assert_eq!(
cph[1].to_degrees() * 3600.,
operands.get_coord(0).to_radians().to_arcsec()[1]
);
}
#[test]
fn setting_and_getting_as_f64() {
let first = Coor4D([11., 12., 13., 14.]);
let second = Coor4D([21., 22., 23., 24.]);
let mut operands = Vec::from([first, second]);
let (x, y) = operands.xy(0);
assert_eq!((x, y), (11., 12.));
let (x, y) = operands.xy(1);
assert_eq!((x, y), (21., 22.));
operands.set_xy(0, x, y);
let (x, y) = operands.xy(0);
assert_eq!((x, y), (21., 22.));
let mut operands = Vec::from([first, second]);
let (x, y, z) = operands.xyz(0);
assert_eq!((x, y, z), (11., 12., 13.));
let (x, y, z) = operands.xyz(1);
assert_eq!((x, y, z), (21., 22., 23.));
operands.set_xyz(0, x, y, z);
let (x, y, z) = operands.xyz(0);
assert_eq!((x, y, z), (21., 22., 23.));
let mut operands = Vec::from([first, second]);
let (x, y, z, t) = operands.xyzt(0);
assert_eq!((x, y, z, t), (11., 12., 13., 14.));
let (x, y, z, t) = operands.xyzt(1);
assert_eq!((x, y, z, t), (21., 22., 23., 24.));
operands.set_xyzt(0, x, y, z, t);
let (x, y, z, t) = operands.xyzt(0);
assert_eq!((x, y, z, t), (21., 22., 23., 24.));
}
}