1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.oned;
18
19 import java.util.List;
20
21 import org.apache.commons.geometry.core.GeometryTestUtils;
22 import org.apache.commons.geometry.core.RegionLocation;
23 import org.apache.commons.geometry.core.Transform;
24 import org.apache.commons.geometry.core.partitioning.HyperplaneConvexSubset;
25 import org.apache.commons.geometry.core.partitioning.HyperplaneLocation;
26 import org.apache.commons.geometry.core.partitioning.Split;
27 import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
28 import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
29 import org.apache.commons.geometry.euclidean.EuclideanTestUtils;
30 import org.apache.commons.numbers.core.Precision;
31 import org.junit.Assert;
32 import org.junit.Test;
33
34 public class OrientedPointTest {
35
36 private static final double TEST_EPS = 1e-15;
37
38 private static final DoublePrecisionContext TEST_PRECISION =
39 new EpsilonDoublePrecisionContext(TEST_EPS);
40
41 @Test
42 public void testGetDirection() {
43
44 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.Unit.PLUS,
45 OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, TEST_PRECISION).getDirection(),
46 TEST_EPS);
47 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.Unit.MINUS,
48 OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), false, TEST_PRECISION).getDirection(),
49 TEST_EPS);
50 }
51
52 @Test
53 public void testReverse() {
54
55 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(0), true, TEST_PRECISION).reverse(),
56 0.0, false, TEST_PRECISION);
57 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(-1), false, TEST_PRECISION).reverse(),
58 -1.0, true, TEST_PRECISION);
59 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(1), true, TEST_PRECISION).reverse(),
60 1.0, false, TEST_PRECISION);
61
62 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(0), true, TEST_PRECISION).reverse().reverse(),
63 0.0, true, TEST_PRECISION);
64 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(-1), false, TEST_PRECISION).reverse().reverse(),
65 -1.0, false, TEST_PRECISION);
66 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(1), true, TEST_PRECISION).reverse().reverse(),
67 1.0, true, TEST_PRECISION);
68 }
69
70 @Test
71 public void testTransform() {
72
73 final AffineTransformMatrix1D scaleAndTranslate = AffineTransformMatrix1D
74 .createScale(0.5)
75 .translate(-10);
76
77 final AffineTransformMatrix1D reflect = AffineTransformMatrix1D.createScale(-2);
78
79 final OrientedPoint a = OrientedPoints.createPositiveFacing(Vector1D.of(2.0), TEST_PRECISION);
80 final OrientedPoint b = OrientedPoints.createNegativeFacing(Vector1D.of(-3.0), TEST_PRECISION);
81
82
83 assertOrientedPoint(a.transform(scaleAndTranslate), -9.0, true, TEST_PRECISION);
84 assertOrientedPoint(b.transform(scaleAndTranslate), -11.5, false, TEST_PRECISION);
85
86 assertOrientedPoint(a.transform(reflect), -4.0, false, TEST_PRECISION);
87 assertOrientedPoint(b.transform(reflect), 6.0, true, TEST_PRECISION);
88 }
89
90 @Test
91 public void testTransform_locationAtInfinity() {
92
93 final OrientedPoint pos = OrientedPoints.createNegativeFacing(Double.POSITIVE_INFINITY, TEST_PRECISION);
94 final OrientedPoint neg = OrientedPoints.createPositiveFacing(Double.NEGATIVE_INFINITY, TEST_PRECISION);
95
96 final Transform<Vector1D> scaleAndTranslate = AffineTransformMatrix1D.identity().scale(10.0).translate(5.0);
97 final Transform<Vector1D> negate = AffineTransformMatrix1D.from(Vector1D::negate);
98
99
100 assertOrientedPoint(pos.transform(scaleAndTranslate), Double.POSITIVE_INFINITY, false, TEST_PRECISION);
101 assertOrientedPoint(neg.transform(scaleAndTranslate), Double.NEGATIVE_INFINITY, true, TEST_PRECISION);
102
103 assertOrientedPoint(pos.transform(negate), Double.NEGATIVE_INFINITY, true, TEST_PRECISION);
104 assertOrientedPoint(neg.transform(negate), Double.POSITIVE_INFINITY, false, TEST_PRECISION);
105 }
106
107 @Test
108 public void testTransform_zeroScale() {
109
110 final AffineTransformMatrix1D zeroScale = AffineTransformMatrix1D.createScale(0.0);
111
112 final OrientedPoint pt = OrientedPoints.createPositiveFacing(Vector1D.of(2.0), TEST_PRECISION);
113
114
115 GeometryTestUtils.assertThrows(
116 () -> pt.transform(zeroScale),
117 IllegalArgumentException.class, "Oriented point direction cannot be zero");
118 }
119
120 @Test
121 public void testOffset_positiveFacing() {
122
123 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(-2.0), true, TEST_PRECISION);
124
125
126 Assert.assertEquals(-98.0, pt.offset(Vector1D.of(-100)), Precision.EPSILON);
127 Assert.assertEquals(-0.1, pt.offset(Vector1D.of(-2.1)), Precision.EPSILON);
128 Assert.assertEquals(0.0, pt.offset(Vector1D.of(-2)), Precision.EPSILON);
129 Assert.assertEquals(0.99, pt.offset(Vector1D.of(-1.01)), Precision.EPSILON);
130 Assert.assertEquals(1.0, pt.offset(Vector1D.of(-1.0)), Precision.EPSILON);
131 Assert.assertEquals(1.01, pt.offset(Vector1D.of(-0.99)), Precision.EPSILON);
132 Assert.assertEquals(2.0, pt.offset(Vector1D.of(0)), Precision.EPSILON);
133 Assert.assertEquals(102, pt.offset(Vector1D.of(100)), Precision.EPSILON);
134 }
135
136 @Test
137 public void testOffset_negativeFacing() {
138
139 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(-2.0), false, TEST_PRECISION);
140
141
142 Assert.assertEquals(98.0, pt.offset(Vector1D.of(-100)), Precision.EPSILON);
143 Assert.assertEquals(0.1, pt.offset(Vector1D.of(-2.1)), Precision.EPSILON);
144 Assert.assertEquals(0.0, pt.offset(Vector1D.of(-2)), Precision.EPSILON);
145 Assert.assertEquals(-0.99, pt.offset(Vector1D.of(-1.01)), Precision.EPSILON);
146 Assert.assertEquals(-1.0, pt.offset(Vector1D.of(-1.0)), Precision.EPSILON);
147 Assert.assertEquals(-1.01, pt.offset(Vector1D.of(-0.99)), Precision.EPSILON);
148 Assert.assertEquals(-2, pt.offset(Vector1D.of(0)), Precision.EPSILON);
149 Assert.assertEquals(-102, pt.offset(Vector1D.of(100)), Precision.EPSILON);
150 }
151
152 @Test
153 public void testOffset_infinityArguments() {
154
155 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(-2.0), true, TEST_PRECISION);
156
157
158 GeometryTestUtils.assertPositiveInfinity(pt.offset(Vector1D.of(Double.POSITIVE_INFINITY)));
159 GeometryTestUtils.assertNegativeInfinity(pt.offset(Vector1D.of(Double.NEGATIVE_INFINITY)));
160 }
161
162 @Test
163 public void testOffset_infinityLocation() {
164
165 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(Double.POSITIVE_INFINITY), true, TEST_PRECISION);
166
167
168 Assert.assertTrue(Double.isNaN(pt.offset(Vector1D.of(Double.POSITIVE_INFINITY))));
169 GeometryTestUtils.assertNegativeInfinity(pt.offset(Vector1D.of(Double.NEGATIVE_INFINITY)));
170
171 GeometryTestUtils.assertNegativeInfinity(pt.offset(Vector1D.of(0)));
172 }
173
174 @Test
175 public void testClassify() {
176
177 final DoublePrecisionContext smallPrecision = new EpsilonDoublePrecisionContext(1e-10);
178 final DoublePrecisionContext largePrecision = new EpsilonDoublePrecisionContext(1e-1);
179
180 final OrientedPoint smallPosFacing = OrientedPoints.fromLocationAndDirection(1.0, true, smallPrecision);
181 final OrientedPoint largeNegFacing = OrientedPoints.fromLocationAndDirection(1.0, false, largePrecision);
182
183
184 assertClassify(HyperplaneLocation.MINUS, smallPosFacing,
185 Double.NEGATIVE_INFINITY, -10, 0, 0.9, 0.99999, 1 - 1e-9);
186 assertClassify(HyperplaneLocation.ON, smallPosFacing,
187 1 - 1e-11, 1, 1 + 1e-11);
188 assertClassify(HyperplaneLocation.PLUS, smallPosFacing,
189 1 + 1e-9, 2, 10, Double.POSITIVE_INFINITY);
190
191 assertClassify(HyperplaneLocation.PLUS, largeNegFacing,
192 Double.NEGATIVE_INFINITY, -10, 0, 0.89);
193 assertClassify(HyperplaneLocation.ON, largeNegFacing,
194 0.91, 0.9999, 1, 1.001, 1.09);
195 assertClassify(HyperplaneLocation.MINUS, largeNegFacing,
196 1.11, 2, 10, Double.POSITIVE_INFINITY);
197 }
198
199 @Test
200 public void testSpan() {
201
202 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(1.0), false, TEST_PRECISION);
203
204
205 final HyperplaneConvexSubset<Vector1D> result = pt.span();
206
207
208 Assert.assertSame(pt, result.getHyperplane());
209 }
210
211 @Test
212 public void testSimilarOrientation() {
213
214 final OrientedPoint negativeDir1 = OrientedPoints.fromPointAndDirection(Vector1D.of(1.0), false, TEST_PRECISION);
215 final OrientedPoint negativeDir2 = OrientedPoints.fromPointAndDirection(Vector1D.of(-1.0), false, TEST_PRECISION);
216 final OrientedPoint positiveDir1 = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, TEST_PRECISION);
217 final OrientedPoint positiveDir2 = OrientedPoints.fromPointAndDirection(Vector1D.of(-2.0), true, TEST_PRECISION);
218
219
220 Assert.assertTrue(negativeDir1.similarOrientation(negativeDir1));
221 Assert.assertTrue(negativeDir1.similarOrientation(negativeDir2));
222 Assert.assertTrue(negativeDir2.similarOrientation(negativeDir1));
223
224 Assert.assertTrue(positiveDir1.similarOrientation(positiveDir1));
225 Assert.assertTrue(positiveDir1.similarOrientation(positiveDir2));
226 Assert.assertTrue(positiveDir2.similarOrientation(positiveDir1));
227
228 Assert.assertFalse(negativeDir1.similarOrientation(positiveDir1));
229 Assert.assertFalse(positiveDir1.similarOrientation(negativeDir1));
230 }
231
232 @Test
233 public void testProject() {
234
235 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(1.0), true, TEST_PRECISION);
236
237
238 Assert.assertEquals(1.0, pt.project(Vector1D.of(-1.0)).getX(), Precision.EPSILON);
239 Assert.assertEquals(1.0, pt.project(Vector1D.of(0.0)).getX(), Precision.EPSILON);
240 Assert.assertEquals(1.0, pt.project(Vector1D.of(1.0)).getX(), Precision.EPSILON);
241 Assert.assertEquals(1.0, pt.project(Vector1D.of(100.0)).getX(), Precision.EPSILON);
242 }
243
244
245 @Test
246 public void testEq() {
247
248 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
249
250 final OrientedPoint a = OrientedPoints.createPositiveFacing(0, precision);
251 final OrientedPoint b = OrientedPoints.createPositiveFacing(0, TEST_PRECISION);
252
253 final OrientedPoint c = OrientedPoints.createPositiveFacing(2e-3, precision);
254 final OrientedPoint d = OrientedPoints.createNegativeFacing(0, precision);
255 final OrientedPoint e = OrientedPoints.createPositiveFacing(1e-4, precision);
256
257
258 Assert.assertTrue(a.eq(a, precision));
259 Assert.assertTrue(a.eq(b, precision));
260
261 Assert.assertFalse(a.eq(c, precision));
262 Assert.assertFalse(a.eq(d, precision));
263
264 Assert.assertTrue(a.eq(e, precision));
265 Assert.assertTrue(e.eq(a, precision));
266 }
267
268 @Test
269 public void testHashCode() {
270
271 final DoublePrecisionContext precisionA = new EpsilonDoublePrecisionContext(1e-10);
272 final DoublePrecisionContext precisionB = new EpsilonDoublePrecisionContext(1e-15);
273
274 final OrientedPoint a = OrientedPoints.fromPointAndDirection(Vector1D.of(3.0), true, precisionA);
275 final OrientedPoint b = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), false, precisionA);
276 final OrientedPoint c = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionB);
277
278 final OrientedPoint d = OrientedPoints.fromPointAndDirection(Vector1D.of(3.0), true, precisionA);
279 final OrientedPoint e = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), false, precisionA);
280 final OrientedPoint f = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionB);
281
282
283 Assert.assertNotEquals(a.hashCode(), b.hashCode());
284 Assert.assertNotEquals(b.hashCode(), c.hashCode());
285 Assert.assertNotEquals(c.hashCode(), a.hashCode());
286
287 Assert.assertEquals(a.hashCode(), d.hashCode());
288 Assert.assertEquals(b.hashCode(), e.hashCode());
289 Assert.assertEquals(c.hashCode(), f.hashCode());
290 }
291
292 @Test
293 public void testEquals() {
294
295 final DoublePrecisionContext precisionA = new EpsilonDoublePrecisionContext(1e-10);
296 final DoublePrecisionContext precisionB = new EpsilonDoublePrecisionContext(1e-15);
297
298 final OrientedPoint a = OrientedPoints.fromPointAndDirection(Vector1D.of(1.0), true, precisionA);
299 final OrientedPoint b = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionA);
300
301 final OrientedPoint c = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionA);
302 final OrientedPoint d = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), false, precisionA);
303
304 final OrientedPoint e = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionA);
305 final OrientedPoint f = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, precisionB);
306
307 final OrientedPoint g = OrientedPoints.fromPointAndDirection(Vector1D.of(1.0), true, precisionA);
308
309
310 Assert.assertFalse(a.equals(null));
311 Assert.assertFalse(a.equals(new Object()));
312
313 Assert.assertNotEquals(a, b);
314 Assert.assertNotEquals(c, d);
315 Assert.assertNotEquals(e, f);
316
317 Assert.assertEquals(a, a);
318 Assert.assertEquals(a, g);
319 Assert.assertEquals(g, a);
320 }
321
322 @Test
323 public void testToString() {
324
325 final OrientedPoint pt = OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), true, TEST_PRECISION);
326
327
328 final String str = pt.toString();
329
330
331 Assert.assertTrue(str.contains("OrientedPoint"));
332 Assert.assertTrue(str.contains("point= (2.0)"));
333 Assert.assertTrue(str.contains("direction= (1.0)"));
334 }
335
336 @Test
337 public void testFromLocationAndDirection() {
338
339 assertOrientedPoint(OrientedPoints.fromLocationAndDirection(3.0, true, TEST_PRECISION),
340 3.0, true, TEST_PRECISION);
341 assertOrientedPoint(OrientedPoints.fromLocationAndDirection(2.0, false, TEST_PRECISION),
342 2.0, false, TEST_PRECISION);
343 }
344
345 @Test
346 public void testFromPointAndDirection_pointAndBooleanArgs() {
347
348 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(3.0), true, TEST_PRECISION),
349 3.0, true, TEST_PRECISION);
350 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), false, TEST_PRECISION),
351 2.0, false, TEST_PRECISION);
352 }
353
354 @Test
355 public void testFromPointAndDirection_pointAndVectorArgs() {
356
357 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(-2.0), Vector1D.of(0.1), TEST_PRECISION),
358 -2.0, true, TEST_PRECISION);
359 assertOrientedPoint(OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), Vector1D.of(-10.1), TEST_PRECISION),
360 2.0, false, TEST_PRECISION);
361 }
362
363 @Test
364 public void testFromPointAndDirection_invalidDirection() {
365
366 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(0.1);
367
368
369 GeometryTestUtils.assertThrows(
370 () -> OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), Vector1D.of(0.09), precision),
371 IllegalArgumentException.class, "Oriented point direction cannot be zero");
372 GeometryTestUtils.assertThrows(
373 () -> OrientedPoints.fromPointAndDirection(Vector1D.of(2.0), Vector1D.of(-0.09), precision),
374 IllegalArgumentException.class, "Oriented point direction cannot be zero");
375 }
376
377 @Test
378 public void testCreatePositiveFacing() {
379
380 assertOrientedPoint(OrientedPoints.createPositiveFacing(Vector1D.of(-2.0), TEST_PRECISION),
381 -2.0, true, TEST_PRECISION);
382 assertOrientedPoint(OrientedPoints.createPositiveFacing(-4.0, TEST_PRECISION),
383 -4.0, true, TEST_PRECISION);
384 }
385
386 @Test
387 public void testCreateNegativeFacing() {
388
389 assertOrientedPoint(OrientedPoints.createNegativeFacing(Vector1D.of(2.0), TEST_PRECISION),
390 2.0, false, TEST_PRECISION);
391 assertOrientedPoint(OrientedPoints.createNegativeFacing(4, TEST_PRECISION),
392 4.0, false, TEST_PRECISION);
393 }
394
395 @Test
396 public void testSubset_split() {
397
398 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3);
399
400 final OrientedPoint pt = OrientedPoints.createPositiveFacing(-1.5, precision);
401 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
402
403
404 checkSplit(sub, OrientedPoints.createPositiveFacing(1.0, precision), true, false);
405 checkSplit(sub, OrientedPoints.createPositiveFacing(-1.5 + 1e-2, precision), true, false);
406
407 checkSplit(sub, OrientedPoints.createNegativeFacing(1.0, precision), false, true);
408 checkSplit(sub, OrientedPoints.createNegativeFacing(-1.5 + 1e-2, precision), false, true);
409
410 checkSplit(sub, OrientedPoints.createNegativeFacing(-1.5, precision), false, false);
411 checkSplit(sub, OrientedPoints.createNegativeFacing(-1.5 + 1e-4, precision), false, false);
412 checkSplit(sub, OrientedPoints.createNegativeFacing(-1.5 - 1e-4, precision), false, false);
413 }
414
415 private void checkSplit(final HyperplaneConvexSubset<Vector1D> sub, final OrientedPoint splitter, final boolean minus, final boolean plus) {
416 final Split<? extends HyperplaneConvexSubset<Vector1D>> split = sub.split(splitter);
417
418 Assert.assertSame(minus ? sub : null, split.getMinus());
419 Assert.assertSame(plus ? sub : null, split.getPlus());
420 }
421
422 @Test
423 public void testSubset_simpleMethods() {
424
425 final OrientedPoint pt = OrientedPoints.createPositiveFacing(2, TEST_PRECISION);
426 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
427
428
429 Assert.assertSame(pt, sub.getHyperplane());
430 Assert.assertFalse(sub.isFull());
431 Assert.assertFalse(sub.isEmpty());
432 Assert.assertFalse(sub.isInfinite());
433 Assert.assertTrue(sub.isFinite());
434 Assert.assertEquals(0.0, sub.getSize(), TEST_EPS);
435 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(2), sub.getCentroid(), TEST_EPS);
436
437 final List<? extends HyperplaneConvexSubset<Vector1D>> list = sub.toConvex();
438 Assert.assertEquals(1, list.size());
439 Assert.assertSame(sub, list.get(0));
440 }
441
442 @Test
443 public void testSubset_classify() {
444
445 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
446 final OrientedPoint pt = OrientedPoints.createPositiveFacing(1, precision);
447 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
448
449
450 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Vector1D.of(0.95)));
451 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Vector1D.of(1)));
452 Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Vector1D.of(1.05)));
453
454 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.of(1.11)));
455 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.of(0.89)));
456
457 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.of(-3)));
458 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.of(10)));
459
460 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.NEGATIVE_INFINITY));
461 Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Vector1D.POSITIVE_INFINITY));
462 }
463
464 @Test
465 public void testSubset_contains() {
466
467 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
468 final OrientedPoint pt = OrientedPoints.createPositiveFacing(1, precision);
469 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
470
471
472 Assert.assertTrue(sub.contains(Vector1D.of(0.95)));
473 Assert.assertTrue(sub.contains(Vector1D.of(1)));
474 Assert.assertTrue(sub.contains(Vector1D.of(1.05)));
475
476 Assert.assertFalse(sub.contains(Vector1D.of(1.11)));
477 Assert.assertFalse(sub.contains(Vector1D.of(0.89)));
478
479 Assert.assertFalse(sub.contains(Vector1D.of(-3)));
480 Assert.assertFalse(sub.contains(Vector1D.of(10)));
481
482 Assert.assertFalse(sub.contains(Vector1D.NEGATIVE_INFINITY));
483 Assert.assertFalse(sub.contains(Vector1D.POSITIVE_INFINITY));
484 }
485
486 @Test
487 public void testSubset_closestContained() {
488
489 final DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1);
490 final OrientedPoint pt = OrientedPoints.createPositiveFacing(1, precision);
491 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
492
493
494 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(1), sub.closest(Vector1D.NEGATIVE_INFINITY), TEST_EPS);
495 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(1), sub.closest(Vector1D.of(0)), TEST_EPS);
496 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(1), sub.closest(Vector1D.of(1)), TEST_EPS);
497 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(1), sub.closest(Vector1D.of(2)), TEST_EPS);
498 EuclideanTestUtils.assertCoordinatesEqual(Vector1D.of(1), sub.closest(Vector1D.POSITIVE_INFINITY), TEST_EPS);
499 }
500
501 @Test
502 public void testSubset_transform() {
503
504 final AffineTransformMatrix1D scaleAndTranslate = AffineTransformMatrix1D
505 .createScale(0.5)
506 .translate(-10);
507
508 final AffineTransformMatrix1D reflect = AffineTransformMatrix1D.createScale(-2);
509
510 final HyperplaneConvexSubset<Vector1D> a =
511 OrientedPoints.createPositiveFacing(Vector1D.of(2.0), TEST_PRECISION).span();
512 final HyperplaneConvexSubset<Vector1D> b =
513 OrientedPoints.createNegativeFacing(Vector1D.of(-3.0), TEST_PRECISION).span();
514
515
516 assertOrientedPoint((OrientedPoint) a.transform(scaleAndTranslate).getHyperplane(),
517 -9.0, true, TEST_PRECISION);
518 assertOrientedPoint((OrientedPoint) b.transform(scaleAndTranslate).getHyperplane(),
519 -11.5, false, TEST_PRECISION);
520
521 assertOrientedPoint((OrientedPoint) a.transform(reflect).getHyperplane(), -4.0, false, TEST_PRECISION);
522 assertOrientedPoint((OrientedPoint) b.transform(reflect).getHyperplane(), 6.0, true, TEST_PRECISION);
523 }
524
525 @Test
526 public void testSubset_reverse() {
527
528 final OrientedPoint pt = OrientedPoints.createPositiveFacing(2.0, TEST_PRECISION);
529 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
530
531
532 final HyperplaneConvexSubset<Vector1D> result = sub.reverse();
533
534
535 Assert.assertEquals(2.0, ((OrientedPoint) result.getHyperplane()).getLocation(), TEST_EPS);
536 Assert.assertFalse(((OrientedPoint) result.getHyperplane()).isPositiveFacing());
537
538 Assert.assertEquals(sub.getHyperplane(), result.reverse().getHyperplane());
539 }
540
541 @Test
542 public void testSubset_toString() {
543
544 final OrientedPoint pt = OrientedPoints.createPositiveFacing(2, TEST_PRECISION);
545 final HyperplaneConvexSubset<Vector1D> sub = pt.span();
546
547
548 final String str = sub.toString();
549
550
551 Assert.assertTrue(str.contains("OrientedPointConvexSubset"));
552 Assert.assertTrue(str.contains("point= (2.0)"));
553 Assert.assertTrue(str.contains("direction= (1.0)"));
554 }
555
556 private static void assertOrientedPoint(final OrientedPoint pt, final double location, final boolean positiveFacing,
557 final DoublePrecisionContext precision) {
558 Assert.assertEquals(location, pt.getPoint().getX(), TEST_EPS);
559 Assert.assertEquals(location, pt.getLocation(), TEST_EPS);
560 Assert.assertEquals(positiveFacing ? 1.0 : -1.0, pt.getDirection().getX(), TEST_EPS);
561 Assert.assertEquals(positiveFacing, pt.isPositiveFacing());
562 Assert.assertSame(precision, pt.getPrecision());
563 }
564
565 private static void assertClassify(final HyperplaneLocation expected, final OrientedPoint pt, final double... locations) {
566 for (final double location : locations) {
567 final String msg = "Unexpected classification for location " + location;
568
569 Assert.assertEquals(msg, expected, pt.classify(location));
570 Assert.assertEquals(msg, expected, pt.classify(Vector1D.of(location)));
571 }
572 }
573 }