use crate::{Real, hypot};
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "tsify", derive(tsify::Tsify))]
pub struct Position {
pub x: Real,
pub y: Real,
pub z: Real,
}
impl Position {
#[inline]
pub const fn new(x: Real, y: Real, z: Real) -> Position {
Self { x, y, z }
}
pub const ZERO: Self = Self::new(f!(0.0), f!(0.0), f!(0.0));
#[inline]
pub const fn from_au(x: Real, y: Real, z: Real) -> Position {
const AU: Real = f!(1.495978707e11);
Self {
x: x * AU,
y: y * AU,
z: z * AU,
}
}
#[inline]
pub const fn norm(self) -> Real {
hypot(hypot(self.x, self.y), self.z)
}
pub const fn distance_to(self, other: Self) -> Real {
let dx = self.x - other.x;
let dy = self.y - other.y;
let dz = self.z - other.z;
hypot(hypot(dx, dy), dz)
}
#[inline]
pub const fn lerp(self, other: Self, t: Real) -> Position {
Self::new(
self.x * (f!(1.0) - t) + other.x * t,
self.y * (f!(1.0) - t) + other.y * t,
self.z * (f!(1.0) - t) + other.z * t,
)
}
}
#[cfg(feature = "wire")]
impl Position {
pub const WIRE_SIZE: usize = 24;
pub fn to_wire_bytes(&self) -> [u8; Self::WIRE_SIZE] {
let mut buf = [0u8; Self::WIRE_SIZE];
buf[0..8].copy_from_slice(&self.x.to_le_bytes());
buf[8..16].copy_from_slice(&self.y.to_le_bytes());
buf[16..24].copy_from_slice(&self.z.to_le_bytes());
buf
}
pub fn from_wire_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != Self::WIRE_SIZE {
return None;
}
let x = Real::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
let y = Real::from_le_bytes([
bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
]);
let z = Real::from_le_bytes([
bytes[16], bytes[17], bytes[18], bytes[19], bytes[20], bytes[21], bytes[22], bytes[23],
]);
Some(Self { x, y, z })
}
}