1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.spherical.oned;
18
19 import java.util.List;
20
21 import org.apache.commons.geometry.core.RegionLocation;
22 import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;
23 import org.apache.commons.geometry.core.partitioning.HyperplaneLocation;
24 import org.apache.commons.geometry.core.partitioning.Split;
25 import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
26 import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
27 import org.apache.commons.geometry.spherical.SphericalTestUtils;
28 import org.apache.commons.numbers.angle.PlaneAngleRadians;
29 import org.junit.Assert;
30 import org.junit.Test;
31
32 public class CutAngleTest {
33
34 private static final double TEST_EPS = 1e-10;
35
36 private static final DoublePrecisionContext TEST_PRECISION =
37 new EpsilonDoublePrecisionContext(TEST_EPS);
38
39 @Test
40 public void testFromAzimuthAndDirection() {
41
42 checkCutAngle(CutAngles.fromAzimuthAndDirection(0.0, true, TEST_PRECISION),
43 0.0, true);
44 checkCutAngle(CutAngles.fromAzimuthAndDirection(PlaneAngleRadians.PI, true, TEST_PRECISION),
45 PlaneAngleRadians.PI, true);
46 checkCutAngle(CutAngles.fromAzimuthAndDirection(-PlaneAngleRadians.PI_OVER_TWO, true, TEST_PRECISION),
47 -PlaneAngleRadians.PI_OVER_TWO, true);
48
49 checkCutAngle(CutAngles.fromAzimuthAndDirection(0.0, false, TEST_PRECISION),
50 0.0, false);
51 checkCutAngle(CutAngles.fromAzimuthAndDirection(PlaneAngleRadians.PI, false, TEST_PRECISION),
52 PlaneAngleRadians.PI, false);
53 checkCutAngle(CutAngles.fromAzimuthAndDirection(-PlaneAngleRadians.PI_OVER_TWO, false, TEST_PRECISION),
54 -PlaneAngleRadians.PI_OVER_TWO, false);
55 }
56
57 @Test
58 public void testFromPointAndDirection() {
59
60 final Point1S pt = Point1S.of(-PlaneAngleRadians.PI_OVER_TWO);
61
62
63 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION),
64 0.0, true);
65 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION),
66 PlaneAngleRadians.PI, true);
67 checkCutAngle(CutAngles.fromPointAndDirection(pt, true, TEST_PRECISION),
68 -PlaneAngleRadians.PI_OVER_TWO, true);
69
70 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION),
71 0.0, false);
72 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.PI, false, TEST_PRECISION),
73 PlaneAngleRadians.PI, false);
74 checkCutAngle(CutAngles.fromPointAndDirection(pt, false, TEST_PRECISION),
75 -PlaneAngleRadians.PI_OVER_TWO, false);
76 }
77
78 @Test
79 public void testCreatePositiveFacing() {
80
81 checkCutAngle(CutAngles.createPositiveFacing(Point1S.ZERO, TEST_PRECISION),
82 0.0, true);
83 checkCutAngle(CutAngles.createPositiveFacing(Point1S.PI, TEST_PRECISION),
84 PlaneAngleRadians.PI, true);
85 checkCutAngle(CutAngles.createPositiveFacing(-PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION),
86 -PlaneAngleRadians.PI_OVER_TWO, true);
87 }
88
89 @Test
90 public void testCreateNegativeFacing() {
91
92 checkCutAngle(CutAngles.createNegativeFacing(Point1S.ZERO, TEST_PRECISION),
93 0.0, false);
94 checkCutAngle(CutAngles.createNegativeFacing(Point1S.PI, TEST_PRECISION),
95 PlaneAngleRadians.PI, false);
96 checkCutAngle(CutAngles.createNegativeFacing(-PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION),
97 -PlaneAngleRadians.PI_OVER_TWO, false);
98 }
99
100 @Test
101 public void testOffset() {
102
103 final CutAngle zeroPos = CutAngles.createPositiveFacing(0.0, TEST_PRECISION);
104 final CutAngle zeroNeg = CutAngles.createNegativeFacing(0.0, TEST_PRECISION);
105 final CutAngle negPiPos = CutAngles.createPositiveFacing(-PlaneAngleRadians.PI, TEST_PRECISION);
106
107 final CutAngle piNeg = CutAngles.createNegativeFacing(PlaneAngleRadians.PI, TEST_PRECISION);
108 final CutAngle twoAndAHalfPiPos = CutAngles.createPositiveFacing(2.5 * PlaneAngleRadians.PI, TEST_PRECISION);
109
110
111 checkOffset(zeroPos, 0, 0);
112 checkOffset(zeroPos, PlaneAngleRadians.TWO_PI, 0);
113 checkOffset(zeroPos, 2.5 * PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
114 checkOffset(zeroPos, PlaneAngleRadians.PI, PlaneAngleRadians.PI);
115 checkOffset(zeroPos, 3.5 * PlaneAngleRadians.PI, 1.5 * PlaneAngleRadians.PI);
116
117 checkOffset(zeroNeg, 0, 0);
118 checkOffset(zeroNeg, PlaneAngleRadians.TWO_PI, 0);
119 checkOffset(zeroNeg, 2.5 * PlaneAngleRadians.PI, -PlaneAngleRadians.PI_OVER_TWO);
120 checkOffset(zeroNeg, PlaneAngleRadians.PI, -PlaneAngleRadians.PI);
121 checkOffset(zeroNeg, 3.5 * PlaneAngleRadians.PI, -1.5 * PlaneAngleRadians.PI);
122
123 checkOffset(negPiPos, 0, -PlaneAngleRadians.PI);
124 checkOffset(negPiPos, PlaneAngleRadians.TWO_PI, -PlaneAngleRadians.PI);
125 checkOffset(negPiPos, 2.5 * PlaneAngleRadians.PI, -PlaneAngleRadians.PI_OVER_TWO);
126 checkOffset(negPiPos, PlaneAngleRadians.PI, 0);
127 checkOffset(negPiPos, 3.5 * PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
128
129 checkOffset(piNeg, 0, PlaneAngleRadians.PI);
130 checkOffset(piNeg, PlaneAngleRadians.TWO_PI, PlaneAngleRadians.PI);
131 checkOffset(piNeg, 2.5 * PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
132 checkOffset(piNeg, PlaneAngleRadians.PI, 0);
133 checkOffset(piNeg, 3.5 * PlaneAngleRadians.PI, -PlaneAngleRadians.PI_OVER_TWO);
134
135 checkOffset(twoAndAHalfPiPos, 0, -PlaneAngleRadians.PI_OVER_TWO);
136 checkOffset(twoAndAHalfPiPos, PlaneAngleRadians.TWO_PI, -PlaneAngleRadians.PI_OVER_TWO);
137 checkOffset(twoAndAHalfPiPos, 2.5 * PlaneAngleRadians.PI, 0);
138 checkOffset(twoAndAHalfPiPos, PlaneAngleRadians.PI, PlaneAngleRadians.PI_OVER_TWO);
139 checkOffset(twoAndAHalfPiPos, 3.5 * PlaneAngleRadians.PI, PlaneAngleRadians.PI);
140 }
141
142 @Test
143 public void testClassify() {
144
145 final CutAngle zeroPos = CutAngles.createPositiveFacing(0.0, TEST_PRECISION);
146 final CutAngle zeroNeg = CutAngles.createNegativeFacing(0.0, TEST_PRECISION);
147 final CutAngle negPiPos = CutAngles.createPositiveFacing(-PlaneAngleRadians.PI, TEST_PRECISION);
148
149
150 checkClassify(zeroPos, HyperplaneLocation.ON,
151 0, 1e-16, -1e-16,
152 PlaneAngleRadians.TWO_PI - 1e-11, PlaneAngleRadians.TWO_PI + 1e-11);
153 checkClassify(zeroPos, HyperplaneLocation.PLUS,
154 0.5, 2.5 * PlaneAngleRadians.PI,
155 -0.5, -PlaneAngleRadians.PI_OVER_TWO);
156
157 checkClassify(zeroNeg, HyperplaneLocation.ON,
158 0, 1e-16, -1e-16,
159 PlaneAngleRadians.TWO_PI - 1e-11, PlaneAngleRadians.TWO_PI + 1e-11);
160 checkClassify(zeroNeg, HyperplaneLocation.MINUS,
161 0.5, 2.5 * PlaneAngleRadians.PI,
162 -0.5, -PlaneAngleRadians.PI_OVER_TWO);
163
164 checkClassify(negPiPos, HyperplaneLocation.ON, PlaneAngleRadians.PI, PlaneAngleRadians.PI + 1e-11);
165 checkClassify(negPiPos, HyperplaneLocation.MINUS, 0.5, 2.5 * PlaneAngleRadians.PI,
166 0, 1e-11, PlaneAngleRadians.TWO_PI, PlaneAngleRadians.TWO_PI - 1e-11);
167 checkClassify(negPiPos, HyperplaneLocation.PLUS, -0.5, -PlaneAngleRadians.PI_OVER_TWO);
168 }
169
170 @Test
171 public void testContains() {
172
173 final CutAngle pt = CutAngles.createNegativeFacing(PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION);
174
175
176 Assert.assertFalse(pt.contains(Point1S.ZERO));
177 Assert.assertFalse(pt.contains(Point1S.of(PlaneAngleRadians.TWO_PI)));
178
179 Assert.assertFalse(pt.contains(Point1S.of(PlaneAngleRadians.PI)));
180 Assert.assertFalse(pt.contains(Point1S.of(0.25 * PlaneAngleRadians.PI)));
181 Assert.assertFalse(pt.contains(Point1S.of(-0.25 * PlaneAngleRadians.PI)));
182
183 Assert.assertTrue(pt.contains(Point1S.of(PlaneAngleRadians.PI_OVER_TWO)));
184 Assert.assertTrue(pt.contains(Point1S.of(PlaneAngleRadians.PI_OVER_TWO + 1e-11)));
185 Assert.assertTrue(pt.contains(Point1S.of(2.5 * PlaneAngleRadians.PI)));
186 Assert.assertTrue(pt.contains(Point1S.of(-3.5 * PlaneAngleRadians.PI)));
187 }
188
189 @Test
190 public void testReverse() {
191
192 final CutAngle pt = CutAngles.createNegativeFacing(PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION);
193
194
195 final CutAngle result = pt.reverse();
196
197
198 checkCutAngle(result, PlaneAngleRadians.PI_OVER_TWO, true);
199 Assert.assertSame(TEST_PRECISION, result.getPrecision());
200
201 checkCutAngle(result.reverse(), PlaneAngleRadians.PI_OVER_TWO, false);
202 }
203
204 @Test
205 public void testProject() {
206
207 final CutAngle pt = CutAngles.createNegativeFacing(PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION);
208
209
210 for (double az = -PlaneAngleRadians.TWO_PI; az <= PlaneAngleRadians.TWO_PI; az += 0.2) {
211 Assert.assertEquals(PlaneAngleRadians.PI_OVER_TWO, pt.project(Point1S.of(az)).getAzimuth(), TEST_EPS);
212 }
213 }
214
215 @Test
216 public void testSimilarOrientation() {
217
218 final CutAngle a = CutAngles.createPositiveFacing(0.0, TEST_PRECISION);
219 final CutAngle b = CutAngles.createNegativeFacing(0.0, TEST_PRECISION);
220 final CutAngle c = CutAngles.createPositiveFacing(-PlaneAngleRadians.PI_OVER_TWO, TEST_PRECISION);
221
222
223 Assert.assertTrue(a.similarOrientation(a));
224 Assert.assertFalse(a.similarOrientation(b));
225 Assert.assertTrue(a.similarOrientation(c));
226 }
227
228 @Test
229 public void testTransform_rotate() {
230
231 final Transform1S transform = Transform1S.createRotation(PlaneAngleRadians.PI_OVER_TWO);
232
233
234 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION).transform(transform),
235 PlaneAngleRadians.PI_OVER_TWO, true);
236 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION).transform(transform),
237 PlaneAngleRadians.PI_OVER_TWO, false);
238
239 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.of(1.5 * PlaneAngleRadians.PI), true, TEST_PRECISION).transform(transform),
240 PlaneAngleRadians.TWO_PI, true);
241 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.of(-PlaneAngleRadians.PI_OVER_TWO), false, TEST_PRECISION).transform(transform),
242 0.0, false);
243 }
244
245 @Test
246 public void testTransform_negate() {
247
248 final Transform1S transform = Transform1S.createNegation();
249
250
251 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION).transform(transform),
252 0.0, false);
253 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION).transform(transform),
254 0.0, true);
255
256 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.of(1.5 * PlaneAngleRadians.PI), true, TEST_PRECISION).transform(transform),
257 -1.5 * PlaneAngleRadians.PI, false);
258 checkCutAngle(CutAngles.fromPointAndDirection(Point1S.of(-PlaneAngleRadians.PI_OVER_TWO), false, TEST_PRECISION).transform(transform),
259 PlaneAngleRadians.PI_OVER_TWO, true);
260 }
261
262 @Test
263 public void testSpan() {
264
265 final CutAngle pt = CutAngles.fromPointAndDirection(Point1S.of(1.0), false, TEST_PRECISION);
266
267
268 final HyperplaneConvexSubset<Point1S> result = pt.span();
269
270
271 Assert.assertSame(pt, result.getHyperplane());
272 }
273
274 @Test
275 public void testEq() {
276
277 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
278
279 final CutAngle a = CutAngles.fromPointAndDirection(Point1S.ZERO, true, precision);
280
281 final CutAngle b = CutAngles.fromPointAndDirection(Point1S.PI, true, precision);
282 final CutAngle c = CutAngles.fromPointAndDirection(Point1S.ZERO, false, precision);
283 final CutAngle d = CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION);
284
285 final CutAngle e = CutAngles.fromPointAndDirection(Point1S.ZERO, true, precision);
286 final CutAngle f = CutAngles.fromPointAndDirection(Point1S.of(PlaneAngleRadians.TWO_PI), true, precision);
287 final CutAngle g = CutAngles.fromPointAndDirection(Point1S.of(1e-4), true, precision);
288 final CutAngle h = CutAngles.fromPointAndDirection(Point1S.of(-1e-4), true, precision);
289
290
291 Assert.assertTrue(a.eq(a, precision));
292
293 Assert.assertFalse(a.eq(b, precision));
294 Assert.assertFalse(a.eq(c, precision));
295
296 Assert.assertTrue(a.eq(d, precision));
297 Assert.assertTrue(a.eq(e, precision));
298 Assert.assertTrue(a.eq(f, precision));
299 Assert.assertTrue(a.eq(g, precision));
300 Assert.assertTrue(a.eq(h, precision));
301 }
302
303 @Test
304 public void testHashCode() {
305
306 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
307
308 final CutAngle a = CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION);
309 final CutAngle b = CutAngles.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION);
310 final CutAngle c = CutAngles.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION);
311 final CutAngle d = CutAngles.fromPointAndDirection(Point1S.ZERO, true, precision);
312 final CutAngle e = CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION);
313
314 final int hash = a.hashCode();
315
316
317 Assert.assertEquals(hash, a.hashCode());
318
319 Assert.assertNotEquals(hash, b.hashCode());
320 Assert.assertNotEquals(hash, c.hashCode());
321 Assert.assertNotEquals(hash, d.hashCode());
322
323 Assert.assertEquals(hash, e.hashCode());
324 }
325
326 @Test
327 public void testEquals() {
328
329 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
330
331 final CutAngle a = CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION);
332 final CutAngle b = CutAngles.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION);
333 final CutAngle c = CutAngles.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION);
334 final CutAngle d = CutAngles.fromPointAndDirection(Point1S.ZERO, true, precision);
335 final CutAngle e = CutAngles.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION);
336
337
338 Assert.assertFalse(a.equals(null));
339 Assert.assertFalse(a.equals(new Object()));
340
341 Assert.assertEquals(a, a);
342
343 Assert.assertNotEquals(a, b);
344 Assert.assertNotEquals(a, c);
345 Assert.assertNotEquals(a, d);
346
347 Assert.assertEquals(a, e);
348 }
349
350 @Test
351 public void testToString() {
352
353 final CutAngle pt = CutAngles.createPositiveFacing(0.0, TEST_PRECISION);
354
355
356 final String str = pt.toString();
357
358
359 Assert.assertTrue(str.startsWith("CutAngle["));
360 Assert.assertTrue(str.contains("point= ") && str.contains("positiveFacing= "));
361 }
362
363 @Test
364 public void testSubset_split() {
365
366 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
367
368 final CutAngle pt = CutAngles.createPositiveFacing(-1.5, precision);
369 final HyperplaneConvexSubset<Point1S> sub = pt.span();
370
371
372 checkSplit(sub, CutAngles.createPositiveFacing(1.0, precision), false, true);
373 checkSplit(sub, CutAngles.createPositiveFacing(-1.5 + 1e-2, precision), true, false);
374
375 checkSplit(sub, CutAngles.createNegativeFacing(1.0, precision), true, false);
376 checkSplit(sub, CutAngles.createNegativeFacing(-1.5 + 1e-2, precision), false, true);
377
378 checkSplit(sub, CutAngles.createNegativeFacing(-1.5, precision), false, false);
379 checkSplit(sub, CutAngles.createNegativeFacing(-1.5 + 1e-4, precision), false, false);
380 checkSplit(sub, CutAngles.createNegativeFacing(-1.5 - 1e-4, precision), false, false);
381 }
382
383 private void checkSplit(final HyperplaneConvexSubset<Point1S> sub, final CutAngle splitter, final boolean minus, final boolean plus) {
384 final Split<? extends HyperplaneConvexSubset<Point1S>> split = sub.split(splitter);
385
386 Assert.assertSame(minus ? sub : null, split.getMinus());
387 Assert.assertSame(plus ? sub : null, split.getPlus());
388 }
389
390 @Test
391 public void testSubset_simpleMethods() {
392
393 final CutAngle pt = CutAngles.createPositiveFacing(1, TEST_PRECISION);
394 final HyperplaneConvexSubset<Point1S> sub = pt.span();
395
396
397 Assert.assertSame(pt, sub.getHyperplane());
398 Assert.assertFalse(sub.isFull());
399 Assert.assertFalse(sub.isEmpty());
400 Assert.assertFalse(sub.isInfinite());
401 Assert.assertTrue(sub.isFinite());
402 Assert.assertEquals(0.0, sub.getSize(), TEST_EPS);
403 SphericalTestUtils.assertPointsEqual(Point1S.of(1), sub.getCentroid(), TEST_EPS);
404
405 final List<? extends HyperplaneConvexSubset<Point1S>> list = sub.toConvex();
406 Assert.assertEquals(1, list.size());
407 Assert.assertSame(sub, list.get(0));
408 }
409
410 @Test
411 public void testSubset_classify() {
412
413 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
414 final CutAngle pt = CutAngles.createPositiveFacing(1, precision);
415 final HyperplaneConvexSubset<Point1S> sub = pt.span();
416
417
418 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(0.95)));
419 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(1)));
420 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(1.05)));
421
422 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(1.11)));
423 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(0.89)));
424
425 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(-3)));
426 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(10)));
427 }
428
429 @Test
430 public void testSubset_contains() {
431
432 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
433 final CutAngle pt = CutAngles.createPositiveFacing(1, precision);
434 final HyperplaneConvexSubset<Point1S> sub = pt.span();
435
436
437 Assert.assertTrue(sub.contains(Point1S.of(0.95)));
438 Assert.assertTrue(sub.contains(Point1S.of(1)));
439 Assert.assertTrue(sub.contains(Point1S.of(1.05)));
440
441 Assert.assertFalse(sub.contains(Point1S.of(1.11)));
442 Assert.assertFalse(sub.contains(Point1S.of(0.89)));
443
444 Assert.assertFalse(sub.contains(Point1S.of(-3)));
445 Assert.assertFalse(sub.contains(Point1S.of(10)));
446 }
447
448 @Test
449 public void testSubset_closestContained() {
450
451 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
452 final CutAngle pt = CutAngles.createPositiveFacing(1, precision);
453 final HyperplaneConvexSubset<Point1S> sub = pt.span();
454
455 final Point1S expected = Point1S.of(1);
456
457
458 Assert.assertEquals(expected, sub.closest(Point1S.ZERO));
459 Assert.assertEquals(expected, sub.closest(Point1S.of(PlaneAngleRadians.PI_OVER_TWO)));
460 Assert.assertEquals(expected, sub.closest(Point1S.PI));
461 Assert.assertEquals(expected, sub.closest(Point1S.of(-PlaneAngleRadians.PI_OVER_TWO)));
462 Assert.assertEquals(expected, sub.closest(Point1S.of(PlaneAngleRadians.TWO_PI)));
463 }
464
465 @Test
466 public void testSubset_transform() {
467
468 final CutAngle pt = CutAngles.fromPointAndDirection(Point1S.of(PlaneAngleRadians.PI_OVER_TWO), true, TEST_PRECISION);
469
470 final Transform1S transform = Transform1S.createNegation().rotate(PlaneAngleRadians.PI);
471
472
473 final HyperplaneConvexSubset<Point1S> result = pt.span().transform(transform);
474
475
476 checkCutAngle((CutAngle) result.getHyperplane(), PlaneAngleRadians.PI_OVER_TWO, false);
477 }
478
479 @Test
480 public void testSubset_reverse() {
481
482 final CutAngle pt = CutAngles.createPositiveFacing(2.0, TEST_PRECISION);
483 final HyperplaneConvexSubset<Point1S> sub = pt.span();
484
485
486 final HyperplaneConvexSubset<Point1S> result = sub.reverse();
487
488
489 Assert.assertEquals(2.0, ((CutAngle) result.getHyperplane()).getAzimuth(), TEST_EPS);
490 Assert.assertFalse(((CutAngle) result.getHyperplane()).isPositiveFacing());
491
492 Assert.assertEquals(sub.getHyperplane(), result.reverse().getHyperplane());
493 }
494
495 @Test
496 public void testSubset_toString() {
497
498 final CutAngle pt = CutAngles.createPositiveFacing(2, TEST_PRECISION);
499 final HyperplaneConvexSubset<Point1S> sub = pt.span();
500
501
502 final String str = sub.toString();
503
504
505 Assert.assertTrue(str.contains("CutAngleConvexSubset["));
506 Assert.assertTrue(str.contains("point= "));
507 Assert.assertTrue(str.contains("positiveFacing= "));
508 }
509
510 private static void checkCutAngle(final CutAngle angle, final double az, final boolean positiveFacing) {
511 checkCutAngle(angle, az, positiveFacing, TEST_PRECISION);
512 }
513
514 private static void checkCutAngle(final CutAngle angle, final double az, final boolean positiveFacing, final DoublePrecisionContext precision) {
515 Assert.assertEquals(az, angle.getAzimuth(), TEST_EPS);
516 Assert.assertEquals(PlaneAngleRadians.normalizeBetweenZeroAndTwoPi(az), angle.getNormalizedAzimuth(), TEST_EPS);
517 Assert.assertEquals(az, angle.getPoint().getAzimuth(), TEST_EPS);
518 Assert.assertEquals(positiveFacing, angle.isPositiveFacing());
519
520 Assert.assertSame(precision, angle.getPrecision());
521 }
522
523 private static void checkOffset(final CutAngle pt, final double az, final double offset) {
524 Assert.assertEquals(offset, pt.offset(Point1S.of(az)), TEST_EPS);
525 }
526
527 private static void checkClassify(final CutAngle pt, final HyperplaneLocation loc, final double... azimuths) {
528 for (final double az : azimuths) {
529 Assert.assertEquals("Unexpected location for azimuth " + az, loc, pt.classify(Point1S.of(az)));
530 }
531 }
532 }