1 | use std::{ |
2 | hash::{Hash, Hasher}, |
3 | ops::{Add, Index, IndexMut, Mul, MulAssign, Neg, Sub}, |
4 | }; |
5 | |
6 | use fnv::FnvHasher; |
7 | |
8 | #[derive (Copy, Clone, Debug, Default)] |
9 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
10 | pub(crate) 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 = qpos - ppos; |
58 | let dpos = pos - ppos; |
59 | let d = pq.mag2(); |
60 | let mut t = pq.dot(dpos); |
61 | |
62 | if d > 0.0 { |
63 | t /= d; |
64 | } |
65 | |
66 | if t < 0.0 { |
67 | t = 0.0; |
68 | } else if t > 1.0 { |
69 | t = 1.0; |
70 | } |
71 | |
72 | let dpos = (ppos - pos) + pq * t; |
73 | |
74 | dpos.mag2() |
75 | } |
76 | } |
77 | |
78 | #[derive (Copy, Clone, Debug, Default)] |
79 | pub(crate) struct Vector { |
80 | pub x: f32, |
81 | pub y: f32, |
82 | } |
83 | |
84 | impl Vector { |
85 | pub fn zero() -> Self { |
86 | Self { x: 0.0, y: 0.0 } |
87 | } |
88 | |
89 | pub fn x(x: f32) -> Self { |
90 | Self { x, y: 0.0 } |
91 | } |
92 | pub fn y(y: f32) -> Self { |
93 | Self { x: 0.0, y } |
94 | } |
95 | |
96 | pub fn with_basis(self, basis_x: Self, basis_y: Self) -> Self { |
97 | basis_x * self.x + basis_y * self.y |
98 | } |
99 | |
100 | pub fn cross(self, other: Self) -> f32 { |
101 | self.orthogonal().dot(other) |
102 | } |
103 | |
104 | #[inline ] |
105 | pub fn dot(self, other: Self) -> f32 { |
106 | self.x * other.x + self.y * other.y |
107 | } |
108 | |
109 | #[inline ] |
110 | pub fn mag2(self) -> f32 { |
111 | self.dot(self) |
112 | } |
113 | |
114 | #[inline ] |
115 | pub fn orthogonal(self) -> Self { |
116 | Self { x: self.y, y: -self.x } |
117 | } |
118 | |
119 | #[inline ] |
120 | pub fn from_angle(angle: f32) -> Self { |
121 | let (y, x) = angle.sin_cos(); |
122 | Self { x, y } |
123 | } |
124 | |
125 | #[inline ] |
126 | pub fn angle(&self) -> f32 { |
127 | self.y.atan2(self.x) |
128 | } |
129 | |
130 | pub fn normalize(&mut self) -> f32 { |
131 | let d = (self.x * self.x + self.y * self.y).sqrt(); |
132 | |
133 | if d > 1e-6 { |
134 | let id = 1.0 / d; |
135 | self.x *= id; |
136 | self.y *= id; |
137 | } |
138 | |
139 | d |
140 | } |
141 | } |
142 | |
143 | impl Add for Vector { |
144 | type Output = Self; |
145 | |
146 | #[inline ] |
147 | fn add(self, other: Self) -> Self { |
148 | Self { |
149 | x: self.x + other.x, |
150 | y: self.y + other.y, |
151 | } |
152 | } |
153 | } |
154 | |
155 | impl Sub for Vector { |
156 | type Output = Self; |
157 | |
158 | #[inline ] |
159 | fn sub(self, other: Self) -> Self { |
160 | Self { |
161 | x: self.x - other.x, |
162 | y: self.y - other.y, |
163 | } |
164 | } |
165 | } |
166 | |
167 | impl Neg for Vector { |
168 | type Output = Self; |
169 | |
170 | #[inline ] |
171 | fn neg(self) -> Self { |
172 | Self { x: -self.x, y: -self.y } |
173 | } |
174 | } |
175 | |
176 | impl Mul<f32> for Vector { |
177 | type Output = Self; |
178 | |
179 | #[inline ] |
180 | fn mul(self, other: f32) -> Self { |
181 | Self { |
182 | x: self.x * other, |
183 | y: self.y * other, |
184 | } |
185 | } |
186 | } |
187 | |
188 | impl MulAssign<f32> for Vector { |
189 | #[inline ] |
190 | fn mul_assign(&mut self, other: f32) { |
191 | self.x *= other; |
192 | self.y *= other; |
193 | } |
194 | } |
195 | |
196 | pub(crate) fn quantize(a: f32, d: f32) -> f32 { |
197 | (a / d + 0.5).trunc() * d |
198 | } |
199 | |
200 | /// 2×3 matrix (2 rows, 3 columns) used for 2D linear transformations. It can represent transformations such as translation, rotation, or scaling. |
201 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
202 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
203 | pub struct Transform2D(pub [f32; 6]); |
204 | |
205 | // TODO: Implement std::ops::* on this |
206 | impl Transform2D { |
207 | /// Creates an identity transformation with no translation, rotation or scaling applied. |
208 | pub fn identity() -> Self { |
209 | Self([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]) |
210 | } |
211 | |
212 | /// Creates a new transformation matrix. |
213 | /// |
214 | /// The parameters are interpreted as matrix as follows: |
215 | /// [a c e] |
216 | /// [b d f] |
217 | /// [0 0 1] |
218 | pub fn new(&mut self, a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> Self { |
219 | Self([a, b, c, d, e, f]) |
220 | } |
221 | |
222 | pub fn new_translation(x: f32, y: f32) -> Self { |
223 | let mut new = Self::identity(); |
224 | new.translate(x, y); |
225 | new |
226 | } |
227 | |
228 | pub fn translate(&mut self, tx: f32, ty: f32) { |
229 | // self[0] = 1.0; self[1] = 0.0; |
230 | // self[2] = 0.0; self[3] = 1.0; |
231 | self[4] = tx; |
232 | self[5] = ty; |
233 | } |
234 | |
235 | pub fn scale(&mut self, sx: f32, sy: f32) { |
236 | self[0] = sx; |
237 | self[1] = 0.0; |
238 | self[2] = 0.0; |
239 | self[3] = sy; |
240 | self[4] = 0.0; |
241 | self[5] = 0.0; |
242 | } |
243 | |
244 | pub fn rotate(&mut self, a: f32) { |
245 | let cs = a.cos(); |
246 | let sn = a.sin(); |
247 | |
248 | self[0] = cs; |
249 | self[1] = sn; |
250 | self[2] = -sn; |
251 | self[3] = cs; |
252 | self[4] = 0.0; |
253 | self[5] = 0.0; |
254 | } |
255 | |
256 | pub fn skew_x(&mut self, a: f32) { |
257 | self[0] = 1.0; |
258 | self[1] = 0.0; |
259 | self[2] = a.tan(); |
260 | self[3] = 1.0; |
261 | self[4] = 0.0; |
262 | self[5] = 0.0; |
263 | } |
264 | |
265 | pub fn skew_y(&mut self, a: f32) { |
266 | self[0] = 1.0; |
267 | self[1] = a.tan(); |
268 | self[2] = 0.0; |
269 | self[3] = 1.0; |
270 | self[4] = 0.0; |
271 | self[5] = 0.0; |
272 | } |
273 | |
274 | pub fn multiply(&mut self, other: &Self) { |
275 | let t0 = self[0] * other[0] + self[1] * other[2]; |
276 | let t2 = self[2] * other[0] + self[3] * other[2]; |
277 | let t4 = self[4] * other[0] + self[5] * other[2] + other[4]; |
278 | self[1] = self[0] * other[1] + self[1] * other[3]; |
279 | self[3] = self[2] * other[1] + self[3] * other[3]; |
280 | self[5] = self[4] * other[1] + self[5] * other[3] + other[5]; |
281 | self[0] = t0; |
282 | self[2] = t2; |
283 | self[4] = t4; |
284 | } |
285 | |
286 | pub fn premultiply(&mut self, other: &Self) { |
287 | let mut other = *other; |
288 | other.multiply(self); |
289 | *self = other; |
290 | } |
291 | |
292 | pub fn inverse(&mut self) { |
293 | let t = *self; |
294 | let det = t[0] as f64 * t[3] as f64 - t[2] as f64 * t[1] as f64; |
295 | |
296 | if det > -1e-6 && det < 1e-6 { |
297 | *self = Self::identity(); |
298 | } |
299 | |
300 | let invdet = 1.0 / det; |
301 | |
302 | self[0] = (t[3] as f64 * invdet) as f32; |
303 | self[2] = (-t[2] as f64 * invdet) as f32; |
304 | self[4] = ((t[2] as f64 * t[5] as f64 - t[3] as f64 * t[4] as f64) * invdet) as f32; |
305 | self[1] = (-t[1] as f64 * invdet) as f32; |
306 | self[3] = (t[0] as f64 * invdet) as f32; |
307 | self[5] = ((t[1] as f64 * t[4] as f64 - t[0] as f64 * t[5] as f64) * invdet) as f32; |
308 | } |
309 | |
310 | pub fn inversed(&self) -> Self { |
311 | let mut inv = *self; |
312 | inv.inverse(); |
313 | inv |
314 | } |
315 | |
316 | pub fn transform_point(&self, sx: f32, sy: f32) -> (f32, f32) { |
317 | let dx = sx * self[0] + sy * self[2] + self[4]; |
318 | let dy = sx * self[1] + sy * self[3] + self[5]; |
319 | (dx, dy) |
320 | } |
321 | |
322 | pub fn average_scale(&self) -> f32 { |
323 | let sx = (self[0] * self[0] + self[2] * self[2]).sqrt(); |
324 | let sy = (self[1] * self[1] + self[3] * self[3]).sqrt(); |
325 | |
326 | (sx + sy) * 0.5 |
327 | } |
328 | |
329 | pub fn to_mat3x4(self) -> [f32; 12] { |
330 | [ |
331 | self[0], self[1], 0.0, 0.0, self[2], self[3], 0.0, 0.0, self[4], self[5], 1.0, 0.0, |
332 | ] |
333 | } |
334 | |
335 | pub fn cache_key(&self) -> u64 { |
336 | let mut hasher = FnvHasher::default(); |
337 | |
338 | for i in 0..6 { |
339 | self.0[i].to_bits().hash(&mut hasher); |
340 | } |
341 | |
342 | hasher.finish() |
343 | } |
344 | } |
345 | |
346 | impl Default for Transform2D { |
347 | fn default() -> Self { |
348 | Self::identity() |
349 | } |
350 | } |
351 | |
352 | impl Index<usize> for Transform2D { |
353 | type Output = f32; |
354 | |
355 | fn index(&self, index: usize) -> &Self::Output { |
356 | &self.0[index] |
357 | } |
358 | } |
359 | |
360 | impl IndexMut<usize> for Transform2D { |
361 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
362 | &mut self.0[index] |
363 | } |
364 | } |
365 | |
366 | #[derive (Copy, Clone, Default, Debug, PartialEq, PartialOrd)] |
367 | pub struct Rect { |
368 | pub x: f32, |
369 | pub y: f32, |
370 | pub w: f32, |
371 | pub h: f32, |
372 | } |
373 | |
374 | impl Rect { |
375 | pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self { |
376 | Self { x, y, w, h } |
377 | } |
378 | |
379 | pub fn intersect(&self, other: Rect) -> Rect { |
380 | let minx = self.x.max(other.x); |
381 | let miny = self.y.max(other.y); |
382 | let maxx = (self.x + self.w).min(other.x + other.w); |
383 | let maxy = (self.y + self.h).min(other.y + other.h); |
384 | |
385 | Rect::new(minx, miny, 0.0f32.max(maxx - minx), 0.0f32.max(maxy - miny)) |
386 | } |
387 | |
388 | pub fn contains_rect(&self, other: &Rect) -> bool { |
389 | other.is_empty() |
390 | || (self.x <= other.x |
391 | && other.x + other.w <= self.x + self.w |
392 | && self.y <= other.y |
393 | && other.y + other.h <= self.y + self.h) |
394 | } |
395 | |
396 | pub fn intersection(&self, other: &Rect) -> Option<Self> { |
397 | let x = self.x.max(other.x); |
398 | let y = self.y.max(other.y); |
399 | let w = (self.x + self.w).min(other.x + other.w) - x; |
400 | let h = (self.y + self.h).min(other.y + other.h) - y; |
401 | |
402 | let result = Self { x, y, w, h }; |
403 | if !result.is_empty() { |
404 | Some(result) |
405 | } else { |
406 | None |
407 | } |
408 | } |
409 | |
410 | pub fn is_empty(&self) -> bool { |
411 | self.w <= 0. || self.h <= 0. |
412 | } |
413 | } |
414 | |
415 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd)] |
416 | pub struct Bounds { |
417 | pub minx: f32, |
418 | pub miny: f32, |
419 | pub maxx: f32, |
420 | pub maxy: f32, |
421 | } |
422 | |
423 | impl Default for Bounds { |
424 | fn default() -> Self { |
425 | Self { |
426 | minx: 1e6, |
427 | miny: 1e6, |
428 | maxx: -1e6, |
429 | maxy: -1e6, |
430 | } |
431 | } |
432 | } |
433 | |
434 | impl Bounds { |
435 | pub(crate) fn contains(&self, x: f32, y: f32) -> bool { |
436 | (self.minx..=self.maxx).contains(&x) && (self.miny..=self.maxy).contains(&y) |
437 | } |
438 | } |
439 | |