building_blocks_core/point/
point2.rs1use 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
10pub type Point2<T> = PointN<[T; 2]>;
12pub type Point2i = PointN<[i32; 2]>;
14pub 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 #[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
300pub 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 product_iter: iproduct!(min.y()..lub.y(), min.x()..lub.x()),
329 }
330 }
331}
332
333impl<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);