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.Arrays;
20
21 import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
22 import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
23 import org.apache.commons.geometry.euclidean.threed.line.Lines3D;
24 import org.apache.commons.geometry.euclidean.threed.shape.Parallelepiped;
25 import org.junit.Test;
26
27 public class BoundarySourceLinecaster3DTest {
28
29 private static final double TEST_EPS = 1e-10;
30
31 private static final DoublePrecisionContext TEST_PRECISION =
32 new EpsilonDoublePrecisionContext(TEST_EPS);
33
34 private static final BoundarySource3D UNIT_CUBE = Parallelepiped.builder(TEST_PRECISION)
35 .setPosition(Vector3D.of(0.5, 0.5, 0.5))
36 .build();
37
38 @Test
39 public void testLinecast_line_simple() {
40
41 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
42
43
44
45
46 LinecastChecker3D.with(linecaster)
47 .expectNothing()
48 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0, 4, 4), Vector3D.Unit.MINUS_X, TEST_PRECISION));
49
50
51 LinecastChecker3D.with(linecaster)
52 .expect(Vector3D.of(0, 0.5, 0.5), Vector3D.Unit.MINUS_X)
53 .and(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
54 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0.5, 0.5, 0.5), Vector3D.Unit.PLUS_X, TEST_PRECISION));
55
56 LinecastChecker3D.with(linecaster)
57 .expect(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
58 .and(Vector3D.of(0, 0.5, 0.5), Vector3D.Unit.MINUS_X)
59 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0.5, 0.5, 0.5), Vector3D.Unit.MINUS_X, TEST_PRECISION));
60 }
61
62 @Test
63 public void testLinecast_line_alongFace() {
64
65 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
66
67
68 LinecastChecker3D.with(linecaster)
69 .expect(Vector3D.ZERO, Vector3D.Unit.MINUS_Y)
70 .and(Vector3D.ZERO, Vector3D.Unit.MINUS_Z)
71 .and(Vector3D.of(0, 1, 1), Vector3D.Unit.PLUS_Z)
72 .and(Vector3D.of(0, 1, 1), Vector3D.Unit.PLUS_Y)
73 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.ZERO, Vector3D.of(0, 1, 1), TEST_PRECISION));
74 }
75
76 @Test
77 public void testLinecast_line_corners() {
78
79 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
80
81
82
83
84 LinecastChecker3D.with(linecaster)
85 .expect(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Z)
86 .and(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Y)
87 .and(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_X)
88 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(1, 1, 1), Vector3D.of(1, -1, -1), TEST_PRECISION));
89
90
91 LinecastChecker3D.with(linecaster)
92 .expect(Vector3D.ZERO, Vector3D.Unit.MINUS_X)
93 .and(Vector3D.ZERO, Vector3D.Unit.MINUS_Y)
94 .and(Vector3D.ZERO, Vector3D.Unit.MINUS_Z)
95 .and(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Z)
96 .and(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Y)
97 .and(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_X)
98 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.ZERO, Vector3D.of(1, 1, 1), TEST_PRECISION));
99 }
100
101 @Test
102 public void testLinecast_line_removesDuplicatePoints() {
103
104 final BoundarySource3D src = BoundarySource3D.from(
105 Planes.convexPolygonFromVertices(Arrays.asList(Vector3D.ZERO, Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y), TEST_PRECISION),
106 Planes.convexPolygonFromVertices(Arrays.asList(Vector3D.ZERO, Vector3D.Unit.PLUS_Y, Vector3D.Unit.MINUS_X), TEST_PRECISION)
107 );
108 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(src);
109
110
111 LinecastChecker3D.with(linecaster)
112 .expect(Vector3D.of(0, 0.5, 0), Vector3D.Unit.PLUS_Z)
113 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(-1, 0.5, 1), Vector3D.of(1, 0, -1), TEST_PRECISION));
114 }
115
116 @Test
117 public void testLinecast_segment_simple() {
118
119 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
120
121
122
123
124 LinecastChecker3D.with(linecaster)
125 .expectNothing()
126 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0, 4, 4), Vector3D.Unit.MINUS_X, TEST_PRECISION)
127 .segment(-10, 10));
128
129
130 LinecastChecker3D.with(linecaster)
131 .expectNothing()
132 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0.5, 0.5, 0.5), Vector3D.Unit.PLUS_X, TEST_PRECISION)
133 .segment(2, 10));
134
135
136 LinecastChecker3D.with(linecaster)
137 .expect(Vector3D.of(0, 0.5, 0.5), Vector3D.Unit.MINUS_X)
138 .and(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
139 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0.5, 0.5, 0.5), Vector3D.Unit.PLUS_X, TEST_PRECISION)
140 .segment(-10, 10));
141
142 LinecastChecker3D.with(linecaster)
143 .expect(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
144 .and(Vector3D.of(0, 0.5, 0.5), Vector3D.Unit.MINUS_X)
145 .whenGiven(Lines3D.fromPointAndDirection(Vector3D.of(0.5, 0.5, 0.5), Vector3D.Unit.MINUS_X, TEST_PRECISION)
146 .segment(-10, 10));
147 }
148
149 @Test
150 public void testLinecast_segment_boundaryExcluded() {
151
152 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
153
154
155 final Vector3D center = Vector3D.of(0.5, 0.5, 0.5);
156 LinecastChecker3D.with(linecaster)
157 .expect(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
158 .whenGiven(Lines3D.fromPointAndDirection(center, Vector3D.Unit.PLUS_X, TEST_PRECISION)
159 .rayFrom(center));
160
161 LinecastChecker3D.with(linecaster)
162 .expect(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
163 .whenGiven(Lines3D.fromPointAndDirection(center, Vector3D.Unit.MINUS_X, TEST_PRECISION)
164 .reverseRayTo(center));
165 }
166
167 @Test
168 public void testLinecast_segment_startEndPointsOnBoundaries() {
169
170 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
171
172
173 LinecastChecker3D.with(linecaster)
174 .expect(Vector3D.of(1, 0.5, 0.5), Vector3D.Unit.PLUS_X)
175 .and(Vector3D.of(0, 0.5, 0.5), Vector3D.Unit.MINUS_X)
176 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(1, 0.5, 0.5), Vector3D.of(0, 0.5, 0.5), TEST_PRECISION));
177 }
178
179 @Test
180 public void testLinecast_segment_alongFace() {
181
182 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
183
184
185
186
187 LinecastChecker3D.with(linecaster)
188 .expect(Vector3D.of(0, 1, 0), Vector3D.Unit.MINUS_X)
189 .and(Vector3D.of(1, 1, 0), Vector3D.Unit.PLUS_X)
190 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(-1, 1, 0), Vector3D.of(2, 1, 0), TEST_PRECISION));
191
192
193 LinecastChecker3D.with(linecaster)
194 .expect(Vector3D.of(1, 1, 0), Vector3D.Unit.PLUS_X)
195 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(0.25, 1, 0), Vector3D.of(2, 1, 0), TEST_PRECISION));
196
197
198 LinecastChecker3D.with(linecaster)
199 .expectNothing()
200 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(0.25, 1, 0), Vector3D.of(0.75, 1, 0), TEST_PRECISION));
201 }
202
203 @Test
204 public void testLinecast_segment_corners() {
205
206 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(UNIT_CUBE);
207
208 final Vector3D corner = Vector3D.of(1, 1, 1);
209
210
211
212
213 LinecastChecker3D.with(linecaster)
214 .expect(corner, Vector3D.Unit.PLUS_Z)
215 .and(corner, Vector3D.Unit.PLUS_Y)
216 .and(corner, Vector3D.Unit.PLUS_X)
217 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(0.5, 0.5, 0.5), Vector3D.of(2, 2, 2), TEST_PRECISION));
218
219
220 LinecastChecker3D.with(linecaster)
221 .expect(corner, Vector3D.Unit.PLUS_Z)
222 .and(corner, Vector3D.Unit.PLUS_Y)
223 .and(corner, Vector3D.Unit.PLUS_X)
224 .whenGiven(Lines3D.segmentFromPoints(corner, Vector3D.of(2, 0, 2), TEST_PRECISION));
225
226
227 LinecastChecker3D.with(linecaster)
228 .expect(corner, Vector3D.Unit.PLUS_Z)
229 .and(corner, Vector3D.Unit.PLUS_Y)
230 .and(corner, Vector3D.Unit.PLUS_X)
231 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(0, 2, 2), corner, TEST_PRECISION));
232 }
233
234 @Test
235 public void testLinecast_segment_removesDuplicatePoints() {
236
237 final BoundarySource3D src = BoundarySource3D.from(
238 Planes.convexPolygonFromVertices(Arrays.asList(Vector3D.ZERO, Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y), TEST_PRECISION),
239 Planes.convexPolygonFromVertices(Arrays.asList(Vector3D.ZERO, Vector3D.Unit.PLUS_Y, Vector3D.Unit.MINUS_X), TEST_PRECISION)
240 );
241 final BoundarySourceLinecaster3D linecaster = new BoundarySourceLinecaster3D(src);
242
243
244 LinecastChecker3D.with(linecaster)
245 .expect(Vector3D.of(0, 0.5, 0), Vector3D.Unit.PLUS_Z)
246 .whenGiven(Lines3D.segmentFromPoints(Vector3D.of(-1, 0.5, 1), Vector3D.of(1, 0.5, -1), TEST_PRECISION));
247 }
248 }