pbrt_r3/core/geometry/
bounds2.rs

1use super::Vector2;
2use crate::core::base::*;
3
4#[derive(Debug, PartialEq, Copy, Clone)]
5pub struct Bounds2<T> {
6    pub min: Vector2<T>,
7    pub max: Vector2<T>,
8}
9
10pub type Bounds2f = Bounds2<Float>;
11pub type Bounds2i = Bounds2<i32>;
12
13impl<T: Copy + PartialOrd> Bounds2<T> {
14    pub fn new(v0: &Vector2<T>, v1: &Vector2<T>) -> Self {
15        let min = Vector2::<T>::new(min_(v0.x, v1.x), min_(v0.y, v1.y));
16        let max = Vector2::<T>::new(max_(v0.x, v1.x), max_(v0.y, v1.y));
17        Bounds2::<T> { min, max }
18    }
19}
20
21fn min_<T: Copy + PartialOrd>(a: T, b: T) -> T {
22    return if a <= b { a } else { b };
23}
24
25fn max_<T: Copy + PartialOrd>(a: T, b: T) -> T {
26    return if a >= b { a } else { b };
27}
28
29impl<
30        T: Copy
31            + PartialOrd
32            + std::ops::Add<Output = T>
33            + std::ops::Sub<Output = T>
34            + std::ops::Mul<Output = T>
35            + std::ops::Div<Output = T>,
36    > Bounds2<T>
37{
38    pub fn area(&self) -> T {
39        return (self.max.x - self.min.x) * (self.max.y - self.min.y);
40    }
41    pub fn diagonal(&self) -> Vector2<T> {
42        return self.max - self.min;
43    }
44    pub fn offset(&self, p: &Vector2<T>) -> Vector2<T> {
45        let mut o = *p - self.min;
46        if self.max.x > self.min.x {
47            o.x = o.x / (self.max.x - self.min.x);
48        }
49        if self.max.y > self.min.y {
50            o.y = o.y / (self.max.y - self.min.y);
51        }
52        return o;
53    }
54
55    pub fn expand(&self, delta: T) -> Self {
56        let delta = Vector2::<T>::new(delta, delta);
57        return Bounds2 {
58            min: self.min - delta,
59            max: self.max + delta,
60        };
61    }
62
63    pub fn union(&self, other: &Self) -> Self {
64        let min = Vector2::<T>::new(min_(self.min.x, other.min.x), min_(self.min.y, other.min.y));
65        let max = Vector2::<T>::new(max_(self.max.x, other.max.x), max_(self.max.y, other.max.y));
66        return Bounds2 { min, max };
67    }
68
69    pub fn intersect(&self, other: &Self) -> Self {
70        let min = Vector2::<T>::new(max_(self.min.x, other.min.x), max_(self.min.y, other.min.y));
71        let max = Vector2::<T>::new(min_(self.max.x, other.max.x), min_(self.max.y, other.max.y));
72        return Bounds2 { min, max };
73    }
74
75    pub fn union_p(&self, other: &Vector2<T>) -> Self {
76        let min = Vector2::<T>::new(min_(self.min.x, other.x), min_(self.min.y, other.y));
77        let max = Vector2::<T>::new(max_(self.max.x, other.x), max_(self.max.y, other.y));
78        return Bounds2 { min, max };
79    }
80
81    pub fn inside(&self, p: &Vector2<T>) -> bool {
82        return p.x >= self.min.x && p.x <= self.max.x && p.y >= self.min.y && p.y <= self.max.y;
83    }
84
85    pub fn inside_exclusive(&self, p: &Vector2<T>) -> bool {
86        return p.x >= self.min.x && p.x < self.max.x && p.y >= self.min.y && p.y < self.max.y;
87    }
88}
89
90impl Bounds2f {
91    pub fn lerp(&self, t: &Vector2f) -> Vector2f {
92        return Vector2f::new(
93            lerp(t.x, self.min.x, self.max.x),
94            lerp(t.y, self.min.y, self.max.y),
95        );
96    }
97}
98
99impl<T: Copy + PartialOrd> From<((T, T), (T, T))> for Bounds2<T> {
100    fn from(value: ((T, T), (T, T))) -> Self {
101        let min = Vector2::<T>::from(value.0);
102        let max = Vector2::<T>::from(value.1);
103        Bounds2::<T>::new(&min, &max)
104    }
105}
106
107impl<T: Copy> From<(T, T)> for Bounds2<T> {
108    fn from(value: (T, T)) -> Self {
109        Bounds2::<T> {
110            min: Vector2::<T>::from(value),
111            max: Vector2::<T>::from(value),
112        }
113    }
114}
115
116pub struct Bounds2iIterator<'a> {
117    p: Point2i,
118    bounds: &'a Bounds2i,
119}
120
121impl<'a> Iterator for Bounds2iIterator<'a> {
122    type Item = Point2i;
123
124    fn next(&mut self) -> Option<Self::Item> {
125        if self.p.y < self.bounds.max.y && self.p.x < self.bounds.max.x {
126            let old = self.p;
127            self.p.x += 1;
128            if self.p.x == self.bounds.max.x {
129                self.p.x = self.bounds.min.x;
130                self.p.y += 1;
131            }
132            return Some(old);
133        } else {
134            return None;
135        }
136    }
137}
138
139impl<'a> IntoIterator for &'a Bounds2i {
140    type Item = Point2i;
141    type IntoIter = Bounds2iIterator<'a>;
142
143    fn into_iter(self) -> Self::IntoIter {
144        Bounds2iIterator {
145            p: self.min,
146            bounds: self,
147        }
148    }
149}
150
151impl Default for Bounds2i {
152    fn default() -> Self {
153        Bounds2i {
154            min: Point2i::new(std::i32::MAX, std::i32::MAX),
155            max: Point2i::new(std::i32::MIN, std::i32::MIN),
156        }
157    }
158}
159
160impl Default for Bounds2f {
161    fn default() -> Self {
162        Bounds2f {
163            min: Point2f::new(Float::MAX, Float::MAX),
164            max: Point2f::new(Float::MIN, Float::MIN),
165        }
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172
173    #[test]
174    fn test_001() {
175        let v1 = Vector2f::new(1.0, 2.0);
176        let v2 = Vector2f::new(4.0, 5.0);
177        let b1 = Bounds2f::new(&v1, &v2);
178        assert_eq!(b1.min, v1);
179        assert_eq!(b1.max, v2);
180    }
181}