1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_point::Point2;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct AffinePair {
9 first: f64,
10 second: f64,
11}
12
13impl AffinePair {
14 #[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 #[must_use]
26 pub const fn first(self) -> f64 {
27 self.first
28 }
29
30 #[must_use]
32 pub const fn second(self) -> f64 {
33 self.second
34 }
35}
36
37#[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}