1 | use std::{ |
2 | hash::{Hash, Hasher}, |
3 | ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign}, |
4 | }; |
5 | |
6 | use fnv::FnvHasher; |
7 | |
8 | #[derive (Copy, Clone, Debug, Default)] |
9 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
10 | pub struct Position { |
11 | pub x: f32, |
12 | pub y: f32, |
13 | } |
14 | |
15 | impl Add<Vector> for Position { |
16 | type Output = Self; |
17 | |
18 | #[inline ] |
19 | fn add(self, other: Vector) -> Self { |
20 | Self { |
21 | x: self.x + other.x, |
22 | y: self.y + other.y, |
23 | } |
24 | } |
25 | } |
26 | |
27 | impl Sub<Vector> for Position { |
28 | type Output = Self; |
29 | |
30 | #[inline ] |
31 | fn sub(self, other: Vector) -> Self { |
32 | Self { |
33 | x: self.x - other.x, |
34 | y: self.y - other.y, |
35 | } |
36 | } |
37 | } |
38 | |
39 | impl Sub for Position { |
40 | type Output = Vector; |
41 | |
42 | #[inline ] |
43 | fn sub(self, other: Self) -> Vector { |
44 | Vector { |
45 | x: self.x - other.x, |
46 | y: self.y - other.y, |
47 | } |
48 | } |
49 | } |
50 | |
51 | impl Position { |
52 | pub(crate) fn equals(p1: Self, p2: Self, tol: f32) -> bool { |
53 | (p2 - p1).mag2() < tol * tol |
54 | } |
55 | |
56 | pub(crate) fn segment_distance(pos: Self, ppos: Self, qpos: Self) -> f32 { |
57 | let pq: Vector = qpos - ppos; |
58 | let dpos: Vector = pos - ppos; |
59 | let d: f32 = pq.mag2(); |
60 | let mut t: f32 = pq.dot(dpos); |
61 | |
62 | if d > 0.0 { |
63 | t /= d; |
64 | } |
65 | |
66 | t = t.clamp(min:0.0, max:1.0); |
67 | |
68 | let dpos: Vector = (ppos - pos) + pq * t; |
69 | |
70 | dpos.mag2() |
71 | } |
72 | } |
73 | |
74 | #[derive (Copy, Clone, Debug, Default)] |
75 | pub struct Vector { |
76 | pub x: f32, |
77 | pub y: f32, |
78 | } |
79 | |
80 | impl Vector { |
81 | pub fn zero() -> Self { |
82 | Self { x: 0.0, y: 0.0 } |
83 | } |
84 | |
85 | pub fn x(x: f32) -> Self { |
86 | Self { x, y: 0.0 } |
87 | } |
88 | pub fn y(y: f32) -> Self { |
89 | Self { x: 0.0, y } |
90 | } |
91 | |
92 | pub fn with_basis(self, basis_x: Self, basis_y: Self) -> Self { |
93 | basis_x * self.x + basis_y * self.y |
94 | } |
95 | |
96 | pub fn cross(self, other: Self) -> f32 { |
97 | self.orthogonal().dot(other) |
98 | } |
99 | |
100 | #[inline ] |
101 | pub fn dot(self, other: Self) -> f32 { |
102 | self.x * other.x + self.y * other.y |
103 | } |
104 | |
105 | #[inline ] |
106 | pub fn mag2(self) -> f32 { |
107 | self.dot(self) |
108 | } |
109 | |
110 | #[inline ] |
111 | pub fn orthogonal(self) -> Self { |
112 | Self { x: self.y, y: -self.x } |
113 | } |
114 | |
115 | #[inline ] |
116 | pub fn from_angle(angle: f32) -> Self { |
117 | let (y, x) = angle.sin_cos(); |
118 | Self { x, y } |
119 | } |
120 | |
121 | #[inline ] |
122 | pub fn angle(&self) -> f32 { |
123 | self.y.atan2(self.x) |
124 | } |
125 | |
126 | pub fn normalize(&mut self) -> f32 { |
127 | let d = self.x.hypot(self.y); |
128 | |
129 | if d > 1e-6 { |
130 | let id = 1.0 / d; |
131 | self.x *= id; |
132 | self.y *= id; |
133 | } |
134 | |
135 | d |
136 | } |
137 | } |
138 | |
139 | impl Add for Vector { |
140 | type Output = Self; |
141 | |
142 | #[inline ] |
143 | fn add(self, other: Self) -> Self { |
144 | Self { |
145 | x: self.x + other.x, |
146 | y: self.y + other.y, |
147 | } |
148 | } |
149 | } |
150 | |
151 | impl Sub for Vector { |
152 | type Output = Self; |
153 | |
154 | #[inline ] |
155 | fn sub(self, other: Self) -> Self { |
156 | Self { |
157 | x: self.x - other.x, |
158 | y: self.y - other.y, |
159 | } |
160 | } |
161 | } |
162 | |
163 | impl Neg for Vector { |
164 | type Output = Self; |
165 | |
166 | #[inline ] |
167 | fn neg(self) -> Self { |
168 | Self { x: -self.x, y: -self.y } |
169 | } |
170 | } |
171 | |
172 | impl Mul<f32> for Vector { |
173 | type Output = Self; |
174 | |
175 | #[inline ] |
176 | fn mul(self, other: f32) -> Self { |
177 | Self { |
178 | x: self.x * other, |
179 | y: self.y * other, |
180 | } |
181 | } |
182 | } |
183 | |
184 | impl MulAssign<f32> for Vector { |
185 | #[inline ] |
186 | fn mul_assign(&mut self, other: f32) { |
187 | self.x *= other; |
188 | self.y *= other; |
189 | } |
190 | } |
191 | |
192 | pub fn quantize(a: f32, d: f32) -> f32 { |
193 | (a / d + 0.5).trunc() * d |
194 | } |
195 | |
196 | /// 2×3 matrix (2 rows, 3 columns) used for 2D linear transformations. It can represent transformations such as translation, rotation, or scaling. |
197 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
198 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
199 | pub struct Transform2D(pub [f32; 6]); |
200 | |
201 | impl Transform2D { |
202 | /// Creates an identity transformation with no translation, rotation, or scaling applied. |
203 | pub fn identity() -> Self { |
204 | Self([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]) |
205 | } |
206 | |
207 | /// Creates a new transformation matrix. |
208 | /// |
209 | /// The parameters are interpreted as matrix elements as follows: |
210 | /// [a c x] |
211 | /// [b d y] |
212 | /// [0 0 1] |
213 | pub fn new(a: f32, b: f32, c: f32, d: f32, x: f32, y: f32) -> Self { |
214 | Self([a, b, c, d, x, y]) |
215 | } |
216 | |
217 | /// Creates a translation transformation matrix. |
218 | pub fn translation(tx: f32, ty: f32) -> Self { |
219 | Self([1.0, 0.0, 0.0, 1.0, tx, ty]) |
220 | } |
221 | |
222 | /// Creates a rotation transformation matrix. |
223 | pub fn rotation(a: f32) -> Self { |
224 | let (sin, cos) = a.sin_cos(); |
225 | |
226 | Self([cos, sin, -sin, cos, 0.0, 0.0]) |
227 | } |
228 | |
229 | /// Creates a scaling transformation matrix. |
230 | pub fn scaling(sx: f32, sy: f32) -> Self { |
231 | Self([sx, 0.0, 0.0, sy, 0.0, 0.0]) |
232 | } |
233 | |
234 | /// Translates the matrix. |
235 | pub fn translate(&mut self, tx: f32, ty: f32) { |
236 | let Self([.., x, y]) = self; |
237 | |
238 | *x += tx; |
239 | *y += ty; |
240 | } |
241 | |
242 | /// Rotates the matrix. |
243 | pub fn rotate(&mut self, a: f32) { |
244 | let (sin, cos) = a.sin_cos(); |
245 | |
246 | let Self([a, b, c, d, x, y]) = self; |
247 | |
248 | [*a, *b] = [*a * cos - *b * sin, *a * sin + *b * cos]; |
249 | [*c, *d] = [*c * cos - *d * sin, *c * sin + *d * cos]; |
250 | [*x, *y] = [*x * cos - *y * sin, *x * sin + *y * cos]; |
251 | } |
252 | |
253 | /// Scales the matrix. |
254 | pub fn scale(&mut self, sx: f32, sy: f32) { |
255 | let Self([a, b, c, d, x, y]) = self; |
256 | |
257 | *a *= sx; |
258 | *b *= sy; |
259 | *c *= sx; |
260 | *d *= sy; |
261 | *x *= sx; |
262 | *y *= sy; |
263 | } |
264 | |
265 | /// Skews the matrix horizontally. |
266 | pub fn skew_x(&mut self, a: f32) { |
267 | let tan = a.tan(); |
268 | |
269 | let Self([a, b, c, d, x, y]) = self; |
270 | |
271 | *a += *b * tan; |
272 | *c += *d * tan; |
273 | *x += *y * tan; |
274 | } |
275 | |
276 | /// Skews the matrix vertically. |
277 | pub fn skew_y(&mut self, a: f32) { |
278 | let tan = a.tan(); |
279 | |
280 | let Self([a, b, c, d, x, y]) = self; |
281 | |
282 | *b += *a * tan; |
283 | *d += *c * tan; |
284 | *y += *x * tan; |
285 | } |
286 | |
287 | /// Premultiplies the current transformation matrix with another matrix. |
288 | #[inline ] |
289 | pub fn premultiply(&mut self, other: &Self) { |
290 | *self = *other * *self; |
291 | } |
292 | |
293 | /// Inverts the current transformation matrix. |
294 | #[inline ] |
295 | pub fn invert(&mut self) { |
296 | *self = self.inverse() |
297 | } |
298 | |
299 | /// Returns the inverse of the current transformation matrix. |
300 | pub fn inverse(&self) -> Self { |
301 | let &Self([a, b, c, d, x, y]) = self; |
302 | let [a, b, c, d, x, y] = [a as f64, b as f64, c as f64, d as f64, x as f64, y as f64]; |
303 | |
304 | let det = a * d - c * b; |
305 | |
306 | if det > -1e-6 && det < 1e-6 { |
307 | return Self::identity(); |
308 | } |
309 | |
310 | let invdet = 1.0 / det; |
311 | |
312 | Self([ |
313 | (d * invdet) as f32, |
314 | (-b * invdet) as f32, |
315 | (-c * invdet) as f32, |
316 | (a * invdet) as f32, |
317 | ((c * y - d * x) * invdet) as f32, |
318 | ((b * x - a * y) * invdet) as f32, |
319 | ]) |
320 | } |
321 | |
322 | /// Transforms a point using the current transformation matrix. |
323 | pub fn transform_point(&self, sx: f32, sy: f32) -> (f32, f32) { |
324 | let &Self([a, b, c, d, x, y]) = self; |
325 | |
326 | let dx = sx * a + sy * c + x; |
327 | let dy = sx * b + sy * d + y; |
328 | (dx, dy) |
329 | } |
330 | |
331 | /// Calculates the average scale factor of the current transformation matrix. |
332 | pub fn average_scale(&self) -> f32 { |
333 | let &Self([a, b, c, d, ..]) = self; |
334 | |
335 | let sx = a.hypot(c); |
336 | let sy = b.hypot(d); |
337 | |
338 | (sx + sy) * 0.5 |
339 | } |
340 | |
341 | /// Converts the current transformation matrix to a 3×4 matrix format. |
342 | pub fn to_mat3x4(self) -> [f32; 12] { |
343 | let Self([a, b, c, d, x, y]) = self; |
344 | [a, b, 0.0, 0.0, c, d, 0.0, 0.0, x, y, 1.0, 0.0] |
345 | } |
346 | |
347 | /// Generates a cache key for the current transformation matrix. |
348 | pub fn cache_key(&self) -> u64 { |
349 | let mut hasher = FnvHasher::default(); |
350 | |
351 | for i in 0..6 { |
352 | self.0[i].to_bits().hash(&mut hasher); |
353 | } |
354 | |
355 | hasher.finish() |
356 | } |
357 | } |
358 | |
359 | impl Default for Transform2D { |
360 | fn default() -> Self { |
361 | Self::identity() |
362 | } |
363 | } |
364 | |
365 | impl Index<usize> for Transform2D { |
366 | type Output = f32; |
367 | |
368 | fn index(&self, index: usize) -> &Self::Output { |
369 | &self.0[index] |
370 | } |
371 | } |
372 | |
373 | impl IndexMut<usize> for Transform2D { |
374 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
375 | &mut self.0[index] |
376 | } |
377 | } |
378 | |
379 | impl Add for Transform2D { |
380 | type Output = Self; |
381 | |
382 | fn add(self, other: Self) -> Self::Output { |
383 | let Self([a0: f32, b0: f32, c0: f32, d0: f32, x0: f32, y0: f32]) = self; |
384 | let Self([a1: f32, b1: f32, c1: f32, d1: f32, x1: f32, y1: f32]) = other; |
385 | |
386 | Self([a0 + a1, b0 + b1, c0 + c1, d0 + d1, x0 + x1, y0 + y1]) |
387 | } |
388 | } |
389 | |
390 | impl AddAssign for Transform2D { |
391 | #[inline ] |
392 | fn add_assign(&mut self, other: Self) { |
393 | *self = *self + other; |
394 | } |
395 | } |
396 | |
397 | impl Sub for Transform2D { |
398 | type Output = Self; |
399 | |
400 | fn sub(self, other: Self) -> Self::Output { |
401 | let Self([a0: f32, b0: f32, c0: f32, d0: f32, x0: f32, y0: f32]) = self; |
402 | let Self([a1: f32, b1: f32, c1: f32, d1: f32, x1: f32, y1: f32]) = other; |
403 | |
404 | Self([a0 - a1, b0 - b1, c0 - c1, d0 - d1, x0 - x1, y0 - y1]) |
405 | } |
406 | } |
407 | |
408 | impl SubAssign for Transform2D { |
409 | #[inline ] |
410 | fn sub_assign(&mut self, other: Self) { |
411 | *self = *self - other; |
412 | } |
413 | } |
414 | |
415 | impl Mul for Transform2D { |
416 | type Output = Self; |
417 | |
418 | #[inline ] |
419 | fn mul(mut self, other: Self) -> Self::Output { |
420 | self *= other; |
421 | self |
422 | } |
423 | } |
424 | |
425 | impl MulAssign for Transform2D { |
426 | fn mul_assign(&mut self, other: Self) { |
427 | let Self([a0: &mut f32, b0: &mut f32, c0: &mut f32, d0: &mut f32, x0: &mut f32, y0: &mut f32]) = self; |
428 | let Self([a1: f32, b1: f32, c1: f32, d1: f32, x1: f32, y1: f32]) = other; |
429 | |
430 | [*a0, *b0] = [*a0 * a1 + *b0 * c1, *a0 * b1 + *b0 * d1]; |
431 | [*c0, *d0] = [*c0 * a1 + *d0 * c1, *c0 * b1 + *d0 * d1]; |
432 | [*x0, *y0] = [*x0 * a1 + *y0 * c1 + x1, *x0 * b1 + *y0 * d1 + y1]; |
433 | } |
434 | } |
435 | |
436 | impl Div for Transform2D { |
437 | type Output = Self; |
438 | |
439 | fn div(self, other: Self) -> Self::Output { |
440 | self * other.inverse() |
441 | } |
442 | } |
443 | |
444 | impl DivAssign for Transform2D { |
445 | #[inline ] |
446 | fn div_assign(&mut self, other: Self) { |
447 | *self = *self / other; |
448 | } |
449 | } |
450 | |
451 | #[derive (Copy, Clone, Default, Debug, PartialEq, PartialOrd)] |
452 | pub struct Rect { |
453 | pub x: f32, |
454 | pub y: f32, |
455 | pub w: f32, |
456 | pub h: f32, |
457 | } |
458 | |
459 | impl Rect { |
460 | pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self { |
461 | Self { x, y, w, h } |
462 | } |
463 | |
464 | pub fn intersect(&self, other: Self) -> Self { |
465 | let minx = self.x.max(other.x); |
466 | let miny = self.y.max(other.y); |
467 | let maxx = (self.x + self.w).min(other.x + other.w); |
468 | let maxy = (self.y + self.h).min(other.y + other.h); |
469 | |
470 | Self::new(minx, miny, 0.0f32.max(maxx - minx), 0.0f32.max(maxy - miny)) |
471 | } |
472 | |
473 | pub fn contains_rect(&self, other: &Self) -> bool { |
474 | other.is_empty() |
475 | || (self.x <= other.x |
476 | && other.x + other.w <= self.x + self.w |
477 | && self.y <= other.y |
478 | && other.y + other.h <= self.y + self.h) |
479 | } |
480 | |
481 | pub fn intersection(&self, other: &Self) -> Option<Self> { |
482 | let x = self.x.max(other.x); |
483 | let y = self.y.max(other.y); |
484 | let w = (self.x + self.w).min(other.x + other.w) - x; |
485 | let h = (self.y + self.h).min(other.y + other.h) - y; |
486 | |
487 | let result = Self { x, y, w, h }; |
488 | if result.is_empty() { |
489 | None |
490 | } else { |
491 | Some(result) |
492 | } |
493 | } |
494 | |
495 | pub fn is_empty(&self) -> bool { |
496 | self.w <= 0. || self.h <= 0. |
497 | } |
498 | } |
499 | |
500 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
501 | pub struct Bounds { |
502 | pub minx: f32, |
503 | pub miny: f32, |
504 | pub maxx: f32, |
505 | pub maxy: f32, |
506 | } |
507 | |
508 | impl Default for Bounds { |
509 | fn default() -> Self { |
510 | Self { |
511 | minx: 1e6, |
512 | miny: 1e6, |
513 | maxx: -1e6, |
514 | maxy: -1e6, |
515 | } |
516 | } |
517 | } |
518 | |
519 | impl Bounds { |
520 | pub(crate) fn contains(&self, x: f32, y: f32) -> bool { |
521 | (self.minx..=self.maxx).contains(&x) && (self.miny..=self.maxy).contains(&y) |
522 | } |
523 | } |
524 | |