use affn::{CartesianDirection, Position, ReferenceCenter, ReferenceFrame};
use qtty::length::LengthUnit;
use qtty::Quantity;
#[derive(Debug, Clone)]
pub struct Ray<C: ReferenceCenter, F: ReferenceFrame, U: LengthUnit> {
pub origin: Position<C, F, U>,
pub direction: CartesianDirection<F>,
}
impl<C: ReferenceCenter, F: ReferenceFrame, U: LengthUnit> Ray<C, F, U> {
#[must_use]
pub fn new(origin: Position<C, F, U>, direction: CartesianDirection<F>) -> Self {
Self { origin, direction }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RaySegment<U: LengthUnit> {
pub t_min: Quantity<U>,
pub t_max: Quantity<U>,
}
impl<U: LengthUnit> RaySegment<U> {
#[must_use]
pub fn new(t_min: Quantity<U>, t_max: Quantity<U>) -> Self {
let (t_min, t_max) = if t_min <= t_max {
(t_min, t_max)
} else {
(t_max, t_min)
};
Self { t_min, t_max }
}
#[must_use]
pub fn length(&self) -> Quantity<U> {
self.t_max - self.t_min
}
}
#[cfg(test)]
mod tests {
use super::*;
use qtty::length::Kilometers;
use qtty::unit::Kilometer;
#[test]
fn segment_orders_endpoints() {
let segment = RaySegment::<Kilometer>::new(Kilometers::new(3.0), Kilometers::new(1.0));
assert_eq!(segment.t_min.value(), 1.0);
assert_eq!(segment.t_max.value(), 3.0);
}
}