geo_booleanop/boolean/
helper.rs

1use float_next_after::NextAfter as NextAfterFloat;
2use geo_types::{Coordinate, CoordinateType};
3use num_traits::Float as NumTraitsFloat;
4use std::cmp::Ordering;
5use std::fmt::{Debug, Display};
6use std::{f32, f64};
7
8pub trait Float: NumTraitsFloat + Debug + Display + NextAfter + Into<f64> {}
9
10impl<T: NumTraitsFloat + Debug + Display + NextAfter + Into<f64>> Float for T {}
11
12pub trait NextAfter: NumTraitsFloat {
13    fn nextafter(self, up: bool) -> Self;
14}
15
16impl NextAfter for f64 {
17    fn nextafter(self, up: bool) -> Self {
18        if up {
19            self.next_after(std::f64::INFINITY)
20        } else {
21            self.next_after(std::f64::NEG_INFINITY)
22        }
23    }
24}
25
26impl NextAfter for f32 {
27    fn nextafter(self, up: bool) -> Self {
28        if up {
29            self.next_after(std::f32::INFINITY)
30        } else {
31            self.next_after(std::f32::NEG_INFINITY)
32        }
33    }
34}
35
36#[inline]
37pub fn less_if(condition: bool) -> Ordering {
38    if condition {
39        Ordering::Less
40    } else {
41        Ordering::Greater
42    }
43}
44
45#[inline]
46pub fn less_if_inversed(condition: bool) -> Ordering {
47    if condition {
48        Ordering::Greater
49    } else {
50        Ordering::Less
51    }
52}
53
54/// A bounded 2D quadrilateral whose area is defined by minimum and maximum `Coordinates`.
55///
56/// A simple implementation copied from geo_types 0.4.0, because this version is a better
57/// fit for the needs of this crate than the newer ones.
58#[derive(PartialEq, Clone, Copy, Debug)]
59pub struct BoundingBox<T>
60    where
61        T: CoordinateType,
62{
63    pub min: Coordinate<T>,
64    pub max: Coordinate<T>,
65}
66
67impl<T: CoordinateType> BoundingBox<T> {
68    pub fn width(self) -> T {
69        self.max.x - self.min.x
70    }
71
72    pub fn height(self) -> T {
73        self.max.y - self.min.y
74    }
75}
76
77#[cfg(test)]
78pub mod test {
79    use super::Float;
80    use float_next_after::NextAfter as NextAfterFloat;
81    use geo_types::Coordinate;
82
83    pub fn xy<X: Into<f64>, Y: Into<f64>>(x: X, y: Y) -> Coordinate<f64> {
84        Coordinate {
85            x: x.into(),
86            y: y.into(),
87        }
88    }
89
90    #[test]
91    fn test_float_type_trait() {
92        fn dummy<T>(x: T) -> T
93        where
94            T: Float,
95        {
96            x.nextafter(true)
97        }
98
99        assert_eq!(dummy(0_f64), 0_f64.next_after(std::f64::INFINITY));
100        assert_eq!(dummy(0_f32), 0_f32.next_after(std::f32::INFINITY));
101    }
102}