#![doc(
html_favicon_url = "https://raw.githubusercontent.com/olson-sean-k/theon/master/doc/theon-favicon.ico"
)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/olson-sean-k/theon/master/doc/theon.svg?sanitize=true"
)]
pub mod adjunct;
pub mod lapack;
pub mod ops;
pub mod query;
pub mod space;
mod integration;
use decorum::R64;
use num_traits::cast::NumCast;
use num_traits::identities::{One, Zero};
use num_traits::Num;
use crate::space::EuclideanSpace;
pub mod prelude {
pub use crate::query::Intersection as _;
}
pub type Position<T> = <T as AsPosition>::Position;
pub trait AsPosition {
type Position: EuclideanSpace;
fn as_position(&self) -> &Self::Position;
}
pub trait AsPositionMut: AsPosition {
fn as_position_mut(&mut self) -> &mut Self::Position;
fn transform<F>(&mut self, mut f: F)
where
F: FnMut(&Self::Position) -> Self::Position,
{
*self.as_position_mut() = f(self.as_position());
}
fn map_position<F>(mut self, f: F) -> Self
where
Self: Sized,
F: FnMut(&Self::Position) -> Self::Position,
{
self.transform(f);
self
}
}
impl<T> AsPosition for &'_ T
where
T: AsPosition,
T::Position: EuclideanSpace,
{
type Position = <T as AsPosition>::Position;
fn as_position(&self) -> &Self::Position {
T::as_position(self)
}
}
impl<T> AsPosition for &'_ mut T
where
T: AsPosition,
T::Position: EuclideanSpace,
{
type Position = <T as AsPosition>::Position;
fn as_position(&self) -> &Self::Position {
T::as_position(self)
}
}
impl<T> AsPositionMut for &'_ mut T
where
T: AsPositionMut,
{
fn as_position_mut(&mut self) -> &mut Self::Position {
T::as_position_mut(self)
}
}
pub fn lerp<T>(a: T, b: T, f: R64) -> T
where
T: Num + NumCast,
{
let f = num_traits::clamp(f, Zero::zero(), One::one());
let af = <R64 as NumCast>::from(a).unwrap() * (R64::one() - f);
let bf = <R64 as NumCast>::from(b).unwrap() * f;
<T as NumCast>::from(af + bf).unwrap()
}