1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.threed;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.apache.commons.geometry.euclidean.threed.line.Line3D;
23 import org.apache.commons.geometry.euclidean.threed.line.LineConvexSubset3D;
24 import org.apache.commons.geometry.euclidean.threed.line.LinecastPoint3D;
25 import org.apache.commons.geometry.euclidean.threed.line.Linecastable3D;
26 import org.apache.commons.numbers.core.Precision;
27 import org.junit.jupiter.api.Assertions;
28
29
30
31 class LinecastChecker3D {
32
33 private static final double TEST_EPS = 1e-10;
34
35 private static final Precision.DoubleEquivalence TEST_PRECISION =
36 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
37
38
39 private final Linecastable3D target;
40
41
42 private final List<ExpectedResult> expectedResults = new ArrayList<>();
43
44
45
46
47
48 LinecastChecker3D(final Linecastable3D target) {
49 this.target = target;
50 }
51
52
53
54
55
56
57 public LinecastChecker3D expectNothing() {
58 expectedResults.clear();
59
60 return this;
61 }
62
63
64
65
66
67
68
69
70 public LinecastChecker3D expect(final Vector3D point, final Vector3D normal) {
71 expectedResults.add(new ExpectedResult(point, normal));
72
73 return this;
74 }
75
76
77
78
79
80
81 public LinecastChecker3D and(final Vector3D point, final Vector3D normal) {
82 return expect(point, normal);
83 }
84
85
86
87
88
89
90 public void whenGiven(final Line3D line) {
91 checkLinecastResults(target.linecast(line), line);
92 checkLinecastFirstResult(target.linecastFirst(line), line);
93 }
94
95
96
97
98
99
100 public void whenGiven(final LineConvexSubset3D segment) {
101 final Line3D line = segment.getLine();
102
103 checkLinecastResults(target.linecast(segment), line);
104 checkLinecastFirstResult(target.linecastFirst(segment), line);
105 }
106
107
108
109
110
111 private void checkLinecastResults(final List<? extends LinecastPoint3D> results, final Line3D line) {
112 Assertions.assertNotNull(results, "Linecast result list cannot be null");
113 Assertions.assertEquals(expectedResults.size(), results.size(), "Unexpected result size for linecast");
114
115 for (int i = 0; i < expectedResults.size(); ++i) {
116 final LinecastPoint3D expected = toLinecastPoint(expectedResults.get(i), line);
117 final LinecastPoint3D actual = results.get(i);
118
119 if (!eq(expected, actual)) {
120 Assertions.fail("Unexpected linecast point at index " + i + " expected " + expected +
121 " but was " + actual);
122 }
123 }
124 }
125
126
127
128
129
130 private void checkLinecastFirstResult(final LinecastPoint3D result, final Line3D line) {
131 if (expectedResults.isEmpty()) {
132 Assertions.assertNull(result, "Expected linecastFirst result to be null");
133 } else {
134 final LinecastPoint3D expected = toLinecastPoint(expectedResults.get(0), line);
135
136 Assertions.assertNotNull(result, "Expected linecastFirst result to not be null");
137
138 if (!eq(expected, result)) {
139 Assertions.fail("Unexpected result from linecastFirst: expected " + expected +
140 " but was " + result);
141 }
142 }
143 }
144
145
146
147
148
149 public static LinecastChecker3D with(final Linecastable3D src) {
150 return new LinecastChecker3D(src);
151 }
152
153
154
155
156
157
158 private static boolean eq(final LinecastPoint3D a, final LinecastPoint3D b) {
159 return a.getPoint().eq(b.getPoint(), TEST_PRECISION) &&
160 a.getNormal().eq(b.getNormal(), TEST_PRECISION) &&
161 a.getLine().equals(b.getLine()) &&
162 TEST_PRECISION.eq(a.getAbscissa(), b.getAbscissa());
163 }
164
165
166
167
168
169
170
171 private static LinecastPoint3D toLinecastPoint(final ExpectedResult expected, final Line3D line) {
172 return new LinecastPoint3D(expected.getPoint(), expected.getNormal(), line);
173 }
174
175
176
177 private static final class ExpectedResult {
178 private final Vector3D point;
179 private final Vector3D normal;
180
181 ExpectedResult(final Vector3D point, final Vector3D normal) {
182 this.point = point;
183 this.normal = normal;
184 }
185
186 public Vector3D getPoint() {
187 return point;
188 }
189
190 public Vector3D getNormal() {
191 return normal;
192 }
193 }
194 }