1use crate::basics::is_equal_eps;
8
9pub const AFFINE_EPSILON: f64 = 1e-14;
11
12#[derive(Debug, Clone, Copy)]
27pub struct TransAffine {
28 pub sx: f64,
29 pub shy: f64,
30 pub shx: f64,
31 pub sy: f64,
32 pub tx: f64,
33 pub ty: f64,
34}
35
36impl TransAffine {
37 pub fn new() -> Self {
43 Self {
44 sx: 1.0,
45 shy: 0.0,
46 shx: 0.0,
47 sy: 1.0,
48 tx: 0.0,
49 ty: 0.0,
50 }
51 }
52
53 pub fn new_custom(sx: f64, shy: f64, shx: f64, sy: f64, tx: f64, ty: f64) -> Self {
55 Self {
56 sx,
57 shy,
58 shx,
59 sy,
60 tx,
61 ty,
62 }
63 }
64
65 pub fn from_array(m: &[f64; 6]) -> Self {
67 Self {
68 sx: m[0],
69 shy: m[1],
70 shx: m[2],
71 sy: m[3],
72 tx: m[4],
73 ty: m[5],
74 }
75 }
76
77 pub fn new_rotation(a: f64) -> Self {
83 let (sa, ca) = a.sin_cos();
84 Self::new_custom(ca, sa, -sa, ca, 0.0, 0.0)
85 }
86
87 pub fn new_scaling(x: f64, y: f64) -> Self {
89 Self::new_custom(x, 0.0, 0.0, y, 0.0, 0.0)
90 }
91
92 pub fn new_scaling_uniform(s: f64) -> Self {
94 Self::new_custom(s, 0.0, 0.0, s, 0.0, 0.0)
95 }
96
97 pub fn new_translation(x: f64, y: f64) -> Self {
99 Self::new_custom(1.0, 0.0, 0.0, 1.0, x, y)
100 }
101
102 pub fn new_skewing(x: f64, y: f64) -> Self {
104 Self::new_custom(1.0, y.tan(), x.tan(), 1.0, 0.0, 0.0)
105 }
106
107 pub fn new_line_segment(x1: f64, y1: f64, x2: f64, y2: f64, dist: f64) -> Self {
109 let dx = x2 - x1;
110 let dy = y2 - y1;
111 let mut m = Self::new();
112 if dist > 0.0 {
113 m.multiply(&Self::new_scaling_uniform(
114 (dx * dx + dy * dy).sqrt() / dist,
115 ));
116 }
117 m.multiply(&Self::new_rotation(dy.atan2(dx)));
118 m.multiply(&Self::new_translation(x1, y1));
119 m
120 }
121
122 pub fn new_reflection(a: f64) -> Self {
124 Self::new_reflection_unit(a.cos(), a.sin())
125 }
126
127 pub fn new_reflection_xy(x: f64, y: f64) -> Self {
130 let d = (x * x + y * y).sqrt();
131 Self::new_reflection_unit(x / d, y / d)
132 }
133
134 pub fn new_reflection_unit(ux: f64, uy: f64) -> Self {
137 Self::new_custom(
138 2.0 * ux * ux - 1.0,
139 2.0 * ux * uy,
140 2.0 * ux * uy,
141 2.0 * uy * uy - 1.0,
142 0.0,
143 0.0,
144 )
145 }
146
147 pub fn parl_to_parl(&mut self, src: &[f64; 6], dst: &[f64; 6]) -> &mut Self {
156 self.sx = src[2] - src[0];
157 self.shy = src[3] - src[1];
158 self.shx = src[4] - src[0];
159 self.sy = src[5] - src[1];
160 self.tx = src[0];
161 self.ty = src[1];
162 self.invert();
163 self.multiply(&TransAffine::new_custom(
164 dst[2] - dst[0],
165 dst[3] - dst[1],
166 dst[4] - dst[0],
167 dst[5] - dst[1],
168 dst[0],
169 dst[1],
170 ));
171 self
172 }
173
174 pub fn rect_to_parl(
176 &mut self,
177 x1: f64,
178 y1: f64,
179 x2: f64,
180 y2: f64,
181 parl: &[f64; 6],
182 ) -> &mut Self {
183 let src = [x1, y1, x2, y1, x2, y2];
184 self.parl_to_parl(&src, parl);
185 self
186 }
187
188 pub fn parl_to_rect(
190 &mut self,
191 parl: &[f64; 6],
192 x1: f64,
193 y1: f64,
194 x2: f64,
195 y2: f64,
196 ) -> &mut Self {
197 let dst = [x1, y1, x2, y1, x2, y2];
198 self.parl_to_parl(parl, &dst);
199 self
200 }
201
202 pub fn reset(&mut self) -> &mut Self {
208 self.sx = 1.0;
209 self.sy = 1.0;
210 self.shy = 0.0;
211 self.shx = 0.0;
212 self.tx = 0.0;
213 self.ty = 0.0;
214 self
215 }
216
217 pub fn translate(&mut self, x: f64, y: f64) -> &mut Self {
219 self.tx += x;
220 self.ty += y;
221 self
222 }
223
224 pub fn rotate(&mut self, a: f64) -> &mut Self {
226 let (sa, ca) = a.sin_cos();
227 let t0 = self.sx * ca - self.shy * sa;
228 let t2 = self.shx * ca - self.sy * sa;
229 let t4 = self.tx * ca - self.ty * sa;
230 self.shy = self.sx * sa + self.shy * ca;
231 self.sy = self.shx * sa + self.sy * ca;
232 self.ty = self.tx * sa + self.ty * ca;
233 self.sx = t0;
234 self.shx = t2;
235 self.tx = t4;
236 self
237 }
238
239 pub fn scale(&mut self, x: f64, y: f64) -> &mut Self {
241 self.sx *= x;
242 self.shx *= x;
243 self.tx *= x;
244 self.shy *= y;
245 self.sy *= y;
246 self.ty *= y;
247 self
248 }
249
250 pub fn scale_uniform(&mut self, s: f64) -> &mut Self {
252 self.scale(s, s)
253 }
254
255 pub fn multiply(&mut self, m: &TransAffine) -> &mut Self {
257 let t0 = self.sx * m.sx + self.shy * m.shx;
258 let t2 = self.shx * m.sx + self.sy * m.shx;
259 let t4 = self.tx * m.sx + self.ty * m.shx + m.tx;
260 self.shy = self.sx * m.shy + self.shy * m.sy;
261 self.sy = self.shx * m.shy + self.sy * m.sy;
262 self.ty = self.tx * m.shy + self.ty * m.sy + m.ty;
263 self.sx = t0;
264 self.shx = t2;
265 self.tx = t4;
266 self
267 }
268
269 pub fn premultiply(&mut self, m: &TransAffine) -> &mut Self {
271 let mut t = *m;
272 t.multiply(self);
273 *self = t;
274 self
275 }
276
277 pub fn multiply_inv(&mut self, m: &TransAffine) -> &mut Self {
279 let mut t = *m;
280 t.invert();
281 self.multiply(&t);
282 self
283 }
284
285 pub fn premultiply_inv(&mut self, m: &TransAffine) -> &mut Self {
287 let mut t = *m;
288 t.invert();
289 t.multiply(self);
290 *self = t;
291 self
292 }
293
294 pub fn invert(&mut self) -> &mut Self {
296 let d = self.determinant_reciprocal();
297 let t0 = self.sy * d;
298 self.sy = self.sx * d;
299 self.shy = -self.shy * d;
300 self.shx = -self.shx * d;
301 let t4 = -self.tx * t0 - self.ty * self.shx;
302 self.ty = -self.tx * self.shy - self.ty * self.sy;
303 self.sx = t0;
304 self.tx = t4;
305 self
306 }
307
308 pub fn flip_x(&mut self) -> &mut Self {
310 self.sx = -self.sx;
311 self.shy = -self.shy;
312 self.tx = -self.tx;
313 self
314 }
315
316 pub fn flip_y(&mut self) -> &mut Self {
318 self.shx = -self.shx;
319 self.sy = -self.sy;
320 self.ty = -self.ty;
321 self
322 }
323
324 pub fn store_to(&self, m: &mut [f64; 6]) {
330 m[0] = self.sx;
331 m[1] = self.shy;
332 m[2] = self.shx;
333 m[3] = self.sy;
334 m[4] = self.tx;
335 m[5] = self.ty;
336 }
337
338 pub fn load_from(&mut self, m: &[f64; 6]) -> &mut Self {
340 self.sx = m[0];
341 self.shy = m[1];
342 self.shx = m[2];
343 self.sy = m[3];
344 self.tx = m[4];
345 self.ty = m[5];
346 self
347 }
348
349 #[inline]
355 pub fn transform(&self, x: &mut f64, y: &mut f64) {
356 let tmp = *x;
357 *x = tmp * self.sx + *y * self.shx + self.tx;
358 *y = tmp * self.shy + *y * self.sy + self.ty;
359 }
360
361 #[inline]
363 pub fn transform_2x2(&self, x: &mut f64, y: &mut f64) {
364 let tmp = *x;
365 *x = tmp * self.sx + *y * self.shx;
366 *y = tmp * self.shy + *y * self.sy;
367 }
368
369 #[inline]
371 pub fn inverse_transform(&self, x: &mut f64, y: &mut f64) {
372 let d = self.determinant_reciprocal();
373 let a = (*x - self.tx) * d;
374 let b = (*y - self.ty) * d;
375 *x = a * self.sy - b * self.shx;
376 *y = b * self.sx - a * self.shy;
377 }
378
379 #[inline]
385 pub fn determinant(&self) -> f64 {
386 self.sx * self.sy - self.shy * self.shx
387 }
388
389 #[inline]
391 pub fn determinant_reciprocal(&self) -> f64 {
392 1.0 / (self.sx * self.sy - self.shy * self.shx)
393 }
394
395 pub fn get_scale(&self) -> f64 {
402 let x = 0.707106781_f64 * self.sx + 0.707106781_f64 * self.shx;
403 let y = 0.707106781_f64 * self.shy + 0.707106781_f64 * self.sy;
404 (x * x + y * y).sqrt()
405 }
406
407 pub fn is_valid(&self, epsilon: f64) -> bool {
409 self.sx.abs() > epsilon && self.sy.abs() > epsilon
410 }
411
412 pub fn is_identity(&self, epsilon: f64) -> bool {
414 is_equal_eps(self.sx, 1.0, epsilon)
415 && is_equal_eps(self.shy, 0.0, epsilon)
416 && is_equal_eps(self.shx, 0.0, epsilon)
417 && is_equal_eps(self.sy, 1.0, epsilon)
418 && is_equal_eps(self.tx, 0.0, epsilon)
419 && is_equal_eps(self.ty, 0.0, epsilon)
420 }
421
422 pub fn is_equal(&self, m: &TransAffine, epsilon: f64) -> bool {
424 is_equal_eps(self.sx, m.sx, epsilon)
425 && is_equal_eps(self.shy, m.shy, epsilon)
426 && is_equal_eps(self.shx, m.shx, epsilon)
427 && is_equal_eps(self.sy, m.sy, epsilon)
428 && is_equal_eps(self.tx, m.tx, epsilon)
429 && is_equal_eps(self.ty, m.ty, epsilon)
430 }
431
432 pub fn rotation(&self) -> f64 {
434 let mut x1 = 0.0;
435 let mut y1 = 0.0;
436 let mut x2 = 1.0;
437 let mut y2 = 0.0;
438 self.transform(&mut x1, &mut y1);
439 self.transform(&mut x2, &mut y2);
440 (y2 - y1).atan2(x2 - x1)
441 }
442
443 pub fn translation(&self) -> (f64, f64) {
445 (self.tx, self.ty)
446 }
447
448 pub fn scaling(&self) -> (f64, f64) {
450 let mut x1 = 0.0;
451 let mut y1 = 0.0;
452 let mut x2 = 1.0;
453 let mut y2 = 1.0;
454 let mut t = *self;
455 t.multiply(&TransAffine::new_rotation(-self.rotation()));
456 t.transform(&mut x1, &mut y1);
457 t.transform(&mut x2, &mut y2);
458 (x2 - x1, y2 - y1)
459 }
460
461 pub fn scaling_abs(&self) -> (f64, f64) {
463 (
464 (self.sx * self.sx + self.shx * self.shx).sqrt(),
465 (self.shy * self.shy + self.sy * self.sy).sqrt(),
466 )
467 }
468}
469
470impl Default for TransAffine {
471 fn default() -> Self {
472 Self::new()
473 }
474}
475
476impl PartialEq for TransAffine {
477 fn eq(&self, other: &Self) -> bool {
478 self.is_equal(other, AFFINE_EPSILON)
479 }
480}
481
482impl std::ops::Mul for TransAffine {
483 type Output = TransAffine;
484 fn mul(self, rhs: TransAffine) -> TransAffine {
485 let mut result = self;
486 result.multiply(&rhs);
487 result
488 }
489}
490
491impl std::ops::MulAssign for TransAffine {
492 fn mul_assign(&mut self, rhs: TransAffine) {
493 self.multiply(&rhs);
494 }
495}
496
497#[cfg(test)]
502mod tests {
503 use super::*;
504 use std::f64::consts::PI;
505
506 const EPS: f64 = 1e-10;
507
508 #[test]
509 fn test_identity() {
510 let m = TransAffine::new();
511 assert!(m.is_identity(AFFINE_EPSILON));
512 assert_eq!(m.determinant(), 1.0);
513 }
514
515 #[test]
516 fn test_translation() {
517 let m = TransAffine::new_translation(10.0, 20.0);
518 let mut x = 5.0;
519 let mut y = 3.0;
520 m.transform(&mut x, &mut y);
521 assert!((x - 15.0).abs() < EPS);
522 assert!((y - 23.0).abs() < EPS);
523 }
524
525 #[test]
526 fn test_scaling() {
527 let m = TransAffine::new_scaling(2.0, 3.0);
528 let mut x = 5.0;
529 let mut y = 4.0;
530 m.transform(&mut x, &mut y);
531 assert!((x - 10.0).abs() < EPS);
532 assert!((y - 12.0).abs() < EPS);
533 }
534
535 #[test]
536 fn test_uniform_scaling() {
537 let m = TransAffine::new_scaling_uniform(5.0);
538 let mut x = 2.0;
539 let mut y = 3.0;
540 m.transform(&mut x, &mut y);
541 assert!((x - 10.0).abs() < EPS);
542 assert!((y - 15.0).abs() < EPS);
543 }
544
545 #[test]
546 fn test_rotation_90() {
547 let m = TransAffine::new_rotation(PI / 2.0);
548 let mut x = 1.0;
549 let mut y = 0.0;
550 m.transform(&mut x, &mut y);
551 assert!(x.abs() < EPS);
552 assert!((y - 1.0).abs() < EPS);
553 }
554
555 #[test]
556 fn test_rotation_180() {
557 let m = TransAffine::new_rotation(PI);
558 let mut x = 1.0;
559 let mut y = 0.0;
560 m.transform(&mut x, &mut y);
561 assert!((x + 1.0).abs() < EPS);
562 assert!(y.abs() < EPS);
563 }
564
565 #[test]
566 fn test_multiply_translate_then_scale() {
567 let mut m = TransAffine::new_translation(10.0, 0.0);
569 m.multiply(&TransAffine::new_scaling(2.0, 2.0));
570 let mut x = 0.0;
571 let mut y = 0.0;
572 m.transform(&mut x, &mut y);
573 assert!((x - 20.0).abs() < EPS); assert!(y.abs() < EPS);
575 }
576
577 #[test]
578 fn test_multiply_scale_then_translate() {
579 let mut m = TransAffine::new_scaling(2.0, 2.0);
580 m.multiply(&TransAffine::new_translation(10.0, 0.0));
581 let mut x = 5.0;
582 let mut y = 0.0;
583 m.transform(&mut x, &mut y);
584 assert!((x - 20.0).abs() < EPS); }
586
587 #[test]
588 fn test_invert() {
589 let mut m = TransAffine::new_scaling(2.0, 3.0);
590 m.multiply(&TransAffine::new_translation(10.0, 20.0));
591
592 let mut inv = m;
593 inv.invert();
594
595 let result = m * inv;
597 assert!(result.is_identity(1e-10));
598 }
599
600 #[test]
601 fn test_inverse_transform() {
602 let m = TransAffine::new_scaling(2.0, 3.0);
603 let mut x = 5.0;
604 let mut y = 4.0;
605 m.transform(&mut x, &mut y);
606 m.inverse_transform(&mut x, &mut y);
607 assert!((x - 5.0).abs() < EPS);
608 assert!((y - 4.0).abs() < EPS);
609 }
610
611 #[test]
612 fn test_transform_2x2() {
613 let m = TransAffine::new_custom(2.0, 0.0, 0.0, 3.0, 100.0, 200.0);
614 let mut x = 5.0;
615 let mut y = 4.0;
616 m.transform_2x2(&mut x, &mut y);
617 assert!((x - 10.0).abs() < EPS);
619 assert!((y - 12.0).abs() < EPS);
620 }
621
622 #[test]
623 fn test_premultiply() {
624 let s = TransAffine::new_scaling(2.0, 2.0);
625 let t = TransAffine::new_translation(10.0, 0.0);
626
627 let mut m = t;
629 m.premultiply(&s);
630
631 let mut x = 5.0;
634 let mut y = 0.0;
635 m.transform(&mut x, &mut y);
636 assert!((x - 20.0).abs() < EPS);
637 }
638
639 #[test]
640 fn test_flip_x() {
641 let mut m = TransAffine::new();
642 m.flip_x();
643 let mut x = 5.0;
644 let mut y = 3.0;
645 m.transform(&mut x, &mut y);
646 assert!((x + 5.0).abs() < EPS);
647 assert!((y - 3.0).abs() < EPS);
648 }
649
650 #[test]
651 fn test_flip_y() {
652 let mut m = TransAffine::new();
653 m.flip_y();
654 let mut x = 5.0;
655 let mut y = 3.0;
656 m.transform(&mut x, &mut y);
657 assert!((x - 5.0).abs() < EPS);
658 assert!((y + 3.0).abs() < EPS);
659 }
660
661 #[test]
662 fn test_reset() {
663 let mut m = TransAffine::new_scaling(2.0, 3.0);
664 m.reset();
665 assert!(m.is_identity(AFFINE_EPSILON));
666 }
667
668 #[test]
669 fn test_store_load() {
670 let m = TransAffine::new_custom(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
671 let mut arr = [0.0; 6];
672 m.store_to(&mut arr);
673 assert_eq!(arr, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
674
675 let m2 = TransAffine::from_array(&arr);
676 assert!(m.is_equal(&m2, EPS));
677 }
678
679 #[test]
680 fn test_get_scale() {
681 let m = TransAffine::new_scaling_uniform(3.0);
682 assert!((m.get_scale() - 3.0).abs() < 1e-8);
684 }
685
686 #[test]
687 fn test_is_valid() {
688 let m = TransAffine::new();
689 assert!(m.is_valid(AFFINE_EPSILON));
690
691 let m2 = TransAffine::new_custom(0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
692 assert!(!m2.is_valid(AFFINE_EPSILON));
693 }
694
695 #[test]
696 fn test_rotation_extraction() {
697 let m = TransAffine::new_rotation(PI / 4.0);
698 assert!((m.rotation() - PI / 4.0).abs() < EPS);
699 }
700
701 #[test]
702 fn test_translation_extraction() {
703 let m = TransAffine::new_translation(42.0, 17.0);
704 let (dx, dy) = m.translation();
705 assert!((dx - 42.0).abs() < EPS);
706 assert!((dy - 17.0).abs() < EPS);
707 }
708
709 #[test]
710 fn test_scaling_extraction() {
711 let m = TransAffine::new_scaling(3.0, 5.0);
712 let (sx, sy) = m.scaling();
713 assert!((sx - 3.0).abs() < EPS);
714 assert!((sy - 5.0).abs() < EPS);
715 }
716
717 #[test]
718 fn test_scaling_abs() {
719 let m = TransAffine::new_scaling(3.0, 5.0);
720 let (ax, ay) = m.scaling_abs();
721 assert!((ax - 3.0).abs() < EPS);
722 assert!((ay - 5.0).abs() < EPS);
723 }
724
725 #[test]
726 fn test_skewing() {
727 let m = TransAffine::new_skewing(PI / 4.0, 0.0);
728 let mut x = 0.0;
729 let mut y = 1.0;
730 m.transform(&mut x, &mut y);
731 assert!((x - 1.0).abs() < EPS);
733 assert!((y - 1.0).abs() < EPS);
734 }
735
736 #[test]
737 fn test_operator_mul() {
738 let a = TransAffine::new_translation(10.0, 0.0);
739 let b = TransAffine::new_scaling(2.0, 2.0);
740 let c = a * b;
741
742 let mut x = 1.0;
743 let mut y = 0.0;
744 c.transform(&mut x, &mut y);
745 assert!((x - 22.0).abs() < EPS);
747 }
748
749 #[test]
750 fn test_operator_mul_assign() {
751 let mut m = TransAffine::new_translation(10.0, 0.0);
752 m *= TransAffine::new_scaling(2.0, 2.0);
753
754 let mut x = 1.0;
755 let mut y = 0.0;
756 m.transform(&mut x, &mut y);
757 assert!((x - 22.0).abs() < EPS);
758 }
759
760 #[test]
761 fn test_partial_eq() {
762 let a = TransAffine::new_translation(10.0, 20.0);
763 let b = TransAffine::new_translation(10.0, 20.0);
764 assert_eq!(a, b);
765
766 let c = TransAffine::new_translation(10.0, 21.0);
767 assert_ne!(a, c);
768 }
769
770 #[test]
771 fn test_determinant() {
772 let m = TransAffine::new_scaling(2.0, 3.0);
773 assert!((m.determinant() - 6.0).abs() < EPS);
774 }
775
776 #[test]
777 fn test_combined_transform() {
778 let mut m = TransAffine::new();
780 m.rotate(PI / 2.0);
781 m.translate(10.0, 0.0);
782
783 let mut x = 1.0;
784 let mut y = 0.0;
785 m.transform(&mut x, &mut y);
786 assert!((x - 10.0).abs() < EPS);
788 assert!((y - 1.0).abs() < EPS);
789 }
790
791 #[test]
792 fn test_chain_methods() {
793 let mut m = TransAffine::new();
794 m.scale(2.0, 2.0);
795 m.translate(5.0, 0.0);
796
797 let mut x = 3.0;
798 let mut y = 0.0;
799 m.transform(&mut x, &mut y);
800 assert!((x - 11.0).abs() < EPS);
802 }
803
804 #[test]
805 fn test_parl_to_parl() {
806 let src = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0];
808 let dst = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0];
809 let mut m = TransAffine::new();
810 m.parl_to_parl(&src, &dst);
811 assert!(m.is_identity(1e-10));
812 }
813
814 #[test]
815 fn test_rect_to_parl() {
816 let parl = [0.0, 0.0, 2.0, 0.0, 2.0, 2.0];
817 let mut m = TransAffine::new();
818 m.rect_to_parl(0.0, 0.0, 1.0, 1.0, &parl);
819
820 let mut x = 0.5;
821 let mut y = 0.5;
822 m.transform(&mut x, &mut y);
823 assert!((x - 1.0).abs() < EPS);
824 assert!((y - 1.0).abs() < EPS);
825 }
826
827 #[test]
828 fn test_reflection() {
829 let m = TransAffine::new_reflection(0.0);
831 let mut x = 1.0;
832 let mut y = 1.0;
833 m.transform(&mut x, &mut y);
834 assert!((x - 1.0).abs() < EPS);
835 assert!((y + 1.0).abs() < EPS);
836 }
837
838 #[test]
839 fn test_line_segment() {
840 let m = TransAffine::new_line_segment(0.0, 0.0, 10.0, 0.0, 10.0);
841 let mut x = 5.0;
842 let mut y = 0.0;
843 m.transform(&mut x, &mut y);
844 assert!((x - 5.0).abs() < EPS);
845 assert!(y.abs() < EPS);
846 }
847
848 #[test]
849 fn test_multiply_inv() {
850 let m = TransAffine::new_scaling(2.0, 3.0);
851 let mut result = TransAffine::new_scaling(2.0, 3.0);
852 result.multiply_inv(&m);
853 assert!(result.is_identity(1e-10));
854 }
855
856 #[test]
857 fn test_default_trait() {
858 let m: TransAffine = Default::default();
859 assert!(m.is_identity(AFFINE_EPSILON));
860 }
861}