1use derive_more::derive::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
4use rand::{
5 distr::{
6 StandardUniform,
7 uniform::{SampleRange, SampleUniform},
8 },
9 prelude::*,
10};
11use std::{
12 cmp::Ordering,
13 num::NonZeroU16,
14 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
15};
16
17#[derive(
20 Copy,
21 Clone,
22 PartialEq,
23 Eq,
24 PartialOrd,
25 Ord,
26 AddAssign,
27 Add,
28 Mul,
29 MulAssign,
30 Sub,
31 SubAssign,
32 Div,
33 DivAssign,
34 Default,
35)]
36#[mul(forward)]
37#[div(forward)]
38#[mul_assign(forward)]
39#[div_assign(forward)]
40pub struct Point2d<T = i64> {
41 pub x: T,
43 pub y: T,
45}
46
47#[derive(PartialEq, Debug, Copy, Clone)]
49pub struct Line<T = i64> {
50 pub start: Point2d<T>,
52 pub end: Point2d<T>,
54}
55
56impl Line {
57 pub fn get_intersection(self, other: Self) -> Option<Point2d> {
60 let s10 = self.end - self.start;
61 let s32 = other.end - other.start;
62
63 let denom = s10.x * s32.y - s32.x * s10.y;
64 if denom == 0 {
65 return None; }
67 let denom_positive = denom > 0;
68
69 let s02 = self.start - other.start;
70 let s_numer = s10.x * s02.y - s10.y * s02.x;
71 if (s_numer < 0) == denom_positive {
72 return None; }
74 let t_numer = s32.x * s02.y - s32.y * s02.x;
75 if (t_numer < 0) == denom_positive {
76 return None; }
78 if (s_numer > denom) == denom_positive || (t_numer > denom) == denom_positive {
79 return None; }
81 let t = t_numer / denom;
83
84 Some(self.start + s10 * t)
85 }
86
87 pub fn bounds(&self) -> Bounds {
89 Bounds {
90 min: self.start,
91 max: self.end,
92 }
93 }
94
95 pub fn with_manhattan_length(self, len: i64) -> Self {
97 assert!(len > 0);
98 let dir = self.end - self.start;
99 let old_len = dir.x.abs() + dir.y.abs();
100 let new_dir = dir * len / old_len;
101 Self {
102 start: self.start,
103 end: self.start + new_dir,
104 }
105 }
106
107 pub fn flip(self) -> Self {
109 Self {
110 start: self.end,
111 end: self.start,
112 }
113 }
114
115 pub fn len_squared(&self) -> i64 {
117 (self.end - self.start).len_squared()
118 }
119}
120
121impl<T: Num> Line<T> {
122 pub fn iter_all_touched_pixels(mut self, mut pnt: impl FnMut(Point2d<T>)) {
124 let mut k = Point2d::splat(T::ZERO);
126 self.end -= self.start;
127
128 match self.end.x.cmp(&T::ZERO) {
130 Ordering::Greater => k.x = T::ONE,
131 Ordering::Equal => {}
132 Ordering::Less => {
133 k.x = -T::ONE;
134 self.end.x = -self.end.x;
135 }
136 }
137 self.end.x += T::ONE;
138
139 match self.end.y.cmp(&T::ZERO) {
141 Ordering::Less => k.y = T::ONE,
142 Ordering::Equal => {}
143 Ordering::Greater => {
144 k.y = -T::ONE;
145 self.end.y = -self.end.y;
146 }
147 }
148 self.end.y += T::ONE;
149
150 let flip = self.end.x >= self.end.y;
152 if flip {
153 self.end = self.end.flip();
154 self.start = self.start.flip();
155 k = k.flip();
156 }
157 let mut pnt = |p: Point2d<T>| if flip { pnt(p.flip()) } else { pnt(p) };
158
159 let mut c = self.end.y;
160 for i in T::iter_range(T::ZERO..self.end.y) {
161 pnt(self.start); c -= self.end.x;
163 if c <= T::ZERO {
164 if i != self.end.y - T::ONE {
165 pnt(self.start + Point2d::new(T::ZERO, k.y));
166 }
167 c += self.end.y;
168 self.start.x += k.x;
169 if i != self.end.y - T::ONE {
170 pnt(self.start);
171 }
172 }
173 self.start.y += k.y
174 }
175 }
176}
177
178impl<T: std::fmt::Debug> std::fmt::Debug for Point2d<T> {
179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 (&self.x, &self.y).fmt(f)
181 }
182}
183
184impl<T> Distribution<Point2d<T>> for StandardUniform
185where
186 StandardUniform: Distribution<T>,
187{
188 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point2d<T> {
189 Point2d {
190 x: self.sample(rng),
191 y: self.sample(rng),
192 }
193 }
194}
195
196impl<T: Copy> Point2d<T> {
197 pub const fn splat(arg: T) -> Self {
199 Self::new(arg, arg)
200 }
201
202 pub const fn new(x: T, y: T) -> Self {
204 Self { x, y }
205 }
206
207 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Point2d<U> {
209 Point2d {
210 x: f(self.x),
211 y: f(self.y),
212 }
213 }
214
215 pub fn to(self, other: Self) -> Line<T> {
217 Line {
218 start: self,
219 end: other,
220 }
221 }
222
223 fn flip(self) -> Point2d<T> {
224 Point2d {
225 x: self.y,
226 y: self.x,
227 }
228 }
229}
230
231impl<T: Neg<Output = T>> Point2d<T> {
232 pub fn perp(self) -> Self {
234 Self {
235 x: -self.y,
236 y: self.x,
237 }
238 }
239}
240
241pub trait Abs {
243 fn abs(self) -> Self;
246}
247
248impl Abs for i64 {
249 fn abs(self) -> Self {
250 i64::abs(self)
251 }
252}
253
254impl<T: Copy + Sub<Output = T> + Mul<Output = T> + Add<Output = T> + Abs> Point2d<T> {
255 pub fn dist_squared(self, center: Point2d<T>) -> T {
257 (self - center).len_squared()
258 }
259
260 pub fn len_squared(self) -> T {
262 let Self { x, y } = self;
263 x * x + y * y
264 }
265
266 pub fn manhattan_dist(self, city: Point2d<T>) -> T {
268 let diff = city - self;
269 diff.manhattan_len()
270 }
271
272 pub fn manhattan_len(&self) -> T {
274 self.x.abs() + self.y.abs()
275 }
276}
277
278impl From<Point2d<NonZeroU16>> for Point2d {
279 fn from(value: Point2d<NonZeroU16>) -> Self {
280 Self {
281 x: value.x.get().into(),
282 y: value.y.get().into(),
283 }
284 }
285}
286
287impl Point2d<i64> {
288 pub const fn sub(mut self, rhs: Point2d) -> Point2d {
290 self.x -= rhs.x;
291 self.y -= rhs.y;
292 self
293 }
294
295 pub const fn mul(mut self, rhs: Point2d) -> Point2d {
297 self.x *= rhs.x;
298 self.y *= rhs.y;
299 self
300 }
301
302 pub fn to_ne_bytes(&self) -> [u8; 16] {
304 let mut array = [0; 16];
305 for (dest, src) in array
306 .iter_mut()
307 .zip(self.x.to_ne_bytes().into_iter().chain(self.y.to_ne_bytes()))
308 {
309 *dest = src;
310 }
311 array
312 }
313}
314
315impl<T: DivAssign + Copy> Div<T> for Point2d<T> {
316 type Output = Self;
317 fn div(mut self, rhs: T) -> Self::Output {
318 self /= rhs;
319 self
320 }
321}
322
323impl<T: DivAssign + Copy> DivAssign<T> for Point2d<T> {
324 fn div_assign(&mut self, rhs: T) {
325 self.x /= rhs;
326 self.y /= rhs;
327 }
328}
329
330impl<T: MulAssign + Copy> Mul<T> for Point2d<T> {
331 type Output = Self;
332 fn mul(mut self, rhs: T) -> Self::Output {
333 self *= rhs;
334 self
335 }
336}
337
338impl<T: MulAssign + Copy> MulAssign<T> for Point2d<T> {
339 fn mul_assign(&mut self, rhs: T) {
340 self.x *= rhs;
341 self.y *= rhs;
342 }
343}
344
345#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
346pub struct Bounds<T = i64> {
348 pub min: Point2d<T>,
350 pub max: Point2d<T>,
352}
353
354impl<T: std::fmt::Debug> std::fmt::Debug for Bounds<T> {
355 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
356 write!(f, "{:?}..={:?}", self.min, self.max)
357 }
358}
359
360impl<T: Copy + PartialEq + PartialOrd + SampleUniform> Bounds<T> {
361 pub fn sample<R: RngCore + ?Sized>(self, rng: &mut R) -> Point2d<T> {
363 Point2d {
364 x: (self.min.x..self.max.x).sample_single(rng).unwrap(),
365 y: (self.min.y..self.max.y).sample_single(rng).unwrap(),
366 }
367 }
368
369 pub fn map<U>(&self, f: impl Fn(Point2d<T>) -> Point2d<U>) -> Bounds<U> {
371 Bounds {
372 min: f(self.min),
373 max: f(self.max),
374 }
375 }
376}
377
378impl<T: Copy> Bounds<T> {
379 pub fn point(point: Point2d<T>) -> Self {
381 Self {
382 min: point,
383 max: point,
384 }
385 }
386}
387
388impl<T: PartialOrd + Num + Copy + AddAssign> Bounds<T> {
389 pub fn iter(self) -> impl Iterator<Item = Point2d<T>> {
391 let mut current = self.min;
392 std::iter::from_fn(move || {
393 if current.y > self.max.y {
394 None
395 } else {
396 let item = current;
397 current.x += T::ONE;
398 if current.x > self.max.x {
399 current.x = self.min.x;
400 current.y += T::ONE;
401 }
402 Some(item)
403 }
404 })
405 }
406}
407
408impl<T: Copy + Num + Add<Output = T> + Sub<Output = T> + DivAssign<T>> Bounds<T> {
409 pub fn center(&self) -> Point2d<T> {
411 (self.max - self.min) / T::TWO + self.min
412 }
413}
414
415impl<T: Copy + Add<Output = T> + Sub<Output = T>> Bounds<T> {
416 pub fn pad(&self, padding: Point2d<T>) -> Self {
418 Self {
419 min: self.min - padding,
420 max: self.max + padding,
421 }
422 }
423}
424
425#[cfg(test)]
426#[test]
427fn iter() {
428 let grid = Bounds {
429 min: Point2d::new(10, 42),
430 max: Point2d::new(12, 43),
431 };
432 let mut iter = grid.iter();
433 assert_eq!(iter.next(), Some(grid.min));
434 assert_eq!(iter.next(), Some(Point2d::new(11, 42)));
435 assert_eq!(iter.next(), Some(Point2d::new(12, 42)));
436 assert_eq!(iter.next(), Some(Point2d::new(10, 43)));
437 assert_eq!(iter.next(), Some(Point2d::new(11, 43)));
438 assert_eq!(iter.next(), Some(Point2d::new(12, 43)));
439 assert_eq!(iter.next(), None);
440 assert_eq!(iter.next(), None);
441}
442
443#[cfg(test)]
444#[test]
445fn iter_point() {
446 let grid = Bounds::point(Point2d::new(10, 42));
447 let mut iter = grid.iter();
448 assert_eq!(iter.next(), Some(grid.min));
449 assert_eq!(iter.next(), None);
450 assert_eq!(iter.next(), None);
451}
452
453impl<T: DivAssign + Copy> Div<Point2d<T>> for Bounds<T> {
454 type Output = Self;
455 fn div(mut self, rhs: Point2d<T>) -> Self::Output {
456 self.min /= rhs;
457 self.max /= rhs;
458 self
459 }
460}
461
462pub trait Num:
464 Sized
465 + Copy
466 + AddAssign
467 + SubAssign
468 + Ord
469 + Sub<Output = Self>
470 + Neg<Output = Self>
471 + Eq
472 + Add<Output = Self>
473{
474 const ZERO: Self;
476 const ONE: Self;
478 const TWO: Self;
480 fn iter_range(range: std::ops::Range<Self>) -> impl Iterator<Item = Self>;
483 fn as_u64(self) -> u64;
486}
487
488impl Num for i64 {
489 const ZERO: i64 = 0;
490 const ONE: i64 = 1;
491 const TWO: i64 = 2;
492
493 fn iter_range(range: std::ops::Range<Self>) -> impl Iterator<Item = Self> {
494 range
495 }
496
497 fn as_u64(self) -> u64 {
498 self as u64
499 }
500}