bymsdfgen_core/math/
signed_distance.rs1use std::cmp::Ordering;
8
9#[derive(Debug, Clone, Copy)]
12pub struct SignedDistance {
13 pub distance: f64,
14 pub dot: f64,
15}
16
17impl Default for SignedDistance {
18 #[inline]
19 fn default() -> Self {
20 SignedDistance {
22 distance: f64::MIN,
23 dot: 0.0,
24 }
25 }
26}
27
28impl SignedDistance {
29 #[inline]
30 pub const fn new(distance: f64, dot: f64) -> Self {
31 SignedDistance { distance, dot }
32 }
33
34 #[inline]
36 pub fn cmp_key(self, other: SignedDistance) -> Ordering {
37 let a = self.distance.abs();
38 let b = other.distance.abs();
39 match a.partial_cmp(&b) {
40 Some(Ordering::Equal) | None => {
41 self.dot.partial_cmp(&other.dot).unwrap_or(Ordering::Equal)
42 }
43 Some(ord) => ord,
44 }
45 }
46
47 #[inline]
48 pub fn is_closer_than(self, other: SignedDistance) -> bool {
49 self.cmp_key(other) == Ordering::Less
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn closer_by_magnitude() {
59 let a = SignedDistance::new(-1.0, 0.5);
60 let b = SignedDistance::new(2.0, 0.0);
61 assert!(a.is_closer_than(b));
62 assert!(!b.is_closer_than(a));
63 }
64
65 #[test]
66 fn tiebreak_by_dot() {
67 let a = SignedDistance::new(1.0, 0.2);
68 let b = SignedDistance::new(-1.0, 0.9);
69 assert!(a.is_closer_than(b));
71 }
72}