emath/
range.rs

1use std::ops::{RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
2
3/// Inclusive range of floats, i.e. `min..=max`, but more ergonomic than [`RangeInclusive`].
4#[repr(C)]
5#[derive(Clone, Copy, Debug, PartialEq)]
6#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
7#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
8pub struct Rangef {
9    pub min: f32,
10    pub max: f32,
11}
12
13impl Rangef {
14    /// Infinite range that contains everything, from -∞ to +∞, inclusive.
15    pub const EVERYTHING: Self = Self {
16        min: f32::NEG_INFINITY,
17        max: f32::INFINITY,
18    };
19
20    /// The inverse of [`Self::EVERYTHING`]: stretches from positive infinity to negative infinity.
21    /// Contains nothing.
22    pub const NOTHING: Self = Self {
23        min: f32::INFINITY,
24        max: f32::NEG_INFINITY,
25    };
26
27    /// An invalid [`Rangef`] filled with [`f32::NAN`].
28    pub const NAN: Self = Self {
29        min: f32::NAN,
30        max: f32::NAN,
31    };
32
33    #[inline]
34    pub fn new(min: f32, max: f32) -> Self {
35        Self { min, max }
36    }
37
38    #[inline]
39    pub fn point(min_and_max: f32) -> Self {
40        Self {
41            min: min_and_max,
42            max: min_and_max,
43        }
44    }
45
46    /// The length of the range, i.e. `max - min`.
47    #[inline]
48    pub fn span(self) -> f32 {
49        self.max - self.min
50    }
51
52    /// The center of the range
53    #[inline]
54    pub fn center(self) -> f32 {
55        0.5 * (self.min + self.max)
56    }
57
58    #[inline]
59    #[must_use]
60    pub fn contains(self, x: f32) -> bool {
61        self.min <= x && x <= self.max
62    }
63
64    /// Equivalent to `x.clamp(min, max)`
65    #[inline]
66    #[must_use]
67    pub fn clamp(self, x: f32) -> f32 {
68        x.clamp(self.min, self.max)
69    }
70
71    /// Flip `min` and `max` if needed, so that `min <= max` after.
72    #[inline]
73    pub fn as_positive(self) -> Self {
74        Self {
75            min: self.min.min(self.max),
76            max: self.min.max(self.max),
77        }
78    }
79
80    /// Shrink by this much on each side, keeping the center
81    #[inline]
82    #[must_use]
83    pub fn shrink(self, amnt: f32) -> Self {
84        Self {
85            min: self.min + amnt,
86            max: self.max - amnt,
87        }
88    }
89
90    /// Expand by this much on each side, keeping the center
91    #[inline]
92    #[must_use]
93    pub fn expand(self, amnt: f32) -> Self {
94        Self {
95            min: self.min - amnt,
96            max: self.max + amnt,
97        }
98    }
99
100    /// Flip the min and the max
101    #[inline]
102    #[must_use]
103    pub fn flip(self) -> Self {
104        Self {
105            min: self.max,
106            max: self.min,
107        }
108    }
109
110    /// The overlap of two ranges, i.e. the range that is contained by both.
111    ///
112    /// If the ranges do not overlap, returns a range with `span() < 0.0`.
113    ///
114    /// ```
115    /// # use emath::Rangef;
116    /// assert_eq!(Rangef::new(0.0, 10.0).intersection(Rangef::new(5.0, 15.0)), Rangef::new(5.0, 10.0));
117    /// assert_eq!(Rangef::new(0.0, 10.0).intersection(Rangef::new(10.0, 20.0)), Rangef::new(10.0, 10.0));
118    /// assert!(Rangef::new(0.0, 10.0).intersection(Rangef::new(20.0, 30.0)).span() < 0.0);
119    /// ```
120    #[inline]
121    #[must_use]
122    pub fn intersection(self, other: Self) -> Self {
123        Self {
124            min: self.min.max(other.min),
125            max: self.max.min(other.max),
126        }
127    }
128
129    /// Do the two ranges intersect?
130    ///
131    /// ```
132    /// # use emath::Rangef;
133    /// assert!(Rangef::new(0.0, 10.0).intersects(Rangef::new(5.0, 15.0)));
134    /// assert!(Rangef::new(0.0, 10.0).intersects(Rangef::new(5.0, 6.0)));
135    /// assert!(Rangef::new(0.0, 10.0).intersects(Rangef::new(10.0, 20.0)));
136    /// assert!(!Rangef::new(0.0, 10.0).intersects(Rangef::new(20.0, 30.0)));
137    /// ```
138    #[inline]
139    #[must_use]
140    pub fn intersects(self, other: Self) -> bool {
141        other.min <= self.max && self.min <= other.max
142    }
143}
144
145impl From<Rangef> for RangeInclusive<f32> {
146    #[inline]
147    fn from(Rangef { min, max }: Rangef) -> Self {
148        min..=max
149    }
150}
151
152impl From<&Rangef> for RangeInclusive<f32> {
153    #[inline]
154    fn from(&Rangef { min, max }: &Rangef) -> Self {
155        min..=max
156    }
157}
158
159impl From<RangeInclusive<f32>> for Rangef {
160    #[inline]
161    fn from(range: RangeInclusive<f32>) -> Self {
162        Self::new(*range.start(), *range.end())
163    }
164}
165
166impl From<&RangeInclusive<f32>> for Rangef {
167    #[inline]
168    fn from(range: &RangeInclusive<f32>) -> Self {
169        Self::new(*range.start(), *range.end())
170    }
171}
172
173impl From<RangeFrom<f32>> for Rangef {
174    #[inline]
175    fn from(range: RangeFrom<f32>) -> Self {
176        Self::new(range.start, f32::INFINITY)
177    }
178}
179
180impl From<&RangeFrom<f32>> for Rangef {
181    #[inline]
182    fn from(range: &RangeFrom<f32>) -> Self {
183        Self::new(range.start, f32::INFINITY)
184    }
185}
186
187impl From<RangeFull> for Rangef {
188    #[inline]
189    fn from(_: RangeFull) -> Self {
190        Self::new(f32::NEG_INFINITY, f32::INFINITY)
191    }
192}
193
194impl From<&RangeFull> for Rangef {
195    #[inline]
196    fn from(_: &RangeFull) -> Self {
197        Self::new(f32::NEG_INFINITY, f32::INFINITY)
198    }
199}
200
201impl From<RangeToInclusive<f32>> for Rangef {
202    #[inline]
203    fn from(range: RangeToInclusive<f32>) -> Self {
204        Self::new(f32::NEG_INFINITY, range.end)
205    }
206}
207
208impl PartialEq<RangeInclusive<f32>> for Rangef {
209    #[inline]
210    fn eq(&self, other: &RangeInclusive<f32>) -> bool {
211        self.min == *other.start() && self.max == *other.end()
212    }
213}
214
215impl PartialEq<Rangef> for RangeInclusive<f32> {
216    #[inline]
217    fn eq(&self, other: &Rangef) -> bool {
218        *self.start() == other.min && *self.end() == other.max
219    }
220}