1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.threed.line;
18
19 import org.apache.commons.geometry.core.GeometryTestUtils;
20 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
21 import org.apache.commons.geometry.euclidean.oned.Interval;
22 import org.apache.commons.geometry.euclidean.threed.AffineTransformMatrix3D;
23 import org.apache.commons.geometry.euclidean.threed.Vector3D;
24 import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
25 import org.apache.commons.numbers.core.Precision;
26 import org.junit.jupiter.api.Assertions;
27 import org.junit.jupiter.api.Test;
28
29 class ReverseRay3DTest {
30
31 private static final double TEST_EPS = 1e-10;
32
33 private static final Precision.DoubleEquivalence TEST_PRECISION =
34 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
35
36 @Test
37 void testFromPointAndDirection() {
38
39 final Vector3D pt = Vector3D.of(1, 1, 2);
40
41
42 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(pt, Vector3D.Unit.PLUS_Z, TEST_PRECISION);
43
44
45 Assertions.assertTrue(revRay.isInfinite());
46 Assertions.assertFalse(revRay.isFinite());
47
48 Assertions.assertNull(revRay.getStartPoint());
49 EuclideanTestUtils.assertCoordinatesEqual(pt, revRay.getEndPoint(), TEST_EPS);
50
51 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.PLUS_Z, revRay.getLine().getDirection(), TEST_EPS);
52
53 GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
54 Assertions.assertEquals(2, revRay.getSubspaceEnd(), TEST_EPS);
55
56 GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
57
58 Assertions.assertNull(revRay.getCentroid());
59 Assertions.assertNull(revRay.getBounds());
60 }
61
62 @Test
63 void testFromPointAndDirection_invalidArgs() {
64
65 final Vector3D pt = Vector3D.of(0, 2, 4);
66 final Vector3D dir = Vector3D.of(1e-11, 0, 0);
67
68
69 GeometryTestUtils.assertThrowsWithMessage(() -> {
70 Lines3D.reverseRayFromPointAndDirection(pt, dir, TEST_PRECISION);
71 }, IllegalArgumentException.class, "Line direction cannot be zero");
72 }
73
74 @Test
75 void testFromPoint() {
76
77 final Vector3D pt = Vector3D.of(-2, -1, 2);
78
79 final Line3D line = Lines3D.fromPointAndDirection(Vector3D.of(1, 0, 2), Vector3D.Unit.PLUS_Y, TEST_PRECISION);
80
81
82 final ReverseRay3D revRay = Lines3D.reverseRayFromPoint(line, pt);
83
84
85 Assertions.assertTrue(revRay.isInfinite());
86 Assertions.assertFalse(revRay.isFinite());
87
88 Assertions.assertNull(revRay.getStartPoint());
89 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(1, -1, 2), revRay.getEndPoint(), TEST_EPS);
90
91 GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
92 Assertions.assertEquals(-1, revRay.getSubspaceEnd(), TEST_EPS);
93
94 GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
95
96 Assertions.assertNull(revRay.getCentroid());
97 Assertions.assertNull(revRay.getBounds());
98 }
99
100 @Test
101 void testFromPoint_invalidArgs() {
102
103 final Line3D line = Lines3D.fromPointAndDirection(Vector3D.ZERO, Vector3D.Unit.PLUS_X, TEST_PRECISION);
104
105
106 GeometryTestUtils.assertThrowsWithMessage(() -> {
107 Lines3D.reverseRayFromPoint(line, Vector3D.NaN);
108 }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
109
110 GeometryTestUtils.assertThrowsWithMessage(() -> {
111 Lines3D.reverseRayFromPoint(line, Vector3D.NEGATIVE_INFINITY);
112 }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
113
114 GeometryTestUtils.assertThrowsWithMessage(() -> {
115 Lines3D.reverseRayFromPoint(line, Vector3D.POSITIVE_INFINITY);
116 }, IllegalArgumentException.class, "Invalid reverse ray end location: NaN");
117 }
118
119 @Test
120 void testFromLocation() {
121
122 final Line3D line = Lines3D.fromPointAndDirection(Vector3D.of(-1, 0, 0), Vector3D.Unit.PLUS_Z, TEST_PRECISION);
123
124
125 final ReverseRay3D revRay = Lines3D.reverseRayFromLocation(line, -1);
126
127
128 Assertions.assertTrue(revRay.isInfinite());
129 Assertions.assertFalse(revRay.isFinite());
130
131 Assertions.assertNull(revRay.getStartPoint());
132 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(-1, 0, -1), revRay.getEndPoint(), TEST_EPS);
133
134 GeometryTestUtils.assertNegativeInfinity(revRay.getSubspaceStart());
135 Assertions.assertEquals(-1, revRay.getSubspaceEnd(), TEST_EPS);
136
137 GeometryTestUtils.assertPositiveInfinity(revRay.getSize());
138
139 Assertions.assertNull(revRay.getCentroid());
140 Assertions.assertNull(revRay.getBounds());
141 }
142
143 @Test
144 void testTransform() {
145
146 final AffineTransformMatrix3D t = QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, 0.5 * Math.PI)
147 .toMatrix()
148 .translate(Vector3D.Unit.PLUS_Y);
149
150 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 0, 0), Vector3D.Unit.PLUS_X, TEST_PRECISION);
151
152
153 final ReverseRay3D result = revRay.transform(t);
154
155
156 Assertions.assertNull(result.getStartPoint());
157 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, -1), result.getEndPoint(), TEST_EPS);
158
159 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.MINUS_Z, result.getLine().getDirection(), TEST_EPS);
160 }
161
162 @Test
163 void testTransform_reflection() {
164
165 final AffineTransformMatrix3D t = QuaternionRotation.fromAxisAngle(Vector3D.Unit.PLUS_Y, 0.5 * Math.PI)
166 .toMatrix()
167 .translate(Vector3D.Unit.PLUS_Y)
168 .scale(1, 1, -2);
169
170 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 0, 0), Vector3D.Unit.PLUS_X, TEST_PRECISION);
171
172
173 final ReverseRay3D result = revRay.transform(t);
174
175
176 Assertions.assertNull(result.getStartPoint());
177 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.of(0, 1, 2), result.getEndPoint(), TEST_EPS);
178
179 EuclideanTestUtils.assertCoordinatesEqual(Vector3D.Unit.PLUS_Z, result.getLine().getDirection(), TEST_EPS);
180 }
181
182 @Test
183 void testContains() {
184
185 final Vector3D p0 = Vector3D.of(1, 1, 1);
186
187 final Vector3D delta = Vector3D.of(1e-12, 1e-12, 1e-12);
188
189 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_X, TEST_PRECISION);
190
191
192 Assertions.assertFalse(revRay.contains(Vector3D.of(2, 2, 2)));
193 Assertions.assertFalse(revRay.contains(Vector3D.of(1.1, 1, 1)));
194 Assertions.assertFalse(revRay.contains(Vector3D.of(100, 1, 1)));
195
196 Assertions.assertTrue(revRay.contains(p0));
197 Assertions.assertTrue(revRay.contains(p0.add(delta)));
198
199 Assertions.assertTrue(revRay.contains(Vector3D.of(-1000, 1, 1)));
200 }
201
202 @Test
203 void testGetInterval() {
204
205 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.of(2, -1, 3), Vector3D.Unit.PLUS_Y, TEST_PRECISION);
206
207
208 final Interval interval = revRay.getInterval();
209
210
211 GeometryTestUtils.assertNegativeInfinity(interval.getMin());
212 Assertions.assertEquals(-1, interval.getMax(), TEST_EPS);
213
214 Assertions.assertSame(revRay.getLine().getPrecision(), interval.getMaxBoundary().getPrecision());
215 }
216
217 @Test
218 void testToString() {
219
220 final ReverseRay3D revRay = Lines3D.reverseRayFromPointAndDirection(Vector3D.ZERO, Vector3D.Unit.PLUS_X, TEST_PRECISION);
221
222
223 final String str = revRay.toString();
224
225
226 GeometryTestUtils.assertContains("ReverseRay3D[direction= (1", str);
227 GeometryTestUtils.assertContains(", endPoint= (0", str);
228 }
229 }