1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.twod;
18
19 import org.apache.commons.geometry.euclidean.twod.shape.Parallelogram;
20 import org.apache.commons.numbers.core.Precision;
21 import org.junit.jupiter.api.Test;
22
23 class BoundarySourceLinecaster2DTest {
24
25 private static final double TEST_EPS = 1e-10;
26
27 private static final Precision.DoubleEquivalence TEST_PRECISION =
28 Precision.doubleEquivalenceOfEpsilon(TEST_EPS);
29
30 private static final BoundarySource2D UNIT_SQUARE =
31 Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION);
32
33 @Test
34 void testLinecast_line_simple() {
35
36 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
37
38
39
40
41 LinecastChecker2D.with(linecaster)
42 .expectNothing()
43 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 4), Vector2D.Unit.MINUS_X, TEST_PRECISION));
44
45
46 LinecastChecker2D.with(linecaster)
47 .expect(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
48 .and(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
49 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION));
50
51 LinecastChecker2D.with(linecaster)
52 .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
53 .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
54 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.MINUS_X, TEST_PRECISION));
55 }
56
57 @Test
58 void testLinecast_line_alongFace() {
59
60 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
61
62
63 LinecastChecker2D.with(linecaster)
64 .expect(Vector2D.of(0, 1), Vector2D.Unit.MINUS_X)
65 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
66 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 1), Vector2D.Unit.PLUS_X, TEST_PRECISION));
67 }
68
69 @Test
70 void testLinecast_line_corners() {
71
72 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
73
74
75
76
77 LinecastChecker2D.with(linecaster)
78 .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
79 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
80 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 2), Vector2D.of(1, -1), TEST_PRECISION));
81
82
83 LinecastChecker2D.with(linecaster)
84 .expect(Vector2D.ZERO, Vector2D.Unit.MINUS_X)
85 .and(Vector2D.ZERO, Vector2D.Unit.MINUS_Y)
86 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
87 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
88 .whenGiven(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION));
89 }
90
91 @Test
92 void testLinecast_line_removesDuplicatePoints() {
93
94 final BoundarySource2D src = BoundarySource2D.of(
95 Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.ZERO, TEST_PRECISION),
96 Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION)
97 );
98 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(src);
99
100
101 LinecastChecker2D.with(linecaster)
102 .expect(Vector2D.ZERO, Vector2D.Unit.from(1, -1))
103 .whenGiven(Lines.fromPointAndDirection(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION));
104 }
105
106 @Test
107 void testLinecast_segment_simple() {
108
109 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
110
111
112
113
114 LinecastChecker2D.with(linecaster)
115 .expectNothing()
116 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0, 4), Vector2D.Unit.MINUS_X, TEST_PRECISION)
117 .segment(-10, 10));
118
119
120 LinecastChecker2D.with(linecaster)
121 .expectNothing()
122 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION)
123 .segment(2, 10));
124
125
126 LinecastChecker2D.with(linecaster)
127 .expect(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
128 .and(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
129 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.PLUS_X, TEST_PRECISION)
130 .segment(-10, 10));
131
132 LinecastChecker2D.with(linecaster)
133 .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
134 .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
135 .whenGiven(Lines.fromPointAndDirection(Vector2D.of(0.5, 0.5), Vector2D.Unit.MINUS_X, TEST_PRECISION)
136 .segment(-10, 10));
137 }
138
139 @Test
140 void testLinecast_segment_boundaryExcluded() {
141
142 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
143
144
145 final Vector2D center = Vector2D.of(0.5, 0.5);
146 LinecastChecker2D.with(linecaster)
147 .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
148 .whenGiven(Lines.fromPointAndDirection(center, Vector2D.Unit.PLUS_X, TEST_PRECISION)
149 .rayFrom(center));
150
151 LinecastChecker2D.with(linecaster)
152 .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
153 .whenGiven(Lines.fromPointAndDirection(center, Vector2D.Unit.MINUS_X, TEST_PRECISION)
154 .reverseRayTo(center));
155 }
156
157 @Test
158 void testLinecast_segment_startEndPointsOnBoundaries() {
159
160 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
161
162
163 LinecastChecker2D.with(linecaster)
164 .expect(Vector2D.of(1, 0.5), Vector2D.Unit.PLUS_X)
165 .and(Vector2D.of(0, 0.5), Vector2D.Unit.MINUS_X)
166 .whenGiven(Lines.segmentFromPoints(Vector2D.of(1, 0.5), Vector2D.of(0, 0.5), TEST_PRECISION));
167 }
168
169 @Test
170 void testLinecast_segment_alongFace() {
171
172 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
173
174
175
176
177 LinecastChecker2D.with(linecaster)
178 .expect(Vector2D.of(0, 1), Vector2D.Unit.MINUS_X)
179 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
180 .whenGiven(Lines.segmentFromPoints(Vector2D.of(-1, 1), Vector2D.of(2, 1), TEST_PRECISION));
181
182
183 LinecastChecker2D.with(linecaster)
184 .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
185 .whenGiven(Lines.segmentFromPoints(Vector2D.of(0.25, 1), Vector2D.of(2, 1), TEST_PRECISION));
186
187
188 LinecastChecker2D.with(linecaster)
189 .expectNothing()
190 .whenGiven(Lines.segmentFromPoints(Vector2D.of(0.25, 1), Vector2D.of(0.75, 1), TEST_PRECISION));
191 }
192
193 @Test
194 void testLinecast_segment_corners() {
195
196 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(UNIT_SQUARE);
197
198
199
200
201 LinecastChecker2D.with(linecaster)
202 .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
203 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
204 .whenGiven(Lines.segmentFromPoints(Vector2D.of(0, 2), Vector2D.of(2, 0), TEST_PRECISION));
205
206
207 LinecastChecker2D.with(linecaster)
208 .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
209 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
210 .whenGiven(Lines.segmentFromPoints(Vector2D.of(1, 1), Vector2D.of(2, 0), TEST_PRECISION));
211
212
213 LinecastChecker2D.with(linecaster)
214 .expect(Vector2D.of(1, 1), Vector2D.Unit.PLUS_Y)
215 .and(Vector2D.of(1, 1), Vector2D.Unit.PLUS_X)
216 .whenGiven(Lines.segmentFromPoints(Vector2D.of(0, 2), Vector2D.of(1, 1), TEST_PRECISION));
217 }
218
219 @Test
220 void testLinecast_segment_removesDuplicatePoints() {
221
222 final BoundarySource2D src = BoundarySource2D.of(
223 Lines.segmentFromPoints(Vector2D.of(-1, -1), Vector2D.ZERO, TEST_PRECISION),
224 Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION)
225 );
226 final BoundarySourceLinecaster2D linecaster = new BoundarySourceLinecaster2D(src);
227
228
229 LinecastChecker2D.with(linecaster)
230 .expect(Vector2D.ZERO, Vector2D.Unit.from(1, -1))
231 .whenGiven(Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.Unit.PLUS_X, TEST_PRECISION));
232 }
233 }
234