1use std::{
2 hash::{Hash, Hasher},
3 ops::{Add, Index, IndexMut, Mul, MulAssign, Neg, Sub},
4};
5
6use fnv::FnvHasher;
7
8#[derive(Copy, Clone, Debug, Default)]
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10pub(crate) struct Position {
11 pub x: f32,
12 pub y: f32,
13}
14
15impl 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
27impl 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
39impl 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
51impl 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)]
79pub(crate) struct Vector {
80 pub x: f32,
81 pub y: f32,
82}
83
84impl 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
143impl 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
155impl 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
167impl 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
176impl 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
188impl 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
196pub(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))]
203pub struct Transform2D(pub [f32; 6]);
204
205// TODO: Implement std::ops::* on this
206impl 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
346impl Default for Transform2D {
347 fn default() -> Self {
348 Self::identity()
349 }
350}
351
352impl Index<usize> for Transform2D {
353 type Output = f32;
354
355 fn index(&self, index: usize) -> &Self::Output {
356 &self.0[index]
357 }
358}
359
360impl 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)]
367pub struct Rect {
368 pub x: f32,
369 pub y: f32,
370 pub w: f32,
371 pub h: f32,
372}
373
374impl 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)]
416pub struct Bounds {
417 pub minx: f32,
418 pub miny: f32,
419 pub maxx: f32,
420 pub maxy: f32,
421}
422
423impl 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
434impl 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