Skip to main content

use_affine/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_point::Point2;
5
6/// A pair of affine weights for two points.
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct AffinePair {
9    first: f64,
10    second: f64,
11}
12
13impl AffinePair {
14    /// Creates affine weights that sum to one.
15    #[must_use]
16    pub fn new(first: f64, second: f64) -> Option<Self> {
17        if first.is_finite() && second.is_finite() && (first + second - 1.0).abs() <= 1.0e-12 {
18            Some(Self { first, second })
19        } else {
20            None
21        }
22    }
23
24    /// Returns the first weight.
25    #[must_use]
26    pub const fn first(self) -> f64 {
27        self.first
28    }
29
30    /// Returns the second weight.
31    #[must_use]
32    pub const fn second(self) -> f64 {
33        self.second
34    }
35}
36
37/// Returns the affine interpolation between two 2D points.
38#[must_use]
39pub const fn affine_combination_2d(a: Point2, b: Point2, t: f64) -> Point2 {
40    a.lerp(b, t)
41}
42
43#[cfg(test)]
44mod tests {
45    use super::{AffinePair, affine_combination_2d};
46    use use_point::Point2;
47
48    #[test]
49    fn computes_affine_combinations() {
50        let midpoint = affine_combination_2d(Point2::new(0.0, 0.0), Point2::new(4.0, 2.0), 0.5);
51
52        assert_eq!(midpoint, Point2::new(2.0, 1.0));
53        assert_eq!(AffinePair::new(0.25, 0.75).expect("valid").first(), 0.25);
54        assert_eq!(AffinePair::new(0.25, 0.70), None);
55    }
56}