1use core::ops::{Mul, MulAssign};
7
8use crate::{Point, Rect, Vec2};
9
10#[cfg(not(feature = "std"))]
11use crate::common::FloatFuncs;
12
13#[derive(Clone, Copy, Debug, PartialEq)]
15#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct Affine([f64; 6]);
18
19impl Affine {
20 pub const IDENTITY: Affine = Affine::scale(1.0);
22
23 pub const FLIP_Y: Affine = Affine::new([1.0, 0., 0., -1.0, 0., 0.]);
26
27 pub const FLIP_X: Affine = Affine::new([-1.0, 0., 0., 1.0, 0., 0.]);
29
30 #[inline(always)]
48 pub const fn new(c: [f64; 6]) -> Affine {
49 Affine(c)
50 }
51
52 #[inline(always)]
54 pub const fn scale(s: f64) -> Affine {
55 Affine([s, 0.0, 0.0, s, 0.0, 0.0])
56 }
57
58 #[inline(always)]
61 pub const fn scale_non_uniform(s_x: f64, s_y: f64) -> Affine {
62 Affine([s_x, 0.0, 0.0, s_y, 0.0, 0.0])
63 }
64
65 #[inline]
72 pub fn scale_about(s: f64, center: Point) -> Affine {
73 let center = center.to_vec2();
74 Self::translate(-center)
75 .then_scale(s)
76 .then_translate(center)
77 }
78
79 #[inline]
88 pub fn rotate(th: f64) -> Affine {
89 let (s, c) = th.sin_cos();
90 Affine([c, s, -s, c, 0.0, 0.0])
91 }
92
93 #[inline]
97 pub fn rotate_about(th: f64, center: Point) -> Affine {
98 let center = center.to_vec2();
99 Self::translate(-center)
100 .then_rotate(th)
101 .then_translate(center)
102 }
103
104 #[inline(always)]
106 pub fn translate<V: Into<Vec2>>(p: V) -> Affine {
107 let p = p.into();
108 Affine([1.0, 0.0, 0.0, 1.0, p.x, p.y])
109 }
110
111 #[inline(always)]
125 pub fn skew(skew_x: f64, skew_y: f64) -> Affine {
126 Affine([1.0, skew_y, skew_x, 1.0, 0.0, 0.0])
127 }
128
129 #[inline]
146 #[must_use]
147 pub fn reflect(point: impl Into<Point>, direction: impl Into<Vec2>) -> Self {
148 let point = point.into();
149 let direction = direction.into();
150
151 let n = Vec2 {
152 x: direction.y,
153 y: -direction.x,
154 }
155 .normalize();
156
157 let x2 = n.x * n.x;
159 let xy = n.x * n.y;
160 let y2 = n.y * n.y;
161 let aff = Affine::new([
163 1. - 2. * x2,
164 -2. * xy,
165 -2. * xy,
166 1. - 2. * y2,
167 point.x,
168 point.y,
169 ]);
170 aff.pre_translate(-point.to_vec2())
171 }
172
173 #[inline]
179 #[must_use]
180 pub fn pre_rotate(self, th: f64) -> Self {
181 self * Affine::rotate(th)
182 }
183
184 #[inline]
190 #[must_use]
191 pub fn pre_rotate_about(self, th: f64, center: Point) -> Self {
192 Affine::rotate_about(th, center) * self
193 }
194
195 #[inline]
201 #[must_use]
202 pub fn pre_scale(self, scale: f64) -> Self {
203 self * Affine::scale(scale)
204 }
205
206 #[inline]
212 #[must_use]
213 pub fn pre_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Self {
214 self * Affine::scale_non_uniform(scale_x, scale_y)
215 }
216
217 #[inline]
223 #[must_use]
224 pub fn pre_translate(self, trans: Vec2) -> Self {
225 self * Affine::translate(trans)
226 }
227
228 #[inline]
234 #[must_use]
235 pub fn then_rotate(self, th: f64) -> Self {
236 Affine::rotate(th) * self
237 }
238
239 #[inline]
245 #[must_use]
246 pub fn then_rotate_about(self, th: f64, center: Point) -> Self {
247 Affine::rotate_about(th, center) * self
248 }
249
250 #[inline]
256 #[must_use]
257 pub fn then_scale(self, scale: f64) -> Self {
258 Affine::scale(scale) * self
259 }
260
261 #[inline]
267 #[must_use]
268 pub fn then_scale_non_uniform(self, scale_x: f64, scale_y: f64) -> Self {
269 Affine::scale_non_uniform(scale_x, scale_y) * self
270 }
271
272 #[inline]
278 #[must_use]
279 pub fn then_scale_about(self, scale: f64, center: Point) -> Self {
280 Affine::scale_about(scale, center) * self
281 }
282
283 #[inline]
289 #[must_use]
290 pub fn then_translate(mut self, trans: Vec2) -> Self {
291 self.0[4] += trans.x;
292 self.0[5] += trans.y;
293 self
294 }
295
296 pub fn map_unit_square(rect: Rect) -> Affine {
301 Affine([rect.width(), 0., 0., rect.height(), rect.x0, rect.y0])
302 }
303
304 #[inline(always)]
306 pub fn as_coeffs(self) -> [f64; 6] {
307 self.0
308 }
309
310 pub fn determinant(self) -> f64 {
312 self.0[0] * self.0[3] - self.0[1] * self.0[2]
313 }
314
315 pub fn inverse(self) -> Affine {
319 let inv_det = self.determinant().recip();
320 Affine([
321 inv_det * self.0[3],
322 -inv_det * self.0[1],
323 -inv_det * self.0[2],
324 inv_det * self.0[0],
325 inv_det * (self.0[2] * self.0[5] - self.0[3] * self.0[4]),
326 inv_det * (self.0[1] * self.0[4] - self.0[0] * self.0[5]),
327 ])
328 }
329
330 pub fn transform_rect_bbox(self, rect: Rect) -> Rect {
338 let p00 = self * Point::new(rect.x0, rect.y0);
339 let p01 = self * Point::new(rect.x0, rect.y1);
340 let p10 = self * Point::new(rect.x1, rect.y0);
341 let p11 = self * Point::new(rect.x1, rect.y1);
342 Rect::from_points(p00, p01).union(Rect::from_points(p10, p11))
343 }
344
345 #[inline]
349 pub fn is_finite(&self) -> bool {
350 self.0[0].is_finite()
351 && self.0[1].is_finite()
352 && self.0[2].is_finite()
353 && self.0[3].is_finite()
354 && self.0[4].is_finite()
355 && self.0[5].is_finite()
356 }
357
358 #[inline]
362 pub fn is_nan(&self) -> bool {
363 self.0[0].is_nan()
364 || self.0[1].is_nan()
365 || self.0[2].is_nan()
366 || self.0[3].is_nan()
367 || self.0[4].is_nan()
368 || self.0[5].is_nan()
369 }
370
371 #[inline]
394 pub(crate) fn svd(self) -> (Vec2, f64) {
395 let a = self.0[0];
396 let a2 = a * a;
397 let b = self.0[1];
398 let b2 = b * b;
399 let c = self.0[2];
400 let c2 = c * c;
401 let d = self.0[3];
402 let d2 = d * d;
403 let ab = a * b;
404 let cd = c * d;
405 let angle = 0.5 * (2.0 * (ab + cd)).atan2(a2 - b2 + c2 - d2);
406 let s1 = a2 + b2 + c2 + d2;
407 let s2 = ((a2 - b2 + c2 - d2).powi(2) + 4.0 * (ab + cd).powi(2)).sqrt();
408 (
409 Vec2 {
410 x: (0.5 * (s1 + s2)).sqrt(),
411 y: (0.5 * (s1 - s2)).sqrt(),
412 },
413 angle,
414 )
415 }
416
417 #[inline(always)]
419 pub fn translation(self) -> Vec2 {
420 Vec2 {
421 x: self.0[4],
422 y: self.0[5],
423 }
424 }
425
426 #[must_use]
430 #[inline(always)]
431 pub fn with_translation(mut self, trans: Vec2) -> Affine {
432 self.0[4] = trans.x;
433 self.0[5] = trans.y;
434 self
435 }
436}
437
438impl Default for Affine {
439 #[inline(always)]
440 fn default() -> Affine {
441 Affine::IDENTITY
442 }
443}
444
445impl Mul<Point> for Affine {
446 type Output = Point;
447
448 #[inline]
449 fn mul(self, other: Point) -> Point {
450 Point::new(
451 self.0[0] * other.x + self.0[2] * other.y + self.0[4],
452 self.0[1] * other.x + self.0[3] * other.y + self.0[5],
453 )
454 }
455}
456
457impl Mul for Affine {
458 type Output = Affine;
459
460 #[inline]
461 fn mul(self, other: Affine) -> Affine {
462 Affine([
463 self.0[0] * other.0[0] + self.0[2] * other.0[1],
464 self.0[1] * other.0[0] + self.0[3] * other.0[1],
465 self.0[0] * other.0[2] + self.0[2] * other.0[3],
466 self.0[1] * other.0[2] + self.0[3] * other.0[3],
467 self.0[0] * other.0[4] + self.0[2] * other.0[5] + self.0[4],
468 self.0[1] * other.0[4] + self.0[3] * other.0[5] + self.0[5],
469 ])
470 }
471}
472
473impl MulAssign for Affine {
474 #[inline]
475 fn mul_assign(&mut self, other: Affine) {
476 *self = self.mul(other);
477 }
478}
479
480impl Mul<Affine> for f64 {
481 type Output = Affine;
482
483 #[inline]
484 fn mul(self, other: Affine) -> Affine {
485 Affine([
486 self * other.0[0],
487 self * other.0[1],
488 self * other.0[2],
489 self * other.0[3],
490 self * other.0[4],
491 self * other.0[5],
492 ])
493 }
494}
495
496#[cfg(feature = "mint")]
498impl From<Affine> for mint::ColumnMatrix2x3<f64> {
499 #[inline(always)]
500 fn from(a: Affine) -> mint::ColumnMatrix2x3<f64> {
501 mint::ColumnMatrix2x3 {
502 x: mint::Vector2 {
503 x: a.0[0],
504 y: a.0[1],
505 },
506 y: mint::Vector2 {
507 x: a.0[2],
508 y: a.0[3],
509 },
510 z: mint::Vector2 {
511 x: a.0[4],
512 y: a.0[5],
513 },
514 }
515 }
516}
517
518#[cfg(feature = "mint")]
519impl From<mint::ColumnMatrix2x3<f64>> for Affine {
520 #[inline(always)]
521 fn from(m: mint::ColumnMatrix2x3<f64>) -> Affine {
522 Affine([m.x.x, m.x.y, m.y.x, m.y.y, m.z.x, m.z.y])
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use crate::{Affine, Point, Vec2};
529 use std::f64::consts::PI;
530
531 fn assert_near(p0: Point, p1: Point) {
532 assert!((p1 - p0).hypot() < 1e-9, "{p0:?} != {p1:?}");
533 }
534
535 fn affine_assert_near(a0: Affine, a1: Affine) {
536 for i in 0..6 {
537 assert!((a0.0[i] - a1.0[i]).abs() < 1e-9, "{a0:?} != {a1:?}");
538 }
539 }
540
541 #[test]
542 fn affine_basic() {
543 let p = Point::new(3.0, 4.0);
544
545 assert_near(Affine::default() * p, p);
546 assert_near(Affine::scale(2.0) * p, Point::new(6.0, 8.0));
547 assert_near(Affine::rotate(0.0) * p, p);
548 assert_near(Affine::rotate(PI / 2.0) * p, Point::new(-4.0, 3.0));
549 assert_near(Affine::translate((5.0, 6.0)) * p, Point::new(8.0, 10.0));
550 assert_near(Affine::skew(0.0, 0.0) * p, p);
551 assert_near(Affine::skew(2.0, 4.0) * p, Point::new(11.0, 16.0));
552 }
553
554 #[test]
555 fn affine_mul() {
556 let a1 = Affine::new([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
557 let a2 = Affine::new([0.1, 1.2, 2.3, 3.4, 4.5, 5.6]);
558
559 let px = Point::new(1.0, 0.0);
560 let py = Point::new(0.0, 1.0);
561 let pxy = Point::new(1.0, 1.0);
562 assert_near(a1 * (a2 * px), (a1 * a2) * px);
563 assert_near(a1 * (a2 * py), (a1 * a2) * py);
564 assert_near(a1 * (a2 * pxy), (a1 * a2) * pxy);
565 }
566
567 #[test]
568 fn affine_inv() {
569 let a = Affine::new([0.1, 1.2, 2.3, 3.4, 4.5, 5.6]);
570 let a_inv = a.inverse();
571
572 let px = Point::new(1.0, 0.0);
573 let py = Point::new(0.0, 1.0);
574 let pxy = Point::new(1.0, 1.0);
575 assert_near(a * (a_inv * px), px);
576 assert_near(a * (a_inv * py), py);
577 assert_near(a * (a_inv * pxy), pxy);
578 assert_near(a_inv * (a * px), px);
579 assert_near(a_inv * (a * py), py);
580 assert_near(a_inv * (a * pxy), pxy);
581 }
582
583 #[test]
584 fn reflection() {
585 affine_assert_near(
586 Affine::reflect(Point::ZERO, (1., 0.)),
587 Affine::new([1., 0., 0., -1., 0., 0.]),
588 );
589 affine_assert_near(
590 Affine::reflect(Point::ZERO, (0., 1.)),
591 Affine::new([-1., 0., 0., 1., 0., 0.]),
592 );
593 affine_assert_near(
595 Affine::reflect(Point::ZERO, (1., 1.)),
596 Affine::new([0., 1., 1., 0., 0., 0.]),
597 );
598
599 let point = Point::new(0., 0.);
601 let vec = Vec2::new(1., 1.);
602 let map = Affine::reflect(point, vec);
603 assert_near(map * Point::new(0., 0.), Point::new(0., 0.));
604 assert_near(map * Point::new(1., 1.), Point::new(1., 1.));
605 assert_near(map * Point::new(1., 2.), Point::new(2., 1.));
606
607 let point = Point::new(1., 0.);
609 let vec = Vec2::new(1., 1.);
610 let map = Affine::reflect(point, vec);
611 assert_near(map * Point::new(1., 0.), Point::new(1., 0.));
612 assert_near(map * Point::new(2., 1.), Point::new(2., 1.));
613 assert_near(map * Point::new(2., 2.), Point::new(3., 1.));
614 }
615
616 #[test]
617 fn svd() {
618 let a = Affine::new([1., 2., 3., 4., 5., 6.]);
619 let a_no_translate = a.with_translation(Vec2::ZERO);
620
621 let (scale, rotation) = a.svd();
623 let (scale_no_translate, rotation_no_translate) = a_no_translate.svd();
624 assert_near(scale.to_point(), scale_no_translate.to_point());
625 assert!((rotation - rotation_no_translate).abs() <= 1e-9);
626
627 assert_near(
628 scale.to_point(),
629 Point::new(5.4649857042190427, 0.36596619062625782),
630 );
631 assert!((rotation - 0.95691013360780001).abs() <= 1e-9);
632
633 let a = Affine::new([0., 0., 0., 0., 5., 6.]);
635 assert_eq!(a.determinant(), 0.);
636 let (scale, rotation) = a.svd();
637 assert_eq!(scale, Vec2::new(0., 0.));
638 assert_eq!(rotation, 0.);
639 }
640}