/*******************************************************************************
* Copyright 2014 Geoscience Australia
*
* Licensed 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 au.gov.ga.earthsci.worldwind.common.view.orbit;
import static org.junit.Assert.assertEquals;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.Matrix;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.globes.EllipsoidalGlobe;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.terrain.ZeroElevationModel;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*
*/
public class ViewStateTest
{
private static final double GLOBE_RADIUS = 50;
private static final double SQRTHALF = Math.sqrt(0.5);
private static final double EPSILON = 1e-9;
private static Globe globe;
private IViewState classUnderTest;
@BeforeClass
public static void setupClass()
{
globe = new EllipsoidalGlobe(GLOBE_RADIUS, GLOBE_RADIUS, 0, new ZeroElevationModel());
}
@Before
public void setup()
{
classUnderTest = new ViewState();
}
@Test
public void testInitialState()
{
Matrix expected = Matrix.fromTranslation(0, 0, -GLOBE_RADIUS - classUnderTest.getZoom());
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
}
@Test
public void testHeading()
{
classUnderTest.setHeading(Angle.fromDegrees(90));
Matrix expected = new Matrix(
0.0, 1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(90, classUnderTest.getHeading().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
expected = new Matrix(
-SQRTHALF, SQRTHALF, 0.0, 0.0,
SQRTHALF, SQRTHALF, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(45, classUnderTest.getHeading().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
}
@Test
public void testPitch()
{
classUnderTest.setPitch(Angle.fromDegrees(90));
Matrix expected = new Matrix(
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(90, classUnderTest.getPitch().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(45));
expected = new Matrix(
-1.0, 0.0, 0.0, 0.0,
0.0, SQRTHALF, SQRTHALF, 0.0,
0.0, SQRTHALF, -SQRTHALF, 0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(45, classUnderTest.getPitch().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
}
@Test
public void testRoll()
{
classUnderTest.setRoll(Angle.fromDegrees(90));
Matrix expected = new Matrix(
0.0, -1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(90, classUnderTest.getRoll().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(45));
expected = new Matrix(
-SQRTHALF, -SQRTHALF, 0.0, 0.0,
-SQRTHALF, SQRTHALF, 0.0, 0.0,
0.0, 0.0, -1.0, -0.0,
0.0, 0.0, 0.0, 1.0);
assertEquals(45, classUnderTest.getRoll().degrees, EPSILON);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
}
@Test
public void testZoom()
{
double zoomTest = 10;
classUnderTest.setZoom(zoomTest);
assertEquals(zoomTest, classUnderTest.getZoom(), EPSILON);
Matrix expected = Matrix.fromTranslation(0, 0, -globe.getRadius() - zoomTest);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
Vec4 eyePoint = classUnderTest.getEyePoint(globe);
Vec4 centerPoint = classUnderTest.getCenterPoint(globe);
assertEquals(zoomTest, eyePoint.distanceTo3(centerPoint), EPSILON);
}
@Test
public void testCenter()
{
Vec4 expected = new Vec4(0.0, 0.0, GLOBE_RADIUS, 1.0);
assertVec4Equals(expected, classUnderTest.getCenterPoint(globe), EPSILON);
double elevation = 40;
Position expectedPosition = Position.fromDegrees(45, 45, elevation);
classUnderTest.setCenter(expectedPosition);
expected = new Vec4((GLOBE_RADIUS + elevation) * 0.5, (GLOBE_RADIUS + elevation) * SQRTHALF,
(GLOBE_RADIUS + elevation) * 0.5, 1.0);
assertPositionEquals(expectedPosition, classUnderTest.getCenter(), EPSILON);
assertVec4Equals(expected, classUnderTest.getCenterPoint(globe), EPSILON);
}
@Test
public void testEye()
{
Vec4 expected = new Vec4(0.0, 0.0, GLOBE_RADIUS + classUnderTest.getZoom(), 1.0);
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
//changing the heading with pitch == 0 shouldn't change the eye point
classUnderTest.setHeading(Angle.fromDegrees(90));
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
classUnderTest.setCenter(Position.fromDegrees(45, 45));
classUnderTest.setZoom(20);
assertPositionEquals(Position.fromDegrees(45, 45, classUnderTest.getZoom()), classUnderTest.getEye(globe),
EPSILON);
expected = new Vec4((GLOBE_RADIUS + classUnderTest.getZoom()) * 0.5, (GLOBE_RADIUS + classUnderTest.getZoom())
* SQRTHALF, (GLOBE_RADIUS + classUnderTest.getZoom()) * 0.5, 1.0);
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
classUnderTest.setCenter(Position.ZERO);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Vec4(-classUnderTest.getZoom(), 0.0, GLOBE_RADIUS, 1.0);
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
classUnderTest.setZoom(10);
expected = new Vec4(-classUnderTest.getZoom(), 0.0, GLOBE_RADIUS, 1.0);
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
expected =
new Vec4(-classUnderTest.getZoom() * SQRTHALF, -classUnderTest.getZoom() * SQRTHALF, GLOBE_RADIUS, 1.0);
assertVec4Equals(expected, classUnderTest.getEyePoint(globe), EPSILON);
Position expectedEye = Position.fromDegrees(50, 50, 50);
classUnderTest.setEye(expectedEye, globe);
assertPositionEquals(expectedEye, classUnderTest.getEye(globe), EPSILON);
Position expectedCenter = Position.fromDegrees(40, 40, 0);
classUnderTest.setCenter(expectedCenter);
classUnderTest.setEye(expectedEye, globe);
assertPositionEquals(expectedCenter, classUnderTest.getCenter(), EPSILON);
assertPositionEquals(expectedEye, classUnderTest.getEye(globe), EPSILON);
expectedCenter = Position.fromDegrees(50, 50, 0);
Angle previousHeading = classUnderTest.getHeading();
classUnderTest.setCenter(expectedCenter);
classUnderTest.setEye(expectedEye, globe);
assertPositionEquals(expectedCenter, classUnderTest.getCenter(), EPSILON);
assertPositionEquals(expectedEye, classUnderTest.getEye(globe), EPSILON);
assertEquals(0, classUnderTest.getPitch().degrees, EPSILON);
assertEquals(previousHeading.degrees, classUnderTest.getHeading().degrees, EPSILON);
expectedCenter = Position.fromDegrees(50, 50, 50);
expectedEye = Position.fromDegrees(40, 40, 20);
classUnderTest.setCenter(expectedCenter);
classUnderTest.setEye(expectedEye, globe);
assertPositionEquals(expectedCenter, classUnderTest.getCenter(), EPSILON);
assertPositionEquals(expectedEye, classUnderTest.getEye(globe), EPSILON);
Assert.assertTrue(classUnderTest.getPitch().degrees > 90);
}
@Test
public void testUp()
{
Vec4 expected = new Vec4(0.0, 1.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getUp(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(90));
expected = new Vec4(1.0, 0.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getUp(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Vec4(0.0, 0.0, 1.0, 1.0);
assertVec4Equals(expected, classUnderTest.getUp(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(90));
expected = new Vec4(0.0, 1.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getUp(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
classUnderTest.setPitch(Angle.fromDegrees(45));
classUnderTest.setRoll(Angle.ZERO);
expected = new Vec4(0.5, 0.5, SQRTHALF, 1.0);
assertVec4Equals(expected, classUnderTest.getUp(globe), EPSILON);
}
@Test
public void testSide()
{
Vec4 expected = new Vec4(-1.0, 0.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getSide(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(90));
expected = new Vec4(0.0, 1.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getSide(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Vec4(0.0, 1.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getSide(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(90));
expected = new Vec4(0.0, 0.0, -1.0, 1.0);
assertVec4Equals(expected, classUnderTest.getSide(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
classUnderTest.setPitch(Angle.fromDegrees(45));
classUnderTest.setRoll(Angle.ZERO);
expected = new Vec4(-SQRTHALF, SQRTHALF, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getSide(globe), EPSILON);
}
@Test
public void testForward()
{
Vec4 expected = new Vec4(0.0, 0.0, -1.0, 1.0);
assertVec4Equals(expected, classUnderTest.getForward(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(90));
expected = new Vec4(0.0, 0.0, -1.0, 1.0);
assertVec4Equals(expected, classUnderTest.getForward(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Vec4(1.0, 0.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getForward(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(90));
expected = new Vec4(1.0, 0.0, 0.0, 1.0);
assertVec4Equals(expected, classUnderTest.getForward(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
classUnderTest.setPitch(Angle.fromDegrees(45));
classUnderTest.setRoll(Angle.ZERO);
expected = new Vec4(0.5, 0.5, -SQRTHALF, 1.0);
assertVec4Equals(expected, classUnderTest.getForward(globe), EPSILON);
}
@Test
public void testRotation()
{
Matrix expected = new Matrix(
-1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(90));
expected = new Matrix(
0.0, 1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Matrix(
0.0, 0.0, 1.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(90));
expected = new Matrix(
0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
classUnderTest.setPitch(Angle.fromDegrees(45));
classUnderTest.setRoll(Angle.ZERO);
expected = new Matrix(
-SQRTHALF, 0.5, 0.5, 0.0,
SQRTHALF, 0.5, 0.5, 0.0,
0.0, SQRTHALF, -SQRTHALF, 0.0,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getRotation(globe), EPSILON);
}
@Test
public void testTransform()
{
Matrix expected = new Matrix(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, -GLOBE_RADIUS - classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(90));
expected = new Matrix(
0.0, -1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, -GLOBE_RADIUS - classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setPitch(Angle.fromDegrees(90));
expected = new Matrix(
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, -GLOBE_RADIUS,
-1.0, 0.0, 0.0, -classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setRoll(Angle.fromDegrees(90));
expected = new Matrix(
0.0, 0.0, 1.0, -GLOBE_RADIUS,
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, -classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setHeading(Angle.fromDegrees(45));
classUnderTest.setPitch(Angle.fromDegrees(45));
classUnderTest.setRoll(Angle.ZERO);
expected = new Matrix(
SQRTHALF, -SQRTHALF, 0.0, 0.0,
0.5, 0.5, SQRTHALF, -SQRTHALF * GLOBE_RADIUS,
-0.5, -0.5, SQRTHALF, -SQRTHALF * GLOBE_RADIUS - classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setZoom(50);
expected = new Matrix(
SQRTHALF, -SQRTHALF, 0.0, 0.0,
0.5, 0.5, SQRTHALF, -SQRTHALF * GLOBE_RADIUS,
-0.5, -0.5, SQRTHALF, -SQRTHALF * GLOBE_RADIUS - classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setCenter(Position.fromDegrees(45, 45));
expected = new Matrix(
(SQRTHALF + 1.0) * 0.5, -0.5, (SQRTHALF - 1.0) * 0.5, 0.0,
SQRTHALF - 0.25, (SQRTHALF + 1.0) * 0.5, -0.25, -SQRTHALF * GLOBE_RADIUS,
0.25, (1.0 - SQRTHALF) * 0.5, SQRTHALF + 0.25, -SQRTHALF * GLOBE_RADIUS - classUnderTest.getZoom(),
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
classUnderTest.setCenter(Position.fromDegrees(12, 34));
classUnderTest.setHeading(Angle.fromDegrees(56));
classUnderTest.setPitch(Angle.fromDegrees(78));
classUnderTest.setRoll(Angle.fromDegrees(91));
classUnderTest.setZoom(23);
expected = new Matrix(
0.654527728349612, 0.33119467416635756, 0.6796348583065297, -48.899931205822476,
-0.5714882330999435, 0.8052636139982711, 0.15796110723449525, 0.8535514741830017,
-0.4949693447576333, -0.49179324901251276, 0.7163412231443305, -33.39558454088797,
0.0, 0.0, 0.0, 1.0);
assertMatrixEquals(expected, classUnderTest.getTransform(globe), EPSILON);
}
private static void assertMatrixEquals(Matrix expected, Matrix actual, double delta)
{
try
{
assertEquals(expected.m11, actual.m11, delta);
assertEquals(expected.m12, actual.m12, delta);
assertEquals(expected.m13, actual.m13, delta);
assertEquals(expected.m14, actual.m14, delta);
assertEquals(expected.m21, actual.m21, delta);
assertEquals(expected.m22, actual.m22, delta);
assertEquals(expected.m23, actual.m23, delta);
assertEquals(expected.m24, actual.m24, delta);
assertEquals(expected.m31, actual.m31, delta);
assertEquals(expected.m32, actual.m32, delta);
assertEquals(expected.m33, actual.m33, delta);
assertEquals(expected.m34, actual.m34, delta);
assertEquals(expected.m41, actual.m41, delta);
assertEquals(expected.m42, actual.m42, delta);
assertEquals(expected.m43, actual.m43, delta);
assertEquals(expected.m44, actual.m44, delta);
}
catch (AssertionError e)
{
assertEquals(expected, actual);
}
}
private static void assertVec4Equals(Vec4 expected, Vec4 actual, double delta)
{
try
{
assertEquals(expected.x, actual.x, delta);
assertEquals(expected.y, actual.y, delta);
assertEquals(expected.z, actual.z, delta);
assertEquals(expected.w, actual.w, delta);
}
catch (AssertionError e)
{
assertEquals(expected, actual);
}
}
private static void assertPositionEquals(Position expected, Position actual, double delta)
{
try
{
assertEquals(expected.latitude.degrees, actual.latitude.degrees, delta);
assertEquals(expected.longitude.degrees, actual.longitude.degrees, delta);
assertEquals(expected.elevation, actual.elevation, delta);
}
catch (AssertionError e)
{
assertEquals(expected, actual);
}
}
}