Skip to main content

theon/
lib.rs

1//! **Theon** abstracts Euclidean spaces and geometric queries with support for popular linear
2//! algebra and spatial crates in the Rust ecosystem.
3
4// TODO: Require the `nalgebra` feature for doc tests.
5//
6//       See https://github.com/rust-lang/rust/issues/43781
7
8#![doc(
9    html_favicon_url = "https://raw.githubusercontent.com/olson-sean-k/theon/master/doc/theon-favicon.ico"
10)]
11#![doc(
12    html_logo_url = "https://raw.githubusercontent.com/olson-sean-k/theon/master/doc/theon.svg?sanitize=true"
13)]
14
15pub mod adjunct;
16pub mod lapack;
17pub mod ops;
18pub mod query;
19pub mod space;
20
21mod integration;
22
23use decorum::R64;
24use num_traits::cast::NumCast;
25use num_traits::identities::{One, Zero};
26use num_traits::Num;
27
28use crate::space::EuclideanSpace;
29
30pub mod prelude {
31    //! Re-exports commonly used types and traits.
32
33    pub use crate::query::Intersection as _;
34}
35
36pub type Position<T> = <T as AsPosition>::Position;
37
38/// Immutable positional data.
39///
40/// This trait exposes positional data for geometric types along with its mutable variant
41/// `AsPositionMut`.
42///
43/// # Examples
44///
45/// Exposing immutable positional data for a vertex:
46///
47/// ```rust
48/// # extern crate nalgebra;
49/// # extern crate theon;
50/// #
51/// use nalgebra::{Point3, Vector3};
52/// use theon::AsPosition;
53///
54/// pub struct Vertex {
55///     position: Point3<f64>,
56///     normal: Vector3<f64>,
57/// }
58///
59/// impl AsPosition for Vertex {
60///     type Position = Point3<f64>;
61///
62///     fn as_position(&self) -> &Self::Position {
63///         &self.position
64///     }
65/// }
66/// ```
67pub trait AsPosition {
68    type Position: EuclideanSpace;
69
70    fn as_position(&self) -> &Self::Position;
71}
72
73/// Mutable positional data.
74///
75/// This trait exposes positional data for geometric types along with its immutable variant
76/// `AsPosition`.
77///
78/// # Examples
79///
80/// Exposing mutable positional data for a vertex:
81///
82/// ```rust
83/// # extern crate nalgebra;
84/// # extern crate theon;
85/// #
86/// use nalgebra::{Point3, Vector3};
87/// use theon::{AsPosition, AsPositionMut};
88///
89/// pub struct Vertex {
90///     position: Point3<f64>,
91///     normal: Vector3<f64>,
92/// }
93///
94/// impl AsPosition for Vertex {
95///     type Position = Point3<f64>;
96///
97///     fn as_position(&self) -> &Self::Position {
98///         &self.position
99///     }
100/// }
101///
102/// impl AsPositionMut for Vertex {
103///     fn as_position_mut(&mut self) -> &mut Self::Position {
104///         &mut self.position
105///     }
106/// }
107/// ```
108pub trait AsPositionMut: AsPosition {
109    fn as_position_mut(&mut self) -> &mut Self::Position;
110
111    fn transform<F>(&mut self, mut f: F)
112    where
113        F: FnMut(&Self::Position) -> Self::Position,
114    {
115        *self.as_position_mut() = f(self.as_position());
116    }
117
118    fn map_position<F>(mut self, f: F) -> Self
119    where
120        Self: Sized,
121        F: FnMut(&Self::Position) -> Self::Position,
122    {
123        self.transform(f);
124        self
125    }
126}
127
128impl<T> AsPosition for &'_ T
129where
130    T: AsPosition,
131    T::Position: EuclideanSpace,
132{
133    type Position = <T as AsPosition>::Position;
134
135    fn as_position(&self) -> &Self::Position {
136        T::as_position(self)
137    }
138}
139
140impl<T> AsPosition for &'_ mut T
141where
142    T: AsPosition,
143    T::Position: EuclideanSpace,
144{
145    type Position = <T as AsPosition>::Position;
146
147    fn as_position(&self) -> &Self::Position {
148        T::as_position(self)
149    }
150}
151
152impl<T> AsPositionMut for &'_ mut T
153where
154    T: AsPositionMut,
155{
156    fn as_position_mut(&mut self) -> &mut Self::Position {
157        T::as_position_mut(self)
158    }
159}
160
161/// Linearly interpolates between two values.
162pub fn lerp<T>(a: T, b: T, f: R64) -> T
163where
164    T: Num + NumCast,
165{
166    let f = num_traits::clamp(f, Zero::zero(), One::one());
167    let af = <R64 as NumCast>::from(a).unwrap() * (R64::one() - f);
168    let bf = <R64 as NumCast>::from(b).unwrap() * f;
169    <T as NumCast>::from(af + bf).unwrap()
170}