| 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 | |