1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.oned;
18
19 import java.util.function.UnaryOperator;
20
21 import org.apache.commons.geometry.core.GeometryTestUtils;
22 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
23 import org.junit.jupiter.api.Assertions;
24 import org.junit.jupiter.api.Test;
25
26 class AffineTransformMatrix1DTest {
27
28 private static final double EPS = 1e-12;
29
30 @Test
31 void testOf() {
32
33 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.of(1, 2);
34
35
36 Assertions.assertTrue(transform.preservesOrientation());
37
38 final double[] result = transform.toArray();
39 Assertions.assertArrayEquals(new double[] {1, 2}, result, 0.0);
40 }
41
42 @Test
43 void testOf_invalidDimensions() {
44
45 GeometryTestUtils.assertThrowsWithMessage(() -> AffineTransformMatrix1D.of(1),
46 IllegalArgumentException.class, "Dimension mismatch: 1 != 2");
47 }
48
49 @Test
50 void testFrom() {
51
52 Assertions.assertArrayEquals(new double[] {1, 0},
53 AffineTransformMatrix1D.from(UnaryOperator.identity()).toArray(), EPS);
54 Assertions.assertArrayEquals(new double[] {1, 2},
55 AffineTransformMatrix1D.from(v -> v.add(Vector1D.of(2))).toArray(), EPS);
56 Assertions.assertArrayEquals(new double[] {3, 0},
57 AffineTransformMatrix1D.from(v -> v.multiply(3)).toArray(), EPS);
58 Assertions.assertArrayEquals(new double[] {3, 6},
59 AffineTransformMatrix1D.from(v -> v.add(Vector1D.of(2)).multiply(3)).toArray(), EPS);
60 }
61
62 @Test
63 void testFrom_invalidFunction() {
64
65 Assertions.assertThrows(IllegalArgumentException.class, () -> AffineTransformMatrix1D.from(v -> v.multiply(0)));
66 }
67
68 @Test
69 void testIdentity() {
70
71 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity();
72
73
74 Assertions.assertTrue(transform.preservesOrientation());
75
76 final double[] expected = {1, 0};
77 Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
78 }
79
80 @Test
81 void testCreateTranslation_value() {
82
83 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createTranslation(2);
84
85
86 Assertions.assertTrue(transform.preservesOrientation());
87
88 final double[] expected = {1, 2};
89 Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
90 }
91
92 @Test
93 void testCreateTranslation_vector() {
94
95 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createTranslation(Vector1D.of(5));
96
97
98 Assertions.assertTrue(transform.preservesOrientation());
99
100 final double[] expected = {1, 5};
101 Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
102 }
103
104 @Test
105 void testTranslate_value() {
106
107 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 10);
108
109
110 final AffineTransformMatrix1D result = a.translate(4);
111
112
113 Assertions.assertTrue(result.preservesOrientation());
114
115 final double[] expected = {2, 14};
116 Assertions.assertArrayEquals(expected, result.toArray(), 0.0);
117 }
118
119 @Test
120 void testTranslate_vector() {
121
122 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 10);
123
124
125 final AffineTransformMatrix1D result = a.translate(Vector1D.of(7));
126
127
128 Assertions.assertTrue(result.preservesOrientation());
129
130 final double[] expected = {2, 17};
131 Assertions.assertArrayEquals(expected, result.toArray(), 0.0);
132 }
133
134 @Test
135 void testCreateScale_vector() {
136
137 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createScale(Vector1D.of(4));
138
139
140 Assertions.assertTrue(transform.preservesOrientation());
141
142 final double[] expected = {4, 0};
143 Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
144 }
145
146 @Test
147 void testCreateScale_value() {
148
149 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createScale(7);
150
151
152 Assertions.assertTrue(transform.preservesOrientation());
153
154 final double[] expected = {7, 0};
155 Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
156 }
157
158 @Test
159 void testScale_value() {
160
161 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 10);
162
163
164 final AffineTransformMatrix1D result = a.scale(4);
165
166
167 Assertions.assertTrue(result.preservesOrientation());
168
169 final double[] expected = {8, 40};
170 Assertions.assertArrayEquals(expected, result.toArray(), 0.0);
171 }
172
173 @Test
174 void testScale_vector() {
175
176 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 10);
177
178
179 final AffineTransformMatrix1D result = a.scale(Vector1D.of(7));
180
181
182 Assertions.assertTrue(result.preservesOrientation());
183
184 final double[] expected = {14, 70};
185 Assertions.assertArrayEquals(expected, result.toArray(), 0.0);
186 }
187
188 @Test
189 void testApply_identity() {
190
191 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity();
192
193
194 runWithCoordinates(x -> {
195 final Vector1D v = Vector1D.of(x);
196
197 EuclideanTestUtils.assertCoordinatesEqual(v, transform.apply(v), EPS);
198 });
199 }
200
201 @Test
202 void testApply_translate() {
203
204 final Vector1D translation = Vector1D.of(-Math.PI);
205
206 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
207 .translate(translation);
208
209
210 runWithCoordinates(x -> {
211 final Vector1D vec = Vector1D.of(x);
212
213 final Vector1D expectedVec = vec.add(translation);
214
215 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
216 });
217 }
218
219 @Test
220 void testApply_scale() {
221
222 final Vector1D factor = Vector1D.of(2.0);
223
224 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
225 .scale(factor);
226
227
228 runWithCoordinates(x -> {
229 final Vector1D vec = Vector1D.of(x);
230
231 final Vector1D expectedVec = Vector1D.of(factor.getX() * x);
232
233 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
234 });
235 }
236
237 @Test
238 void testApply_translateThenScale() {
239
240 final Vector1D translation = Vector1D.of(-2.0);
241 final Vector1D scale = Vector1D.of(5.0);
242
243 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
244 .translate(translation)
245 .scale(scale);
246
247
248 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(-5), transform.apply(Vector1D.of(1)), EPS);
249
250 runWithCoordinates(x -> {
251 final Vector1D vec = Vector1D.of(x);
252
253 final Vector1D expectedVec = Vector1D.of(
254 (x + translation.getX()) * scale.getX()
255 );
256
257 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
258 });
259 }
260
261 @Test
262 void testApply_scaleThenTranslate() {
263
264 final Vector1D scale = Vector1D.of(5.0);
265 final Vector1D translation = Vector1D.of(-2.0);
266
267 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
268 .scale(scale)
269 .translate(translation);
270
271
272 runWithCoordinates(x -> {
273 final Vector1D vec = Vector1D.of(x);
274
275 final Vector1D expectedVec = Vector1D.of(
276 (x * scale.getX()) + translation.getX()
277 );
278
279 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
280 });
281 }
282
283 @Test
284 void testApplyX() {
285
286 final Vector1D translation = Vector1D.of(-2.0);
287 final Vector1D scale = Vector1D.of(5.0);
288
289 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
290 .translate(translation)
291 .scale(scale);
292
293
294 runWithCoordinates(x -> {
295 final double expected = (x + translation.getX()) * scale.getX();
296
297 Assertions.assertEquals(expected, transform.applyX(x), EPS);
298 });
299 }
300
301 @Test
302 void testApplyVector_identity() {
303
304 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity();
305
306
307 runWithCoordinates(x -> {
308 final Vector1D v = Vector1D.of(x);
309
310 EuclideanTestUtils.assertCoordinatesEqual(v, transform.applyVector(v), EPS);
311 });
312 }
313
314 @Test
315 void testApplyVector_translate() {
316
317 final Vector1D translation = Vector1D.of(-Math.PI);
318
319 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
320 .translate(translation);
321
322
323 runWithCoordinates(x -> {
324 final Vector1D vec = Vector1D.of(x);
325
326 EuclideanTestUtils.assertCoordinatesEqual(vec, transform.applyVector(vec), EPS);
327 });
328 }
329
330 @Test
331 void testApplyVector_scale() {
332
333 final Vector1D factor = Vector1D.of(2.0);
334
335 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
336 .scale(factor);
337
338
339 runWithCoordinates(x -> {
340 final Vector1D vec = Vector1D.of(x);
341
342 final Vector1D expectedVec = Vector1D.of(factor.getX() * x);
343
344 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.applyVector(vec), EPS);
345 });
346 }
347
348 @Test
349 void testApplyVector_representsDisplacement() {
350
351 final Vector1D p1 = Vector1D.of(Math.PI);
352
353 final Vector1D translation = Vector1D.of(-2.0);
354 final Vector1D scale = Vector1D.of(5.0);
355
356 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
357 .translate(translation)
358 .scale(scale);
359
360
361 runWithCoordinates(x -> {
362 final Vector1D p2 = Vector1D.of(x);
363 final Vector1D input = p1.subtract(p2);
364
365 final Vector1D expectedVec = transform.apply(p1).subtract(transform.apply(p2));
366
367 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.applyVector(input), EPS);
368 });
369 }
370
371 @Test
372 void testApplyVectorX() {
373
374 final Vector1D p1 = Vector1D.of(Math.PI);
375
376 final Vector1D translation = Vector1D.of(-2.0);
377 final Vector1D scale = Vector1D.of(5.0);
378
379 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
380 .translate(translation)
381 .scale(scale);
382
383
384 runWithCoordinates(x -> {
385 final Vector1D p2 = p1.add(Vector1D.of(x));
386
387 final double expected = transform.apply(p1).vectorTo(transform.apply(p2)).getX();
388
389 Assertions.assertEquals(expected, transform.applyVectorX(x), EPS);
390 });
391 }
392
393 @Test
394 void testApplyDirection_identity() {
395
396 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity();
397
398
399 runWithCoordinates(x -> {
400 final Vector1D v = Vector1D.of(x);
401
402 EuclideanTestUtils.assertCoordinatesEqual(v.normalize(), transform.applyDirection(v), EPS);
403 }, true);
404 }
405
406 @Test
407 void testApplyDirection_translate() {
408
409 final Vector1D translation = Vector1D.of(-Math.PI);
410
411 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
412 .translate(translation);
413
414
415 runWithCoordinates(x -> {
416 final Vector1D vec = Vector1D.of(x);
417
418 EuclideanTestUtils.assertCoordinatesEqual(vec.normalize(), transform.applyDirection(vec), EPS);
419 }, true);
420 }
421
422 @Test
423 void testApplyDirection_scale() {
424
425 final Vector1D factor = Vector1D.of(2.0);
426
427 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
428 .scale(factor);
429
430
431 runWithCoordinates(x -> {
432 final Vector1D vec = Vector1D.of(x);
433
434 final Vector1D expectedVec = Vector1D.of(factor.getX() * x).normalize();
435
436 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.applyDirection(vec), EPS);
437 }, true);
438 }
439
440 @Test
441 void testApplyDirection_representsNormalizedDisplacement() {
442
443 final Vector1D p1 = Vector1D.of(Math.PI);
444
445 final Vector1D translation = Vector1D.of(-2.0);
446 final Vector1D scale = Vector1D.of(5.0);
447
448 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
449 .translate(translation)
450 .scale(scale);
451
452
453 runWithCoordinates(x -> {
454 final Vector1D p2 = Vector1D.of(x);
455 final Vector1D input = p1.subtract(p2);
456
457 final Vector1D expectedVec = transform.apply(p1).subtract(transform.apply(p2)).normalize();
458
459 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.applyDirection(input), EPS);
460 });
461 }
462
463 @Test
464 void testApplyDirection_illegalNorm() {
465
466 Assertions.assertThrows(IllegalArgumentException.class, () -> AffineTransformMatrix1D.createScale(0).applyDirection(Vector1D.Unit.PLUS));
467 Assertions.assertThrows(IllegalArgumentException.class, () -> AffineTransformMatrix1D.createScale(2).applyDirection(Vector1D.ZERO));
468 }
469
470 @Test
471 void testDeterminant() {
472
473 Assertions.assertEquals(0.0, AffineTransformMatrix1D.of(0, 1).determinant(), EPS);
474 Assertions.assertEquals(1.0, AffineTransformMatrix1D.of(1, 0).determinant(), EPS);
475 Assertions.assertEquals(-1.0, AffineTransformMatrix1D.of(-1, 2).determinant(), EPS);
476 }
477
478 @Test
479 void testPreservesOrientation() {
480
481 Assertions.assertFalse(AffineTransformMatrix1D.of(0, 1).preservesOrientation());
482 Assertions.assertTrue(AffineTransformMatrix1D.of(1, 0).preservesOrientation());
483 Assertions.assertFalse(AffineTransformMatrix1D.of(-1, 2).preservesOrientation());
484 }
485
486 @Test
487 void testMultiply() {
488
489 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 3);
490 final AffineTransformMatrix1D b = AffineTransformMatrix1D.of(13, 14);
491
492
493 final AffineTransformMatrix1D result = a.multiply(b);
494
495
496 final double[] arr = result.toArray();
497 Assertions.assertArrayEquals(new double[] {26, 31}, arr, EPS);
498 }
499
500 @Test
501 void testMultiply_combinesTransformOperations() {
502
503 final Vector1D translation1 = Vector1D.of(1);
504 final double scale = 2.0;
505 final Vector1D translation2 = Vector1D.of(4);
506
507 final AffineTransformMatrix1D a = AffineTransformMatrix1D.createTranslation(translation1);
508 final AffineTransformMatrix1D b = AffineTransformMatrix1D.createScale(scale);
509 final AffineTransformMatrix1D c = AffineTransformMatrix1D.identity();
510 final AffineTransformMatrix1D d = AffineTransformMatrix1D.createTranslation(translation2);
511
512
513 final AffineTransformMatrix1D transform = d.multiply(c).multiply(b).multiply(a);
514
515
516 runWithCoordinates(x -> {
517 final Vector1D vec = Vector1D.of(x);
518
519 final Vector1D expectedVec = vec
520 .add(translation1)
521 .multiply(scale)
522 .add(translation2);
523
524 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
525 });
526 }
527
528 @Test
529 void testPremultiply() {
530
531 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(2, 3);
532 final AffineTransformMatrix1D b = AffineTransformMatrix1D.of(13, 14);
533
534
535 final AffineTransformMatrix1D result = b.premultiply(a);
536
537
538 final double[] arr = result.toArray();
539 Assertions.assertArrayEquals(new double[] {26, 31}, arr, EPS);
540 }
541
542 @Test
543 void testPremultiply_combinesTransformOperations() {
544
545 final Vector1D translation1 = Vector1D.of(1);
546 final double scale = 2.0;
547 final Vector1D translation2 = Vector1D.of(4);
548
549 final AffineTransformMatrix1D a = AffineTransformMatrix1D.createTranslation(translation1);
550 final AffineTransformMatrix1D b = AffineTransformMatrix1D.createScale(scale);
551 final AffineTransformMatrix1D c = AffineTransformMatrix1D.identity();
552 final AffineTransformMatrix1D d = AffineTransformMatrix1D.createTranslation(translation2);
553
554
555 final AffineTransformMatrix1D transform = a.premultiply(b).premultiply(c).premultiply(d);
556
557
558 runWithCoordinates(x -> {
559 final Vector1D vec = Vector1D.of(x);
560
561 final Vector1D expectedVec = vec
562 .add(translation1)
563 .multiply(scale)
564 .add(translation2);
565
566 EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
567 });
568 }
569
570 @Test
571 void testLinear() {
572
573 final AffineTransformMatrix1D mat = AffineTransformMatrix1D.of(2, 3);
574
575
576 final AffineTransformMatrix1D result = mat.linear();
577
578
579 Assertions.assertArrayEquals(new double[] {2, 0}, result.toArray(), 0.0);
580 }
581
582 @Test
583 void testLinearTranspose() {
584
585 final AffineTransformMatrix1D mat = AffineTransformMatrix1D.of(2, 3);
586
587
588 final AffineTransformMatrix1D result = mat.linearTranspose();
589
590
591 Assertions.assertArrayEquals(new double[] {2, 0}, result.toArray(), 0.0);
592 }
593
594 @Test
595 void testNormalTransform() {
596
597 checkNormalTransform(AffineTransformMatrix1D.identity());
598
599 checkNormalTransform(AffineTransformMatrix1D.createTranslation(4));
600 checkNormalTransform(AffineTransformMatrix1D.createTranslation(-4));
601
602 checkNormalTransform(AffineTransformMatrix1D.createScale(2));
603 checkNormalTransform(AffineTransformMatrix1D.createScale(-2));
604
605 checkNormalTransform(AffineTransformMatrix1D.createScale(2).translate(3));
606 checkNormalTransform(AffineTransformMatrix1D.createScale(2).translate(-3));
607 checkNormalTransform(AffineTransformMatrix1D.createTranslation(2).scale(-3));
608 checkNormalTransform(AffineTransformMatrix1D.createTranslation(-4).scale(-1));
609 }
610
611 private void checkNormalTransform(final AffineTransformMatrix1D transform) {
612 final AffineTransformMatrix1D normalTransform = transform.normalTransform();
613
614 final Vector1D expectedPlus = transform.apply(Vector1D.Unit.PLUS)
615 .subtract(transform.apply(Vector1D.ZERO))
616 .normalize();
617
618 final Vector1D expectedMinus = transform.apply(Vector1D.Unit.MINUS)
619 .subtract(transform.apply(Vector1D.ZERO))
620 .normalize();
621
622 EuclideanTestUtils.assertCoordinatesEqual(expectedPlus,
623 normalTransform.apply(Vector1D.Unit.PLUS).normalize(), EPS);
624 EuclideanTestUtils.assertCoordinatesEqual(expectedMinus,
625 normalTransform.apply(Vector1D.Unit.MINUS).normalize(), EPS);
626 }
627
628 @Test
629 void testNormalTransform_nonInvertible() {
630
631 Assertions.assertThrows(IllegalStateException.class, () -> AffineTransformMatrix1D.createScale(0).normalTransform());
632 }
633
634 @Test
635 void testInverse_identity() {
636
637 final AffineTransformMatrix1D inverse = AffineTransformMatrix1D.identity().inverse();
638
639
640 final double[] expected = {1, 0};
641 Assertions.assertArrayEquals(expected, inverse.toArray(), 0.0);
642 }
643
644 @Test
645 void testInverse_multiplyByInverse_producesIdentity() {
646
647 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(1, 3);
648
649 final AffineTransformMatrix1D inv = a.inverse();
650
651
652 final AffineTransformMatrix1D result = inv.multiply(a);
653
654
655 final double[] expected = {1, 0};
656 Assertions.assertArrayEquals(expected, result.toArray(), EPS);
657 }
658
659 @Test
660 void testInverse_translate() {
661
662 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createTranslation(3);
663
664
665 final AffineTransformMatrix1D inverse = transform.inverse();
666
667
668 final double[] expected = {1, -3};
669 Assertions.assertArrayEquals(expected, inverse.toArray(), 0.0);
670 }
671
672 @Test
673 void testInverse_scale() {
674
675 final AffineTransformMatrix1D transform = AffineTransformMatrix1D.createScale(10);
676
677
678 final AffineTransformMatrix1D inverse = transform.inverse();
679
680
681 final double[] expected = {0.1, 0};
682 Assertions.assertArrayEquals(expected, inverse.toArray(), 0.0);
683 }
684
685 @Test
686 void testInverse_undoesOriginalTransform_translationAndScale() {
687
688 final Vector1D v1 = Vector1D.ZERO;
689 final Vector1D v2 = Vector1D.Unit.PLUS;
690 final Vector1D v3 = Vector1D.of(1.5);
691 final Vector1D v4 = Vector1D.of(-2);
692
693
694 runWithCoordinates(x -> {
695 final AffineTransformMatrix1D transform = AffineTransformMatrix1D
696 .createTranslation(x)
697 .scale(2)
698 .translate(x / 3);
699
700 final AffineTransformMatrix1D inverse = transform.inverse();
701
702 EuclideanTestUtils.assertCoordinatesEqual(v1, inverse.apply(transform.apply(v1)), EPS);
703 EuclideanTestUtils.assertCoordinatesEqual(v2, inverse.apply(transform.apply(v2)), EPS);
704 EuclideanTestUtils.assertCoordinatesEqual(v3, inverse.apply(transform.apply(v3)), EPS);
705 EuclideanTestUtils.assertCoordinatesEqual(v4, inverse.apply(transform.apply(v4)), EPS);
706 });
707 }
708
709 @Test
710 void testInverse_nonInvertible() {
711
712 GeometryTestUtils.assertThrowsWithMessage(() -> {
713 AffineTransformMatrix1D.of(0, 0).inverse();
714 }, IllegalStateException.class, "Matrix is not invertible; matrix determinant is 0.0");
715
716 GeometryTestUtils.assertThrowsWithMessage(() -> {
717 AffineTransformMatrix1D.of(Double.NaN, 0).inverse();
718 }, IllegalStateException.class, "Matrix is not invertible; matrix determinant is NaN");
719
720 GeometryTestUtils.assertThrowsWithMessage(() -> {
721 AffineTransformMatrix1D.of(Double.NEGATIVE_INFINITY, 0.0).inverse();
722 }, IllegalStateException.class, "Matrix is not invertible; matrix determinant is -Infinity");
723
724 GeometryTestUtils.assertThrowsWithMessage(() -> {
725 AffineTransformMatrix1D.of(Double.POSITIVE_INFINITY, 0).inverse();
726 }, IllegalStateException.class, "Matrix is not invertible; matrix determinant is Infinity");
727
728 GeometryTestUtils.assertThrowsWithMessage(() -> {
729 AffineTransformMatrix1D.of(1, Double.NaN).inverse();
730 }, IllegalStateException.class, "Matrix is not invertible; invalid matrix element: NaN");
731
732 GeometryTestUtils.assertThrowsWithMessage(() -> {
733 AffineTransformMatrix1D.of(1, Double.NEGATIVE_INFINITY).inverse();
734 }, IllegalStateException.class, "Matrix is not invertible; invalid matrix element: -Infinity");
735
736 GeometryTestUtils.assertThrowsWithMessage(() -> {
737 AffineTransformMatrix1D.of(1, Double.POSITIVE_INFINITY).inverse();
738 }, IllegalStateException.class, "Matrix is not invertible; invalid matrix element: Infinity");
739 }
740
741 @Test
742 void testHashCode() {
743
744 final int orig = AffineTransformMatrix1D.of(1, 2).hashCode();
745 final int same = AffineTransformMatrix1D.of(1, 2).hashCode();
746
747
748 Assertions.assertEquals(orig, same);
749
750 Assertions.assertNotEquals(orig, AffineTransformMatrix1D.of(0, 2).hashCode());
751 Assertions.assertNotEquals(orig, AffineTransformMatrix1D.of(1, 0).hashCode());
752 }
753
754 @Test
755 void testEquals() {
756
757 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(1, 2);
758
759
760 GeometryTestUtils.assertSimpleEqualsCases(a);
761
762 Assertions.assertNotEquals(a, AffineTransformMatrix1D.of(0, 2));
763 Assertions.assertNotEquals(a, AffineTransformMatrix1D.of(1, 0));
764 }
765
766 @Test
767 void testEqualsAndHashCode_signedZeroConsistency() {
768
769 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(0.0, -0.0);
770 final AffineTransformMatrix1D b = AffineTransformMatrix1D.of(-0.0, 0.0);
771 final AffineTransformMatrix1D c = AffineTransformMatrix1D.of(0.0, -0.0);
772 final AffineTransformMatrix1D d = AffineTransformMatrix1D.of(-0.0, 0.0);
773
774
775 Assertions.assertFalse(a.equals(b));
776
777 Assertions.assertTrue(a.equals(c));
778 Assertions.assertEquals(a.hashCode(), c.hashCode());
779
780 Assertions.assertTrue(b.equals(d));
781 Assertions.assertEquals(b.hashCode(), d.hashCode());
782 }
783
784 @Test
785 void testToString() {
786
787 final AffineTransformMatrix1D a = AffineTransformMatrix1D.of(1, 2);
788
789
790 final String result = a.toString();
791
792
793 Assertions.assertEquals("[ 1.0, 2.0 ]", result);
794 }
795
796 @FunctionalInterface
797 private interface Coordinate1DTest {
798
799 void run(double x);
800 }
801
802 private static void runWithCoordinates(final Coordinate1DTest test) {
803 runWithCoordinates(test, false);
804 }
805
806 private static void runWithCoordinates(final Coordinate1DTest test, final boolean skipZero) {
807 runWithCoordinates(test, -1e-2, 1e-2, 5e-3, skipZero);
808 runWithCoordinates(test, -1e2, 1e2, 5, skipZero);
809 }
810
811 private static void runWithCoordinates(final Coordinate1DTest test, final double min, final double max, final double step, final boolean skipZero) {
812 for (double x = min; x <= max; x += step) {
813 if (!skipZero || x != 0.0) {
814 test.run(x);
815 }
816 }
817 }
818 }