building_blocks_core/point/
point2.rs

1use crate::{Axis2, IterExtent};
2
3use super::{point_traits::*, PointN};
4
5use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Range, Rem, Shl, Shr};
6use itertools::{iproduct, Product};
7use num::{traits::Pow, Integer, Signed};
8use std::cmp::Ordering;
9
10/// A 2-dimensional point with scalar type `T`.
11pub type Point2<T> = PointN<[T; 2]>;
12/// A 2-dimensional point with scalar type `i32`.
13pub type Point2i = PointN<[i32; 2]>;
14/// A 2-dimensional point with scalar type `f32`.
15pub type Point2f = PointN<[f32; 2]>;
16
17impl<T> Point2<T> {
18    #[inline]
19    pub fn x_mut(&mut self) -> &mut T {
20        &mut self.0[0]
21    }
22
23    #[inline]
24    pub fn y_mut(&mut self) -> &mut T {
25        &mut self.0[1]
26    }
27
28    #[inline]
29    pub fn axis_component_mut(&mut self, axis: Axis2) -> &mut T {
30        &mut self.0[axis.index()]
31    }
32}
33
34impl<T> Point2<T>
35where
36    T: Copy,
37{
38    #[inline]
39    pub fn axis_component(self, axis: Axis2) -> T {
40        self.0[axis.index()]
41    }
42
43    #[inline]
44    pub fn x(self) -> T {
45        self.0[0]
46    }
47
48    #[inline]
49    pub fn y(self) -> T {
50        self.0[1]
51    }
52
53    #[inline]
54    pub fn yx(self) -> Self {
55        PointN([self.y(), self.x()])
56    }
57}
58
59impl Point2i {
60    pub const SQUARE_CORNER_OFFSETS: [Self; 4] = [
61        PointN([0, 0]),
62        PointN([1, 0]),
63        PointN([0, 1]),
64        PointN([1, 1]),
65    ];
66
67    pub const VON_NEUMANN_OFFSETS: [Self; 4] = [
68        PointN([-1, 0]),
69        PointN([1, 0]),
70        PointN([0, -1]),
71        PointN([0, 1]),
72    ];
73
74    pub const MOORE_OFFSETS: [Self; 8] = [
75        PointN([-1, -1]),
76        PointN([0, -1]),
77        PointN([1, -1]),
78        PointN([-1, 0]),
79        PointN([1, 0]),
80        PointN([-1, 1]),
81        PointN([0, 1]),
82        PointN([1, 1]),
83    ];
84}
85
86impl Point2f {
87    /// Returns the coordinates of the pixel containing `self`.
88    #[inline]
89    pub fn in_pixel(self) -> Point2i {
90        self.floor_int()
91    }
92}
93
94impl IntoIntegerPoint for Point2f {
95    type IntPoint = Point2i;
96
97    #[inline]
98    fn into_int(self) -> Self::IntPoint {
99        PointN([self.x() as i32, self.y() as i32])
100    }
101}
102
103impl<T> Bounded for Point2<T>
104where
105    T: Bounded,
106{
107    const MAX: Self = PointN([T::MAX; 2]);
108    const MIN: Self = PointN([T::MIN; 2]);
109}
110
111impl<T> MapComponents for Point2<T>
112where
113    T: Copy,
114{
115    type Scalar = T;
116
117    #[inline]
118    fn map_components_unary(self, f: impl Fn(Self::Scalar) -> Self::Scalar) -> Self {
119        PointN([f(self.x()), f(self.y())])
120    }
121
122    #[inline]
123    fn map_components_binary(
124        self,
125        other: Self,
126        f: impl Fn(Self::Scalar, Self::Scalar) -> Self::Scalar,
127    ) -> Self {
128        PointN([f(self.x(), other.x()), f(self.y(), other.y())])
129    }
130}
131
132impl MinMaxComponent for Point2i {
133    type Scalar = i32;
134
135    #[inline]
136    fn min_component(self) -> Self::Scalar {
137        self.x().min(self.y())
138    }
139    #[inline]
140    fn max_component(self) -> Self::Scalar {
141        self.x().max(self.y())
142    }
143}
144
145impl MinMaxComponent for Point2f {
146    type Scalar = f32;
147
148    #[inline]
149    fn min_component(self) -> Self::Scalar {
150        self.x().min(self.y())
151    }
152    #[inline]
153    fn max_component(self) -> Self::Scalar {
154        self.x().max(self.y())
155    }
156}
157
158impl<T> GetComponent for Point2<T>
159where
160    T: Copy,
161{
162    type Scalar = T;
163
164    #[inline]
165    fn at(self, component_index: usize) -> T {
166        self.0[component_index]
167    }
168}
169
170impl Point for Point2i {
171    type Scalar = i32;
172
173    #[inline]
174    fn fill(value: i32) -> Self {
175        Self([value; 2])
176    }
177
178    #[inline]
179    fn basis() -> Vec<Self> {
180        vec![PointN([1, 0]), PointN([0, 1])]
181    }
182
183    #[inline]
184    fn volume(self) -> <Self as Point>::Scalar {
185        self.x() * self.y()
186    }
187}
188
189impl Point for Point2f {
190    type Scalar = f32;
191
192    #[inline]
193    fn fill(value: f32) -> Self {
194        Self([value; 2])
195    }
196
197    #[inline]
198    fn basis() -> Vec<Self> {
199        vec![PointN([1.0, 0.0]), PointN([0.0, 1.0])]
200    }
201
202    #[inline]
203    fn volume(self) -> <Self as Point>::Scalar {
204        self.x() * self.y()
205    }
206}
207
208impl<T> ConstZero for Point2<T>
209where
210    T: ConstZero,
211{
212    const ZERO: Self = PointN([T::ZERO; 2]);
213}
214
215impl<T> Ones for Point2<T>
216where
217    T: ConstOne,
218{
219    const ONES: Self = PointN([T::ONE; 2]);
220}
221
222impl<T> Distance for Point2<T>
223where
224    T: Copy + Signed + Add<Output = T> + Pow<u16, Output = T>,
225    Point2<T>: Point<Scalar = T>,
226{
227    #[inline]
228    fn l1_distance(self, other: Self) -> T {
229        let diff = self - other;
230
231        diff.x().abs() + diff.y().abs()
232    }
233
234    #[inline]
235    fn l2_distance_squared(self, other: Self) -> T {
236        let diff = self - other;
237
238        diff.x().pow(2) + diff.y().pow(2)
239    }
240}
241
242impl Norm for Point2i {
243    #[inline]
244    fn norm_squared(self) -> f32 {
245        self.dot(self) as f32
246    }
247}
248
249impl Norm for Point2f {
250    #[inline]
251    fn norm_squared(self) -> f32 {
252        self.dot(self)
253    }
254}
255
256impl<T> DotProduct for Point2<T>
257where
258    T: Copy + Add<Output = T> + Mul<Output = T>,
259{
260    type Scalar = T;
261
262    #[inline]
263    fn dot(self, other: Self) -> Self::Scalar {
264        self.x() * other.x() + self.y() * other.y()
265    }
266}
267
268impl IntegerPoint<[i32; 2]> for Point2i {
269    #[inline]
270    fn dimensions_are_powers_of_2(self) -> bool {
271        self.x().is_positive()
272            && self.y().is_positive()
273            && (self.x() as u32).is_power_of_two()
274            && (self.y() as u32).is_power_of_two()
275    }
276
277    #[inline]
278    fn is_cube(self) -> bool {
279        self.x() == self.y()
280    }
281}
282
283impl Neighborhoods for Point2i {
284    #[inline]
285    fn corner_offsets() -> Vec<Self> {
286        Self::SQUARE_CORNER_OFFSETS.to_vec()
287    }
288
289    #[inline]
290    fn von_neumann_offsets() -> Vec<Self> {
291        Self::VON_NEUMANN_OFFSETS.to_vec()
292    }
293
294    #[inline]
295    fn moore_offsets() -> Vec<Self> {
296        Self::MOORE_OFFSETS.to_vec()
297    }
298}
299
300/// An iterator over all points in an `Extent2<T>`.
301pub struct Extent2PointIter<T>
302where
303    Range<T>: Iterator<Item = T>,
304{
305    product_iter: Product<Range<T>, Range<T>>,
306}
307
308impl<T> Iterator for Extent2PointIter<T>
309where
310    T: Clone,
311    Range<T>: Iterator<Item = T>,
312{
313    type Item = Point2<T>;
314
315    #[inline]
316    fn next(&mut self) -> Option<Self::Item> {
317        self.product_iter.next().map(|(y, x)| PointN([x, y]))
318    }
319}
320
321impl IterExtent<[i32; 2]> for Point2i {
322    type PointIter = Extent2PointIter<i32>;
323
324    #[inline]
325    fn iter_extent(min: Point2i, lub: Point2i) -> Self::PointIter {
326        Extent2PointIter {
327            // iproduct is opposite of row-major order.
328            product_iter: iproduct!(min.y()..lub.y(), min.x()..lub.x()),
329        }
330    }
331}
332
333// This particular partial order allows us to say that an `Extent2i` e contains a `Point2i` p iff p
334// is GEQ the minimum of e and p is LEQ the maximum of e.
335impl<T> PartialOrd for Point2<T>
336where
337    T: Copy + PartialOrd,
338{
339    #[inline]
340    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
341        if self < other {
342            Some(Ordering::Less)
343        } else if self > other {
344            Some(Ordering::Greater)
345        } else if self.x() == other.x() && self.y() == other.y() {
346            Some(Ordering::Equal)
347        } else {
348            None
349        }
350    }
351
352    #[inline]
353    fn lt(&self, other: &Self) -> bool {
354        self.x() < other.x() && self.y() < other.y()
355    }
356
357    #[inline]
358    fn gt(&self, other: &Self) -> bool {
359        self.x() > other.x() && self.y() > other.y()
360    }
361
362    #[inline]
363    fn le(&self, other: &Self) -> bool {
364        self.x() <= other.x() && self.y() <= other.y()
365    }
366
367    #[inline]
368    fn ge(&self, other: &Self) -> bool {
369        self.x() >= other.x() && self.y() >= other.y()
370    }
371}
372
373impl From<Point2i> for Point2f {
374    #[inline]
375    fn from(p: Point2i) -> Self {
376        PointN([p.x() as f32, p.y() as f32])
377    }
378}
379
380impl_unary_ops!(Point2f, f32);
381impl_unary_ops!(Point2i, i32);
382
383impl_binary_ops!(Point2i, i32);
384impl_binary_ops!(Point2f, f32);
385
386impl_unary_integer_ops!(Point2i, i32);
387
388impl_binary_integer_ops!(Point2i);
389
390impl_float_div!(Point2f, f32);
391impl_integer_div!(Point2i, i32);