blob: b81a44ba32e2568c61213ac010b8ac3de1ca0863 [file] [log] [blame]
/*
* 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.twod;
import org.apache.commons.geometry.core.Geometry;
import org.apache.commons.geometry.core.partitioning.Transform;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
import org.apache.commons.geometry.euclidean.threed.Vector3D;
import org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation;
import org.apache.commons.geometry.spherical.oned.Arc;
import org.apache.commons.geometry.spherical.oned.LimitAngle;
import org.apache.commons.geometry.spherical.oned.S1Point;
import org.apache.commons.geometry.spherical.oned.SubLimitAngle;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.UnitSphereSampler;
import org.apache.commons.rng.simple.RandomSource;
import org.junit.Assert;
import org.junit.Test;
public class CircleTest {
private static final double TEST_EPS = 1e-10;
private static final DoublePrecisionContext TEST_PRECISION =
new EpsilonDoublePrecisionContext(TEST_EPS);
@Test
public void testEquator() {
Circle circle = new Circle(Vector3D.of(0, 0, 1000), TEST_PRECISION).copySelf();
Assert.assertEquals(Vector3D.Unit.PLUS_Z, circle.getPole());
Assert.assertEquals(TEST_PRECISION, circle.getPrecision());
circle.revertSelf();
Assert.assertEquals(Vector3D.Unit.MINUS_Z, circle.getPole());
Assert.assertEquals(Vector3D.Unit.PLUS_Z, circle.getReverse().getPole());
Assert.assertEquals(Vector3D.Unit.MINUS_Z, circle.getPole());
}
@Test
public void testXY() {
Circle circle = new Circle(S2Point.of(1.2, 2.5), S2Point.of(-4.3, 0), TEST_PRECISION);
Assert.assertEquals(0.0, circle.getPointAt(0).distance(circle.getXAxis()), TEST_EPS);
Assert.assertEquals(0.0, circle.getPointAt(0.5 * Math.PI).distance(circle.getYAxis()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getXAxis().angle(circle.getYAxis()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getXAxis().angle(circle.getPole()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getPole().angle(circle.getYAxis()), TEST_EPS);
Assert.assertEquals(0.0,
circle.getPole().distance(circle.getXAxis().cross(circle.getYAxis())),
TEST_EPS);
}
@Test
public void testReverse() {
Circle circle = new Circle(S2Point.of(1.2, 2.5), S2Point.of(-4.3, 0), TEST_PRECISION);
Circle reversed = circle.getReverse();
Assert.assertEquals(0.0, reversed.getPointAt(0).distance(reversed.getXAxis()), TEST_EPS);
Assert.assertEquals(0.0, reversed.getPointAt(0.5 * Math.PI).distance(reversed.getYAxis()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, reversed.getXAxis().angle(reversed.getYAxis()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, reversed.getXAxis().angle(reversed.getPole()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, reversed.getPole().angle(reversed.getYAxis()), TEST_EPS);
Assert.assertEquals(0.0,
reversed.getPole().distance(reversed.getXAxis().cross(reversed.getYAxis())),
TEST_EPS);
Assert.assertEquals(0, circle.getXAxis().angle(reversed.getXAxis()), TEST_EPS);
Assert.assertEquals(Math.PI, circle.getYAxis().angle(reversed.getYAxis()), TEST_EPS);
Assert.assertEquals(Math.PI, circle.getPole().angle(reversed.getPole()), TEST_EPS);
Assert.assertTrue(circle.sameOrientationAs(circle));
Assert.assertFalse(circle.sameOrientationAs(reversed));
}
@Test
public void testPhase() {
Circle circle = new Circle(S2Point.of(1.2, 2.5), S2Point.of(-4.3, 0), TEST_PRECISION);
Vector3D p = Vector3D.of(1, 2, -4);
Vector3D samePhase = circle.getPointAt(circle.getPhase(p));
Assert.assertEquals(0.0,
circle.getPole().cross(p).angle(
circle.getPole().cross(samePhase)),
TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getPole().angle(samePhase), TEST_EPS);
Assert.assertEquals(circle.getPhase(p), circle.getPhase(samePhase), TEST_EPS);
Assert.assertEquals(0.0, circle.getPhase(circle.getXAxis()), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getPhase(circle.getYAxis()), TEST_EPS);
}
@Test
public void testSubSpace() {
Circle circle = new Circle(S2Point.of(1.2, 2.5), S2Point.of(-4.3, 0), TEST_PRECISION);
Assert.assertEquals(0.0, circle.toSubSpace(S2Point.ofVector(circle.getXAxis())).getAzimuth(), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.toSubSpace(S2Point.ofVector(circle.getYAxis())).getAzimuth(), TEST_EPS);
Vector3D p = Vector3D.of(1, 2, -4);
Assert.assertEquals(circle.getPhase(p), circle.toSubSpace(S2Point.ofVector(p)).getAzimuth(), TEST_EPS);
}
@Test
public void testSpace() {
Circle circle = new Circle(S2Point.of(1.2, 2.5), S2Point.of(-4.3, 0), TEST_PRECISION);
for (double alpha = 0; alpha < Geometry.TWO_PI; alpha += 0.1) {
Vector3D p = Vector3D.linearCombination(Math.cos(alpha), circle.getXAxis(),
Math.sin(alpha), circle.getYAxis());
Vector3D q = circle.toSpace(S1Point.of(alpha)).getVector();
Assert.assertEquals(0.0, p.distance(q), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getPole().angle(q), TEST_EPS);
}
}
@Test
public void testOffset() {
Circle circle = new Circle(Vector3D.Unit.PLUS_Z, TEST_PRECISION);
Assert.assertEquals(0.0, circle.getOffset(S2Point.ofVector(Vector3D.Unit.PLUS_X)), TEST_EPS);
Assert.assertEquals(0.0, circle.getOffset(S2Point.ofVector(Vector3D.Unit.MINUS_X)), TEST_EPS);
Assert.assertEquals(0.0, circle.getOffset(S2Point.ofVector(Vector3D.Unit.PLUS_Y)), TEST_EPS);
Assert.assertEquals(0.0, circle.getOffset(S2Point.ofVector(Vector3D.Unit.MINUS_Y)), TEST_EPS);
Assert.assertEquals(-0.5 * Math.PI, circle.getOffset(S2Point.ofVector(Vector3D.Unit.PLUS_Z)), TEST_EPS);
Assert.assertEquals(0.5 * Math.PI, circle.getOffset(S2Point.ofVector(Vector3D.Unit.MINUS_Z)), TEST_EPS);
}
@Test
public void testInsideArc() {
UnitSphereSampler sphRandom = new UnitSphereSampler(3, RandomSource.create(RandomSource.WELL_1024_A,
0xbfd34e92231bbcfel));
for (int i = 0; i < 100; ++i) {
Circle c1 = new Circle(Vector3D.of(sphRandom.nextVector()), TEST_PRECISION);
Circle c2 = new Circle(Vector3D.of(sphRandom.nextVector()), TEST_PRECISION);
checkArcIsInside(c1, c2);
checkArcIsInside(c2, c1);
}
}
private void checkArcIsInside(final Circle arcCircle, final Circle otherCircle) {
Arc arc = arcCircle.getInsideArc(otherCircle);
Assert.assertEquals(Math.PI, arc.getSize(), TEST_EPS);
for (double alpha = arc.getInf(); alpha < arc.getSup(); alpha += 0.1) {
Assert.assertTrue(otherCircle.getOffset(arcCircle.getPointAt(alpha)) <= 2.0e-15);
}
for (double alpha = arc.getSup(); alpha < arc.getInf() + Geometry.TWO_PI; alpha += 0.1) {
Assert.assertTrue(otherCircle.getOffset(arcCircle.getPointAt(alpha)) >= -2.0e-15);
}
}
@Test
public void testTransform() {
UniformRandomProvider random = RandomSource.create(RandomSource.WELL_1024_A,
0x16992fc4294bf2f1l);
UnitSphereSampler sphRandom = new UnitSphereSampler(3, random);
for (int i = 0; i < 100; ++i) {
QuaternionRotation r = QuaternionRotation.fromAxisAngle(Vector3D.of(sphRandom.nextVector()),
Math.PI * random.nextDouble());
Transform<S2Point, S1Point> t = Circle.getTransform(r);
S2Point p = S2Point.ofVector(Vector3D.of(sphRandom.nextVector()));
S2Point tp = t.apply(p);
Assert.assertEquals(0.0, r.apply(p.getVector()).distance(tp.getVector()), TEST_EPS);
Circle c = new Circle(Vector3D.of(sphRandom.nextVector()), TEST_PRECISION);
Circle tc = (Circle) t.apply(c);
Assert.assertEquals(0.0, r.apply(c.getPole()).distance(tc.getPole()), TEST_EPS);
Assert.assertEquals(0.0, r.apply(c.getXAxis()).distance(tc.getXAxis()), TEST_EPS);
Assert.assertEquals(0.0, r.apply(c.getYAxis()).distance(tc.getYAxis()), TEST_EPS);
Assert.assertSame(c.getPrecision(), ((Circle) t.apply(c)).getPrecision());
SubLimitAngle sub = new LimitAngle(S1Point.of(Geometry.TWO_PI * random.nextDouble()),
random.nextBoolean(), TEST_PRECISION).wholeHyperplane();
Vector3D psub = c.getPointAt(((LimitAngle) sub.getHyperplane()).getLocation().getAzimuth());
SubLimitAngle tsub = (SubLimitAngle) t.apply(sub, c, tc);
Vector3D ptsub = tc.getPointAt(((LimitAngle) tsub.getHyperplane()).getLocation().getAzimuth());
Assert.assertEquals(0.0, r.apply(psub).distance(ptsub), TEST_EPS);
}
}
}