1 use fpnum::{distance, FPNum, FPPoint, fp}; |
1 use fpnum::{distance, fp, FPNum, FPPoint}; |
2 use std::{ |
2 use std::{ |
3 cmp::{max, min}, |
3 cmp::{max, min}, |
4 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}, |
4 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}, |
5 }; |
5 }; |
6 |
6 |
9 pub x: i32, |
9 pub x: i32, |
10 pub y: i32, |
10 pub y: i32, |
11 } |
11 } |
12 |
12 |
13 impl Point { |
13 impl Point { |
14 #[inline] |
14 pub const ZERO: Self = Self::new(0, 0); |
15 pub fn new(x: i32, y: i32) -> Self { |
15 |
|
16 #[inline] |
|
17 pub const fn new(x: i32, y: i32) -> Self { |
16 Self { x, y } |
18 Self { x, y } |
17 } |
19 } |
18 |
20 |
19 #[inline] |
21 #[inline] |
20 pub fn diag(v: i32) -> Self { |
22 pub const fn diag(v: i32) -> Self { |
21 Self::new(v, v) |
23 Self::new(v, v) |
22 } |
|
23 |
|
24 #[inline] |
|
25 pub fn zero() -> Self { |
|
26 Self::new(0, 0) |
|
27 } |
24 } |
28 |
25 |
29 #[inline] |
26 #[inline] |
30 pub fn signum(self) -> Self { |
27 pub fn signum(self) -> Self { |
31 Self::new(self.x.signum(), self.y.signum()) |
28 Self::new(self.x.signum(), self.y.signum()) |
35 pub fn abs(self) -> Self { |
32 pub fn abs(self) -> Self { |
36 Self::new(self.x.abs(), self.y.abs()) |
33 Self::new(self.x.abs(), self.y.abs()) |
37 } |
34 } |
38 |
35 |
39 #[inline] |
36 #[inline] |
40 pub fn dot(self, other: Point) -> i32 { |
37 pub const fn dot(self, other: Point) -> i32 { |
41 self.x * other.x + self.y * other.y |
38 self.x * other.x + self.y * other.y |
42 } |
39 } |
43 |
40 |
44 #[inline] |
41 #[inline] |
45 pub fn max_norm(self) -> i32 { |
42 pub fn max_norm(self) -> i32 { |
50 pub fn integral_norm(self) -> u32 { |
47 pub fn integral_norm(self) -> u32 { |
51 distance(self.x, self.y).abs_round() |
48 distance(self.x, self.y).abs_round() |
52 } |
49 } |
53 |
50 |
54 #[inline] |
51 #[inline] |
55 pub fn transform(self, matrix: &[i32; 4]) -> Self { |
52 pub const fn transform(self, matrix: &[i32; 4]) -> Self { |
56 Point::new( |
53 Point::new( |
57 matrix[0] * self.x + matrix[1] * self.y, |
54 matrix[0] * self.x + matrix[1] * self.y, |
58 matrix[2] * self.x + matrix[3] * self.y, |
55 matrix[2] * self.x + matrix[3] * self.y, |
59 ) |
56 ) |
60 } |
57 } |
61 |
58 |
62 #[inline] |
59 #[inline] |
63 pub fn rotate90(self) -> Self { |
60 pub const fn rotate90(self) -> Self { |
64 Point::new(self.y, -self.x) |
61 Point::new(self.y, -self.x) |
65 } |
62 } |
66 |
63 |
67 #[inline] |
64 #[inline] |
68 pub fn cross(self, other: Point) -> i32 { |
65 pub const fn cross(self, other: Point) -> i32 { |
69 self.dot(other.rotate90()) |
66 self.dot(other.rotate90()) |
70 } |
67 } |
71 |
68 |
72 #[inline] |
69 #[inline] |
73 pub fn clamp(self, rect: &Rect) -> Point { |
70 pub fn clamp(self, rect: &Rect) -> Point { |
74 Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y)) |
71 Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y)) |
75 } |
72 } |
76 |
73 |
77 #[inline] |
74 #[inline] |
78 pub fn line_to(self, end: Point) -> Line { |
75 pub const fn line_to(self, end: Point) -> Line { |
79 Line::new(self, end) |
76 Line::new(self, end) |
80 } |
77 } |
81 |
78 |
82 #[inline] |
79 #[inline] |
83 pub fn ray_with_dir(self, direction: Point) -> Ray { |
80 pub const fn ray_with_dir(self, direction: Point) -> Ray { |
84 Ray::new(self, direction) |
81 Ray::new(self, direction) |
85 } |
82 } |
86 |
83 |
87 #[inline] |
84 #[inline] |
88 pub fn tangent_mul(self, x: i32) -> i32 { |
85 pub const fn tangent_mul(self, x: i32) -> i32 { |
89 x * self.y / self.x |
86 x * self.y / self.x |
90 } |
87 } |
91 |
88 |
92 #[inline] |
89 #[inline] |
93 pub fn cotangent_mul(self, y: i32) -> i32 { |
90 pub const fn cotangent_mul(self, y: i32) -> i32 { |
94 y * self.x / self.y |
91 y * self.x / self.y |
95 } |
92 } |
96 |
93 |
97 #[inline] |
94 #[inline] |
98 pub fn to_fppoint(self) -> FPPoint { |
95 pub fn to_fppoint(self) -> FPPoint { |
111 pub height: usize, |
108 pub height: usize, |
112 } |
109 } |
113 |
110 |
114 impl Size { |
111 impl Size { |
115 #[inline] |
112 #[inline] |
116 pub fn new(width: usize, height: usize) -> Self { |
113 pub const fn new(width: usize, height: usize) -> Self { |
117 Size { width, height } |
114 Self { width, height } |
118 } |
115 } |
119 |
116 |
120 #[inline] |
117 #[inline] |
121 pub fn square(size: usize) -> Self { |
118 pub const fn square(size: usize) -> Self { |
122 Size { |
119 Self { |
123 width: size, |
120 width: size, |
124 height: size, |
121 height: size, |
125 } |
122 } |
126 } |
123 } |
127 |
124 |
128 #[inline] |
125 #[inline] |
129 pub fn area(&self) -> usize { |
126 pub const fn area(&self) -> usize { |
130 self.width * self.height |
127 self.width * self.height |
131 } |
128 } |
132 |
129 |
133 #[inline] |
130 #[inline] |
134 pub fn linear_index(&self, x: usize, y: usize) -> usize { |
131 pub const fn linear_index(&self, x: usize, y: usize) -> usize { |
135 y * self.width + x |
132 y * self.width + x |
136 } |
133 } |
137 |
134 |
138 #[inline] |
135 #[inline] |
139 pub fn is_power_of_two(&self) -> bool { |
136 pub fn is_power_of_two(&self) -> bool { |
147 height: self.height.next_power_of_two(), |
144 height: self.height.next_power_of_two(), |
148 } |
145 } |
149 } |
146 } |
150 |
147 |
151 #[inline] |
148 #[inline] |
152 pub fn transpose(&self) -> Self { |
149 pub const fn transpose(&self) -> Self { |
153 Self::new(self.height, self.width) |
150 Self::new(self.height, self.width) |
154 } |
151 } |
155 |
152 |
156 #[inline] |
153 #[inline] |
157 pub fn to_mask(&self) -> SizeMask { |
154 pub fn to_mask(&self) -> SizeMask { |
158 SizeMask::new(*self) |
155 SizeMask::new(*self) |
159 } |
156 } |
160 |
157 |
161 #[inline] |
158 #[inline] |
162 pub fn to_square(&self) -> Size { |
159 pub fn to_square(&self) -> Self { |
163 Size::square(max(self.width, self.height)) |
160 Self::square(max(self.width, self.height)) |
164 } |
161 } |
165 |
162 |
166 pub fn to_grid_index(&self) -> GridIndex { |
163 pub fn to_grid_index(&self) -> GridIndex { |
167 GridIndex::new(*self) |
164 GridIndex::new(*self) |
168 } |
165 } |
329 pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self { |
326 pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self { |
330 Self::from_size(Point::new(x, y), Size::new(width, height)) |
327 Self::from_size(Point::new(x, y), Size::new(width, height)) |
331 } |
328 } |
332 |
329 |
333 pub fn at_origin(size: Size) -> Self { |
330 pub fn at_origin(size: Size) -> Self { |
334 Self::from_size(Point::zero(), size) |
331 Self::from_size(Point::ZERO, size) |
335 } |
332 } |
336 |
333 |
337 #[inline] |
334 #[inline] |
338 pub fn width(&self) -> usize { |
335 pub const fn width(&self) -> usize { |
339 (self.right() - self.left() + 1) as usize |
336 (self.right() - self.left() + 1) as usize |
340 } |
337 } |
341 |
338 |
342 #[inline] |
339 #[inline] |
343 pub fn height(&self) -> usize { |
340 pub const fn height(&self) -> usize { |
344 (self.bottom() - self.top() + 1) as usize |
341 (self.bottom() - self.top() + 1) as usize |
345 } |
342 } |
346 |
343 |
347 #[inline] |
344 #[inline] |
348 pub fn size(&self) -> Size { |
345 pub const fn size(&self) -> Size { |
349 Size::new(self.width(), self.height()) |
346 Size::new(self.width(), self.height()) |
350 } |
347 } |
351 |
348 |
352 #[inline] |
349 #[inline] |
353 pub fn area(&self) -> usize { |
350 pub const fn area(&self) -> usize { |
354 self.size().area() |
351 self.size().area() |
355 } |
352 } |
356 |
353 |
357 #[inline] |
354 #[inline] |
358 pub fn left(&self) -> i32 { |
355 pub const fn left(&self) -> i32 { |
359 self.top_left().x |
356 self.top_left().x |
360 } |
357 } |
361 |
358 |
362 #[inline] |
359 #[inline] |
363 pub fn top(&self) -> i32 { |
360 pub const fn top(&self) -> i32 { |
364 self.top_left().y |
361 self.top_left().y |
365 } |
362 } |
366 |
363 |
367 #[inline] |
364 #[inline] |
368 pub fn right(&self) -> i32 { |
365 pub const fn right(&self) -> i32 { |
369 self.bottom_right().x |
366 self.bottom_right().x |
370 } |
367 } |
371 |
368 |
372 #[inline] |
369 #[inline] |
373 pub fn bottom(&self) -> i32 { |
370 pub const fn bottom(&self) -> i32 { |
374 self.bottom_right().y |
371 self.bottom_right().y |
375 } |
372 } |
376 |
373 |
377 #[inline] |
374 #[inline] |
378 pub fn top_left(&self) -> Point { |
375 pub const fn top_left(&self) -> Point { |
379 self.top_left |
376 self.top_left |
380 } |
377 } |
381 |
378 |
382 #[inline] |
379 #[inline] |
383 pub fn bottom_right(&self) -> Point { |
380 pub const fn bottom_right(&self) -> Point { |
384 self.bottom_right |
381 self.bottom_right |
385 } |
382 } |
386 |
383 |
387 #[inline] |
384 #[inline] |
388 pub fn center(&self) -> Point { |
385 pub fn center(&self) -> Point { |
627 pub direction: Point, |
624 pub direction: Point, |
628 } |
625 } |
629 |
626 |
630 impl Ray { |
627 impl Ray { |
631 #[inline] |
628 #[inline] |
632 pub fn new(start: Point, direction: Point) -> Ray { |
629 pub const fn new(start: Point, direction: Point) -> Ray { |
633 Self { start, direction } |
630 Self { start, direction } |
634 } |
631 } |
635 |
632 |
636 #[inline] |
633 #[inline] |
637 pub fn tangent_mul(&self, x: i32) -> i32 { |
634 pub const fn tangent_mul(&self, x: i32) -> i32 { |
638 self.direction.tangent_mul(x) |
635 self.direction.tangent_mul(x) |
639 } |
636 } |
640 |
637 |
641 #[inline] |
638 #[inline] |
642 pub fn cotangent_mul(&self, y: i32) -> i32 { |
639 pub const fn cotangent_mul(&self, y: i32) -> i32 { |
643 self.direction.cotangent_mul(y) |
640 self.direction.cotangent_mul(y) |
644 } |
641 } |
645 |
642 |
646 #[inline] |
643 #[inline] |
647 pub fn orientation(&self, point: Point) -> i32 { |
644 pub fn orientation(&self, point: Point) -> i32 { |
654 pub start: Point, |
651 pub start: Point, |
655 pub end: Point, |
652 pub end: Point, |
656 } |
653 } |
657 |
654 |
658 impl Line { |
655 impl Line { |
659 #[inline] |
656 pub const ZERO: Self = Self::new(Point::ZERO, Point::ZERO); |
660 pub fn new(start: Point, end: Point) -> Self { |
657 |
|
658 #[inline] |
|
659 pub const fn new(start: Point, end: Point) -> Self { |
661 Self { start, end } |
660 Self { start, end } |
662 } |
|
663 |
|
664 #[inline] |
|
665 pub fn zero() -> Self { |
|
666 Self::new(Point::zero(), Point::zero()) |
|
667 } |
661 } |
668 |
662 |
669 #[inline] |
663 #[inline] |
670 pub fn center(&self) -> Point { |
664 pub fn center(&self) -> Point { |
671 (self.start + self.end) / 2 |
665 (self.start + self.end) / 2 |
708 impl LinePoints { |
702 impl LinePoints { |
709 pub fn new(line: Line) -> Self { |
703 pub fn new(line: Line) -> Self { |
710 let dir = line.end - line.start; |
704 let dir = line.end - line.start; |
711 |
705 |
712 Self { |
706 Self { |
713 accumulator: Point::zero(), |
707 accumulator: Point::ZERO, |
714 direction: dir.abs(), |
708 direction: dir.abs(), |
715 sign: dir.signum(), |
709 sign: dir.signum(), |
716 current: line.start, |
710 current: line.start, |
717 total_steps: dir.max_norm(), |
711 total_steps: dir.max_norm(), |
718 step: 0, |
712 step: 0, |