| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.geometry.spherical.oned; |
| |
| import java.util.List; |
| |
| import org.apache.commons.geometry.core.Geometry; |
| import org.apache.commons.geometry.core.GeometryTestUtils; |
| import org.apache.commons.geometry.core.RegionLocation; |
| import org.apache.commons.geometry.core.exception.GeometryException; |
| import org.apache.commons.geometry.core.partitioning.HyperplaneLocation; |
| import org.apache.commons.geometry.core.partitioning.Split; |
| import org.apache.commons.geometry.core.partitioning.SubHyperplane; |
| import org.apache.commons.geometry.core.partitioning.SubHyperplane.Builder; |
| import org.apache.commons.geometry.core.precision.DoublePrecisionContext; |
| import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext; |
| import org.apache.commons.geometry.spherical.oned.CutAngle.SubCutAngle; |
| import org.apache.commons.geometry.spherical.oned.CutAngle.SubCutAngleBuilder; |
| import org.apache.commons.numbers.angle.PlaneAngleRadians; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| public class CutAngleTest { |
| |
| private static final double TEST_EPS = 1e-10; |
| |
| private static final DoublePrecisionContext TEST_PRECISION = |
| new EpsilonDoublePrecisionContext(TEST_EPS); |
| |
| @Test |
| public void testFromAzimuthAndDirection() { |
| // act/assert |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.ZERO_PI, true, TEST_PRECISION), |
| Geometry.ZERO_PI, true); |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.PI, true, TEST_PRECISION), |
| Geometry.PI, true); |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.MINUS_HALF_PI, true, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, true); |
| |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.ZERO_PI, false, TEST_PRECISION), |
| Geometry.ZERO_PI, false); |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.PI, false, TEST_PRECISION), |
| Geometry.PI, false); |
| checkCutAngle(CutAngle.fromAzimuthAndDirection(Geometry.MINUS_HALF_PI, false, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, false); |
| } |
| |
| @Test |
| public void testFromPointAndDirection() { |
| // arrange |
| Point1S pt = Point1S.of(Geometry.MINUS_HALF_PI); |
| |
| // act/assert |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION), |
| Geometry.ZERO_PI, true); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION), |
| Geometry.PI, true); |
| checkCutAngle(CutAngle.fromPointAndDirection(pt, true, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, true); |
| |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION), |
| Geometry.ZERO_PI, false); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.PI, false, TEST_PRECISION), |
| Geometry.PI, false); |
| checkCutAngle(CutAngle.fromPointAndDirection(pt, false, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, false); |
| } |
| |
| @Test |
| public void testCreatePositiveFacing() { |
| // act/assert |
| checkCutAngle(CutAngle.createPositiveFacing(Point1S.ZERO, TEST_PRECISION), |
| Geometry.ZERO_PI, true); |
| checkCutAngle(CutAngle.createPositiveFacing(Point1S.PI, TEST_PRECISION), |
| Geometry.PI, true); |
| checkCutAngle(CutAngle.createPositiveFacing(Geometry.MINUS_HALF_PI, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, true); |
| } |
| |
| @Test |
| public void testCreateNegativeFacing() { |
| // act/assert |
| checkCutAngle(CutAngle.createNegativeFacing(Point1S.ZERO, TEST_PRECISION), |
| Geometry.ZERO_PI, false); |
| checkCutAngle(CutAngle.createNegativeFacing(Point1S.PI, TEST_PRECISION), |
| Geometry.PI, false); |
| checkCutAngle(CutAngle.createNegativeFacing(Geometry.MINUS_HALF_PI, TEST_PRECISION), |
| Geometry.MINUS_HALF_PI, false); |
| } |
| |
| @Test |
| public void testOffset() { |
| // arrange |
| CutAngle zeroPos = CutAngle.createPositiveFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle zeroNeg = CutAngle.createNegativeFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle negPiPos = CutAngle.createPositiveFacing(-Geometry.PI, TEST_PRECISION); |
| |
| CutAngle piNeg = CutAngle.createNegativeFacing(Geometry.PI, TEST_PRECISION); |
| CutAngle twoAndAHalfPiPos = CutAngle.createPositiveFacing(2.5 * Geometry.PI, TEST_PRECISION); |
| |
| // act/assert |
| checkOffset(zeroPos, 0, 0); |
| checkOffset(zeroPos, Geometry.TWO_PI, 0); |
| checkOffset(zeroPos, 2.5 * Geometry.PI, Geometry.HALF_PI); |
| checkOffset(zeroPos, Geometry.PI, Geometry.PI); |
| checkOffset(zeroPos, 3.5 * Geometry.PI, 1.5 * Geometry.PI); |
| |
| checkOffset(zeroNeg, 0, 0); |
| checkOffset(zeroNeg, Geometry.TWO_PI, 0); |
| checkOffset(zeroNeg, 2.5 * Geometry.PI, Geometry.MINUS_HALF_PI); |
| checkOffset(zeroNeg, Geometry.PI, -Geometry.PI); |
| checkOffset(zeroNeg, 3.5 * Geometry.PI, -1.5 * Geometry.PI); |
| |
| checkOffset(negPiPos, 0, -Geometry.PI); |
| checkOffset(negPiPos, Geometry.TWO_PI, -Geometry.PI); |
| checkOffset(negPiPos, 2.5 * Geometry.PI, Geometry.MINUS_HALF_PI); |
| checkOffset(negPiPos, Geometry.PI, 0); |
| checkOffset(negPiPos, 3.5 * Geometry.PI, Geometry.HALF_PI); |
| |
| checkOffset(piNeg, 0, Geometry.PI); |
| checkOffset(piNeg, Geometry.TWO_PI, Geometry.PI); |
| checkOffset(piNeg, 2.5 * Geometry.PI, Geometry.HALF_PI); |
| checkOffset(piNeg, Geometry.PI, 0); |
| checkOffset(piNeg, 3.5 * Geometry.PI, Geometry.MINUS_HALF_PI); |
| |
| checkOffset(twoAndAHalfPiPos, 0, Geometry.MINUS_HALF_PI); |
| checkOffset(twoAndAHalfPiPos, Geometry.TWO_PI, Geometry.MINUS_HALF_PI); |
| checkOffset(twoAndAHalfPiPos, 2.5 * Geometry.PI, 0); |
| checkOffset(twoAndAHalfPiPos, Geometry.PI, Geometry.HALF_PI); |
| checkOffset(twoAndAHalfPiPos, 3.5 * Geometry.PI, Geometry.PI); |
| } |
| |
| @Test |
| public void testClassify() { |
| // arrange |
| CutAngle zeroPos = CutAngle.createPositiveFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle zeroNeg = CutAngle.createNegativeFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle negPiPos = CutAngle.createPositiveFacing(-Geometry.PI, TEST_PRECISION); |
| |
| // act/assert |
| checkClassify(zeroPos, HyperplaneLocation.ON, |
| 0, 1e-16, -1e-16, |
| Geometry.TWO_PI - 1e-11, Geometry.TWO_PI + 1e-11); |
| checkClassify(zeroPos, HyperplaneLocation.PLUS, |
| 0.5, 2.5 * Geometry.PI, |
| -0.5, Geometry.MINUS_HALF_PI); |
| |
| checkClassify(zeroNeg, HyperplaneLocation.ON, |
| 0, 1e-16, -1e-16, |
| Geometry.TWO_PI - 1e-11, Geometry.TWO_PI + 1e-11); |
| checkClassify(zeroNeg, HyperplaneLocation.MINUS, |
| 0.5, 2.5 * Geometry.PI, |
| -0.5, Geometry.MINUS_HALF_PI); |
| |
| checkClassify(negPiPos, HyperplaneLocation.ON, Geometry.PI, Geometry.PI + 1e-11); |
| checkClassify(negPiPos, HyperplaneLocation.MINUS, 0.5, 2.5 * Geometry.PI, |
| 0, 1e-11, Geometry.TWO_PI, Geometry.TWO_PI - 1e-11); |
| checkClassify(negPiPos, HyperplaneLocation.PLUS, -0.5, Geometry.MINUS_HALF_PI); |
| } |
| |
| @Test |
| public void testContains() { |
| // arrange |
| CutAngle pt = CutAngle.createNegativeFacing(Geometry.HALF_PI, TEST_PRECISION); |
| |
| // act/assert |
| Assert.assertFalse(pt.contains(Point1S.ZERO)); |
| Assert.assertFalse(pt.contains(Point1S.of(Geometry.TWO_PI))); |
| |
| Assert.assertFalse(pt.contains(Point1S.of(Geometry.PI))); |
| Assert.assertFalse(pt.contains(Point1S.of(0.25 * Geometry.PI))); |
| Assert.assertFalse(pt.contains(Point1S.of(-0.25 * Geometry.PI))); |
| |
| Assert.assertTrue(pt.contains(Point1S.of(Geometry.HALF_PI))); |
| Assert.assertTrue(pt.contains(Point1S.of(Geometry.HALF_PI + 1e-11))); |
| Assert.assertTrue(pt.contains(Point1S.of(2.5 * Geometry.PI))); |
| Assert.assertTrue(pt.contains(Point1S.of(-3.5 * Geometry.PI))); |
| } |
| |
| @Test |
| public void testReverse() { |
| // arrange |
| CutAngle pt = CutAngle.createNegativeFacing(Geometry.HALF_PI, TEST_PRECISION); |
| |
| // act |
| CutAngle result = pt.reverse(); |
| |
| // assert |
| checkCutAngle(result, Geometry.HALF_PI, true); |
| Assert.assertSame(TEST_PRECISION, result.getPrecision()); |
| |
| checkCutAngle(result.reverse(), Geometry.HALF_PI, false); |
| } |
| |
| @Test |
| public void testProject() { |
| // arrange |
| CutAngle pt = CutAngle.createNegativeFacing(Geometry.HALF_PI, TEST_PRECISION); |
| |
| // act/assert |
| for (double az = -Geometry.TWO_PI; az <= Geometry.TWO_PI; az += 0.2) { |
| Assert.assertEquals(Geometry.HALF_PI, pt.project(Point1S.of(az)).getAzimuth(), TEST_EPS); |
| } |
| } |
| |
| @Test |
| public void testSimilarOrientation() { |
| // arrange |
| CutAngle a = CutAngle.createPositiveFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle b = CutAngle.createNegativeFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| CutAngle c = CutAngle.createPositiveFacing(Geometry.MINUS_HALF_PI, TEST_PRECISION); |
| |
| // act/assert |
| Assert.assertTrue(a.similarOrientation(a)); |
| Assert.assertFalse(a.similarOrientation(b)); |
| Assert.assertTrue(a.similarOrientation(c)); |
| } |
| |
| @Test |
| public void testTransform_rotate() { |
| // arrange |
| Transform1S transform = Transform1S.createRotation(Geometry.HALF_PI); |
| |
| // act |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION).transform(transform), |
| Geometry.HALF_PI, true); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION).transform(transform), |
| Geometry.HALF_PI, false); |
| |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.of(1.5 * Geometry.PI), true, TEST_PRECISION).transform(transform), |
| Geometry.TWO_PI, true); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.of(Geometry.MINUS_HALF_PI), false, TEST_PRECISION).transform(transform), |
| Geometry.ZERO_PI, false); |
| } |
| |
| @Test |
| public void testTransform_negate() { |
| // arrange |
| Transform1S transform = Transform1S.createNegation(); |
| |
| // act |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION).transform(transform), |
| Geometry.ZERO_PI, false); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION).transform(transform), |
| Geometry.ZERO_PI, true); |
| |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.of(1.5 * Geometry.PI), true, TEST_PRECISION).transform(transform), |
| -1.5 * Geometry.PI, false); |
| checkCutAngle(CutAngle.fromPointAndDirection(Point1S.of(Geometry.MINUS_HALF_PI), false, TEST_PRECISION).transform(transform), |
| Geometry.HALF_PI, true); |
| } |
| |
| @Test |
| public void testSpan() { |
| // arrange |
| CutAngle pt = CutAngle.fromPointAndDirection(Point1S.of(1.0), false, TEST_PRECISION); |
| |
| // act |
| SubCutAngle result = pt.span(); |
| |
| // assert |
| Assert.assertSame(pt, result.getHyperplane()); |
| } |
| |
| @Test |
| public void testEq() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle a = CutAngle.fromPointAndDirection(Point1S.ZERO, true, precision); |
| |
| CutAngle b = CutAngle.fromPointAndDirection(Point1S.PI, true, precision); |
| CutAngle c = CutAngle.fromPointAndDirection(Point1S.ZERO, false, precision); |
| CutAngle d = CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION); |
| |
| CutAngle e = CutAngle.fromPointAndDirection(Point1S.ZERO, true, precision); |
| CutAngle f = CutAngle.fromPointAndDirection(Point1S.of(Geometry.TWO_PI), true, precision); |
| CutAngle g = CutAngle.fromPointAndDirection(Point1S.of(1e-4), true, precision); |
| CutAngle h = CutAngle.fromPointAndDirection(Point1S.of(-1e-4), true, precision); |
| |
| // act/assert |
| Assert.assertTrue(a.eq(a)); |
| |
| Assert.assertFalse(a.eq(b)); |
| Assert.assertFalse(a.eq(c)); |
| Assert.assertFalse(a.eq(d)); |
| |
| Assert.assertTrue(a.eq(e)); |
| Assert.assertTrue(a.eq(f)); |
| Assert.assertTrue(a.eq(g)); |
| Assert.assertTrue(a.eq(h)); |
| } |
| |
| @Test |
| public void testHashCode() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle a = CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION); |
| CutAngle b = CutAngle.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION); |
| CutAngle c = CutAngle.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION); |
| CutAngle d = CutAngle.fromPointAndDirection(Point1S.ZERO, true, precision); |
| CutAngle e = CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION); |
| |
| int hash = a.hashCode(); |
| |
| // act/assert |
| Assert.assertEquals(hash, a.hashCode()); |
| |
| Assert.assertNotEquals(hash, b.hashCode()); |
| Assert.assertNotEquals(hash, c.hashCode()); |
| Assert.assertNotEquals(hash, d.hashCode()); |
| |
| Assert.assertEquals(hash, e.hashCode()); |
| } |
| |
| @Test |
| public void testEquals() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle a = CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION); |
| CutAngle b = CutAngle.fromPointAndDirection(Point1S.PI, true, TEST_PRECISION); |
| CutAngle c = CutAngle.fromPointAndDirection(Point1S.ZERO, false, TEST_PRECISION); |
| CutAngle d = CutAngle.fromPointAndDirection(Point1S.ZERO, true, precision); |
| CutAngle e = CutAngle.fromPointAndDirection(Point1S.ZERO, true, TEST_PRECISION); |
| |
| // act/assert |
| Assert.assertFalse(a.equals(null)); |
| Assert.assertFalse(a.equals(new Object())); |
| |
| Assert.assertTrue(a.equals(a)); |
| |
| Assert.assertFalse(a.equals(b)); |
| Assert.assertFalse(a.equals(c)); |
| Assert.assertFalse(a.equals(d)); |
| |
| Assert.assertTrue(a.equals(e)); |
| } |
| |
| @Test |
| public void testToString() { |
| // arrange |
| CutAngle pt = CutAngle.createPositiveFacing(Geometry.ZERO_PI, TEST_PRECISION); |
| |
| // act |
| String str = pt.toString(); |
| |
| // assert |
| Assert.assertTrue(str.startsWith("CutAngle[")); |
| Assert.assertTrue(str.contains("point= ") && str.contains("positiveFacing= ")); |
| } |
| |
| @Test |
| public void testSubHyperplane_split() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle pt = CutAngle.createPositiveFacing(-1.5, precision); |
| SubCutAngle sub = pt.span(); |
| |
| // act/assert |
| checkSplit(sub, CutAngle.createPositiveFacing(1.0, precision), false, true); |
| checkSplit(sub, CutAngle.createPositiveFacing(-1.5 + 1e-2, precision), true, false); |
| |
| checkSplit(sub, CutAngle.createNegativeFacing(1.0, precision), true, false); |
| checkSplit(sub, CutAngle.createNegativeFacing(-1.5 + 1e-2, precision), false, true); |
| |
| checkSplit(sub, CutAngle.createNegativeFacing(-1.5, precision), false, false); |
| checkSplit(sub, CutAngle.createNegativeFacing(-1.5 + 1e-4, precision), false, false); |
| checkSplit(sub, CutAngle.createNegativeFacing(-1.5 - 1e-4, precision), false, false); |
| } |
| |
| private void checkSplit(SubCutAngle sub, CutAngle splitter, boolean minus, boolean plus) { |
| Split<SubCutAngle> split = sub.split(splitter); |
| |
| Assert.assertSame(minus ? sub : null, split.getMinus()); |
| Assert.assertSame(plus ? sub : null, split.getPlus()); |
| } |
| |
| @Test |
| public void testSubHyperplane_simpleMethods() { |
| // arrange |
| CutAngle pt = CutAngle.createPositiveFacing(0, TEST_PRECISION); |
| SubCutAngle sub = pt.span(); |
| |
| // act/assert |
| Assert.assertSame(pt, sub.getHyperplane()); |
| Assert.assertFalse(sub.isFull()); |
| Assert.assertFalse(sub.isEmpty()); |
| Assert.assertFalse(sub.isInfinite()); |
| Assert.assertTrue(sub.isFinite()); |
| Assert.assertEquals(0.0, sub.getSize(), TEST_EPS); |
| |
| List<SubCutAngle> list = sub.toConvex(); |
| Assert.assertEquals(1, list.size()); |
| Assert.assertSame(sub, list.get(0)); |
| } |
| |
| @Test |
| public void testSubHyperplane_classify() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1); |
| CutAngle pt = CutAngle.createPositiveFacing(1, precision); |
| SubCutAngle sub = pt.span(); |
| |
| // act/assert |
| Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(0.95))); |
| Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(1))); |
| Assert.assertEquals(RegionLocation.BOUNDARY, sub.classify(Point1S.of(1.05))); |
| |
| Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(1.11))); |
| Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(0.89))); |
| |
| Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(-3))); |
| Assert.assertEquals(RegionLocation.OUTSIDE, sub.classify(Point1S.of(10))); |
| } |
| |
| @Test |
| public void testSubHyperplane_contains() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1); |
| CutAngle pt = CutAngle.createPositiveFacing(1, precision); |
| SubCutAngle sub = pt.span(); |
| |
| // act/assert |
| Assert.assertTrue(sub.contains(Point1S.of(0.95))); |
| Assert.assertTrue(sub.contains(Point1S.of(1))); |
| Assert.assertTrue(sub.contains(Point1S.of(1.05))); |
| |
| Assert.assertFalse(sub.contains(Point1S.of(1.11))); |
| Assert.assertFalse(sub.contains(Point1S.of(0.89))); |
| |
| Assert.assertFalse(sub.contains(Point1S.of(-3))); |
| Assert.assertFalse(sub.contains(Point1S.of(10))); |
| } |
| |
| @Test |
| public void testSubHyperplane_closestContained() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-1); |
| CutAngle pt = CutAngle.createPositiveFacing(1, precision); |
| SubCutAngle sub = pt.span(); |
| |
| Point1S expected = Point1S.of(1); |
| |
| // act/assert |
| Assert.assertEquals(expected, sub.closest(Point1S.ZERO)); |
| Assert.assertEquals(expected, sub.closest(Point1S.of(Geometry.HALF_PI))); |
| Assert.assertEquals(expected, sub.closest(Point1S.PI)); |
| Assert.assertEquals(expected, sub.closest(Point1S.of(Geometry.MINUS_HALF_PI))); |
| Assert.assertEquals(expected, sub.closest(Point1S.of(Geometry.TWO_PI))); |
| } |
| |
| @Test |
| public void testSubHyperplane_transform() { |
| // arrange |
| CutAngle pt = CutAngle.fromPointAndDirection(Point1S.of(Geometry.HALF_PI), true, TEST_PRECISION); |
| |
| Transform1S transform = Transform1S.createNegation().rotate(Geometry.PI); |
| |
| // act |
| SubCutAngle result = pt.span().transform(transform); |
| |
| // assert |
| checkCutAngle(result.getHyperplane(), Geometry.HALF_PI, false); |
| } |
| |
| @Test |
| public void testSubHyperplane_reverse() { |
| // arrange |
| CutAngle pt = CutAngle.createPositiveFacing(2.0, TEST_PRECISION); |
| SubCutAngle sub = pt.span(); |
| |
| // act |
| SubCutAngle result = sub.reverse(); |
| |
| // assert |
| Assert.assertEquals(2.0, result.getHyperplane().getAzimuth(), TEST_EPS); |
| Assert.assertFalse(result.getHyperplane().isPositiveFacing()); |
| |
| Assert.assertEquals(sub.getHyperplane(), result.reverse().getHyperplane()); |
| } |
| |
| @Test |
| public void testSubHyperplane_toString() { |
| // arrange |
| CutAngle pt = CutAngle.createPositiveFacing(2, TEST_PRECISION); |
| SubCutAngle sub = pt.span(); |
| |
| // act |
| String str = sub.toString(); |
| |
| //assert |
| Assert.assertTrue(str.contains("SubCutAngle[")); |
| Assert.assertTrue(str.contains("point= ")); |
| Assert.assertTrue(str.contains("positiveFacing= ")); |
| } |
| |
| @Test |
| public void testBuilder() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle pt = CutAngle.createPositiveFacing(0, precision); |
| SubCutAngle sub = pt.span(); |
| |
| // act |
| Builder<Point1S> builder = sub.builder(); |
| |
| builder.add(sub); |
| builder.add(CutAngle.createPositiveFacing(1e-4, precision).span()); |
| builder.add((SubHyperplane<Point1S>) sub); |
| |
| SubHyperplane<Point1S> result = builder.build(); |
| |
| // assert |
| Assert.assertSame(sub, result); |
| } |
| |
| @Test |
| public void testBuilder_invalidArgs() { |
| // arrange |
| DoublePrecisionContext precision = new EpsilonDoublePrecisionContext(1e-3); |
| |
| CutAngle pt = CutAngle.createPositiveFacing(0, precision); |
| SubCutAngle sub = pt.span(); |
| |
| Builder<Point1S> builder = sub.builder(); |
| |
| // act/assert |
| GeometryTestUtils.assertThrows( |
| () -> builder.add(CutAngle.createPositiveFacing(2e-3, precision).span()), |
| GeometryException.class); |
| GeometryTestUtils.assertThrows( |
| () -> builder.add(CutAngle.createNegativeFacing(2e-3, precision).span()), |
| GeometryException.class); |
| |
| GeometryTestUtils.assertThrows( |
| () -> builder.add((SubHyperplane<Point1S>) CutAngle.createPositiveFacing(2e-3, precision).span()), |
| GeometryException.class); |
| } |
| |
| @Test |
| public void testBuilder_toString() { |
| // arrange |
| CutAngle pt = CutAngle.createPositiveFacing(2, TEST_PRECISION); |
| SubCutAngleBuilder builder = pt.span().builder(); |
| |
| // act |
| String str = builder.toString(); |
| |
| //assert |
| Assert.assertTrue(str.contains("SubCutAngleBuilder[")); |
| Assert.assertTrue(str.contains("base= SubCutAngle[")); |
| Assert.assertTrue(str.contains("point= ")); |
| Assert.assertTrue(str.contains("positiveFacing= ")); |
| } |
| |
| private static void checkCutAngle(CutAngle angle, double az, boolean positiveFacing) { |
| checkCutAngle(angle, az, positiveFacing, TEST_PRECISION); |
| } |
| |
| private static void checkCutAngle(CutAngle angle, double az, boolean positiveFacing, DoublePrecisionContext precision) { |
| Assert.assertEquals(az, angle.getAzimuth(), TEST_EPS); |
| Assert.assertEquals(PlaneAngleRadians.normalizeBetweenZeroAndTwoPi(az), angle.getNormalizedAzimuth(), TEST_EPS); |
| Assert.assertEquals(az, angle.getPoint().getAzimuth(), TEST_EPS); |
| Assert.assertEquals(positiveFacing, angle.isPositiveFacing()); |
| |
| Assert.assertSame(precision, angle.getPrecision()); |
| } |
| |
| private static void checkOffset(CutAngle pt, double az, double offset) { |
| Assert.assertEquals(offset, pt.offset(Point1S.of(az)), TEST_EPS); |
| } |
| |
| private static void checkClassify(CutAngle pt, HyperplaneLocation loc, double ... azimuths) { |
| for (double az : azimuths) { |
| Assert.assertEquals("Unexpected location for azimuth " + az, loc, pt.classify(Point1S.of(az))); |
| } |
| } |
| } |