package au.gov.amsa.util.navigation;
import static au.gov.amsa.util.navigation.Position.longitudeDiff;
import static au.gov.amsa.util.navigation.Position.to180;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import au.gov.amsa.util.navigation.Position.LongitudePair;
import com.google.common.collect.Lists;
/**
* @author sxo
*
*/
public class PositionTest {
private static final int ACCEPTABLE_DISTANCE_PRECISION = 3;
private static final double PRECISION = 0.00001;
private static final double MIN_DISTANCE_KM = 200;
private static Logger log = Logger.getLogger(PositionTest.class);
List<Position> squareRegion;
@Before
public void init() {
squareRegion = new ArrayList<Position>();
squareRegion.add(new Position(20, 20));
squareRegion.add(new Position(40, 20));
squareRegion.add(new Position(40, 40));
squareRegion.add(new Position(20, 40));
}
@Test
public final void testPredict() {
Position p = new Position(53, 3);
Position p2 = p.predict(100, 30);
Assert.assertEquals(53.77644258276322, p2.getLat(), 0.01);
Assert.assertEquals(3.7609191005595877, p2.getLon(), 0.01);
// large distance tests around the equator
double meanCircumferenceKm = 40041.47;
// start on equator, just East of Greenwich
p = new Position(0, 3);
// quarter circumference, Still in Eastern hemisphere
p2 = p.predict(meanCircumferenceKm / 4.0, 90);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(93.0, p2.getLon(), 0.1);
// half circumference, Now in Western hemisphere,
// just East of the International date line
p2 = p.predict(meanCircumferenceKm / 2.0, 90);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(-177.0, p2.getLon(), 0.1);
// three quarters circumference, Now in Western hemisphere,
p2 = p.predict(3.0 * meanCircumferenceKm / 4.0, 90);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(-87.0, p2.getLon(), 0.1);
// full circumference, back to start
// relax Longitude tolerance slightly
p2 = p.predict(meanCircumferenceKm, 90);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(p.getLon(), p2.getLon(), 0.2);
// same thing but backwards (heading west)
// quarter circumference, Still in western hemisphere
p2 = p.predict(meanCircumferenceKm / 4.0, 270);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(-87.0, p2.getLon(), 0.1);
// half circumference, Now in Western hemisphere,
// just East of the International date line
p2 = p.predict(meanCircumferenceKm / 2.0, 270);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(-177.0, p2.getLon(), 0.1);
// three quarters circumference, Now in eastern hemisphere,
p2 = p.predict(3.0 * meanCircumferenceKm / 4.0, 270);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(93.0, p2.getLon(), 0.1);
// full circumference, back to start
// relax Longitude tolerance slightly
p2 = p.predict(meanCircumferenceKm, 90);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.001);
Assert.assertEquals(p.getLon(), p2.getLon(), 0.2);
// OVER THE South POLE
// ===================
// quarter circumference, should be at south pole
p2 = p.predict(meanCircumferenceKm / 4.0, 180);
Assert.assertEquals(-90.0, p2.getLat(), 0.1);
// this next assertion is by no means confident
// expecting 3 but getting it's reciprocal.
// Strange things happen at the pole!!
Assert.assertEquals(-177, p2.getLon(), 0.00001);
// half circumference, should be at the equator
// but in the Western hemisphere
p2 = p.predict(meanCircumferenceKm / 2.0, 180);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.1);
Assert.assertEquals(-177, p2.getLon(), 0.00001);
// 3/4 circumference, should be at the north Pole
// but in the Western hemisphere
p2 = p.predict(3.0 * meanCircumferenceKm / 4.0, 180);
Assert.assertEquals(90.0, p2.getLat(), 0.1);
Assert.assertEquals(p.getLon(), p2.getLon(), 0.00001);
// full circumference, back to start
// relax latitude tolerance slightly
p2 = p.predict(meanCircumferenceKm, 270);
Assert.assertEquals(p.getLat(), p2.getLat(), 0.1);
Assert.assertEquals(p.getLon(), p2.getLon(), 0.2);
}
/**
* worked example from http://en.wikipedia.org/wiki/Great-circle_distance#
* Radius_for_spherical_Earth used for test below
*/
@Test
public final void testDistance() {
Position p1 = new Position(36.12, -86.67);
Position p2 = new Position(33.94, -118.4);
Assert.assertEquals(2886.45, p1.getDistanceToKm(p2), 0.01);
}
@Test
public final void testBearing() {
// test case taken from Geoscience Australia implementation of
// Vincenty formula.
// http://www.ga.gov.au/bin/gda_vincenty.cgi?inverse=0&lat_degrees1=-37&lat_minutes1=57&lat_seconds1=03.72030&NamePoint1=Flinders+Peak
// &lon_degrees1=144&lon_minutes1=25&lon_seconds1=29.52440&forward_azimuth_deg=306&forward_azimuth_min=52&forward_azimuth_sec=05.37
// &NamePoint2=Buninyong&ellipsoidal_dist=54972.217&lat_deg1=-37+deg&lat_min1=57+min&lat_sec1=3.7203+sec&lon_deg1=144+deg
// &lon_min1=25+min&lon_sec1=29.5244+sec&f_az_deg=306+deg&f_az_min=52+min&f_az_sec=5.37+sec&Submit=Submit+Data
// Note that we are not using Vincenty formula but we are close to the
// answer (within 0.2 degrees). That's sufficient!
Position p1 = new Position(-(37 + 57.0 / 60 + 3.72030 / 3600), 144
+ 25.0 / 60 + 29.52440 / 3600);
Position p2 = new Position(-(37 + 39.0 / 60 + 10.15718 / 3600), 143
+ 55.0 / 60 + 35.38564 / 3600);
Assert.assertEquals(Position.toDegrees(306, 52, 5.37),
p1.getBearingDegrees(p2), 0.2);
}
@Test
public final void testBearingToSelfReturnsZero() {
Position p = Position.create(-10, 120);
assertEquals(0, p.getBearingDegrees(p), PRECISION);
}
@Test
public final void testBearingToSameLonReturns180() {
Position p = Position.create(-10, 120);
Position p2 = Position.create(-15, 120);
assertEquals(180, p.getBearingDegrees(p2), PRECISION);
}
// @Test
// public final void
// testBearingWithSmallDeltaIsCorrectForTinyChangeInLatitude() {
// double delta = 0.00000000000000001;
// Position p = Position.create(-10, 120);
// Position p2 = Position.create(-10 - delta, 120);
// assertEquals(270, p.getBearingDegrees(p2), PRECISION);
// }
//
// @Test
// public final void
// testBearingWithSmallDeltaIsCorrectForTinyChangeInLongitude() {
// double delta = 0.00000000000000001;
// Position p = Position.create(-10, 120);
// Position p2 = Position.create(-10, 120 + delta);
// assertEquals(90, p.getBearingDegrees(p2), PRECISION);
// }
@Test
public final void testBearingDifference() {
double precision = 0.00001;
Assert.assertEquals(15.0, Position.getBearingDifferenceDegrees(20, 5),
precision);
Assert.assertEquals(15.0,
Position.getBearingDifferenceDegrees(20, 365), precision);
Assert.assertEquals(15.0, Position.getBearingDifferenceDegrees(20, 5),
precision);
Assert.assertEquals(15.0, Position.getBearingDifferenceDegrees(380, 5),
precision);
Assert.assertEquals(-25, Position.getBearingDifferenceDegrees(-20, 5),
precision);
Assert.assertEquals(5, Position.getBearingDifferenceDegrees(-20, -25),
precision);
}
@Test
public final void testLatLonPresentation() {
char d = 0x00B0;
char m = '\'';
Assert.assertEquals("25" + d + "30.00" + m + "S",
Position.toDegreesMinutesDecimalMinutesLatitude(-25.5));
Assert.assertEquals("0" + d + "00.00" + m + "N",
Position.toDegreesMinutesDecimalMinutesLatitude(0));
Assert.assertEquals("0" + d + "30.00" + m + "S",
Position.toDegreesMinutesDecimalMinutesLatitude(-0.5));
Assert.assertEquals("0" + d + "30.00" + m + "N",
Position.toDegreesMinutesDecimalMinutesLatitude(0.5));
Assert.assertEquals("1" + d + "30.00" + m + "N",
Position.toDegreesMinutesDecimalMinutesLatitude(1.5));
Assert.assertEquals("1" + d + "00.00" + m + "N",
Position.toDegreesMinutesDecimalMinutesLatitude(1.0));
Assert.assertEquals("1" + d + "00.00" + m + "E",
Position.toDegreesMinutesDecimalMinutesLongitude(1.0));
Assert.assertEquals("1" + d + "00.00" + m + "W",
Position.toDegreesMinutesDecimalMinutesLongitude(-1.0));
}
@Test
public final void testGetPositionAlongPath() {
// Create new position objects
Position p1 = new Position(36.12, -86.67);
Position p2 = new Position(33.94, -118.4);
{
double distanceKm = p1.getDistanceToKm(p2);
double bearingDegrees = p1.getBearingDegrees(p2);
Position p3 = p1.predict(distanceKm * 0.7, bearingDegrees);
// Expected position
Position actual = p1.getPositionAlongPath(p2, 0.7);
// Test expected Lat return position
Assert.assertEquals(p3.getLat(), actual.getLat(), 0.01);
// Test expected Lon return position
Assert.assertEquals(p3.getLon(), actual.getLon(), 0.01);
// Test expected Lat return position
Assert.assertEquals(35.47, actual.getLat(), 0.01);
// Test expected Lon return position
Assert.assertEquals(-109.11, actual.getLon(), 0.01);
}
{
// If start point equals end point then a proportion
// along the path should equal the start point.
Position actual = p1.getPositionAlongPath(p1, 0.7);
// Test expected Lat return position
Assert.assertEquals(p1.getLat(), actual.getLat(), 0.01);
// Test expected Lon return position
Assert.assertEquals(p1.getLon(), actual.getLon(), 0.01);
}
{
// If proportion is 0.0 then should return start point
Position actual = p1.getPositionAlongPath(p2, 0.0);
// Test expected Lat return position
Assert.assertEquals(p1.getLat(), actual.getLat(), 0.01);
// Test expected Lon return position
Assert.assertEquals(p1.getLon(), actual.getLon(), 0.01);
}
{
// If proportion is 1.0 then should return end point
Position actual = p1.getPositionAlongPath(p2, 1.0);
// Test expected Lat return position
Assert.assertEquals(p2.getLat(), actual.getLat(), 0.01);
// Test expected Lon return position
Assert.assertEquals(p2.getLon(), actual.getLon(), 0.01);
}
}
@Test(expected = RuntimeException.class)
public final void testGetPositionAlongPathExceptionsGreater() {
// Create new position objects
Position p1 = new Position(36.12, -86.67);
Position p2 = new Position(33.94, -118.4);
p1.getPositionAlongPath(p2, 1.1);
}
@Test(expected = RuntimeException.class)
public final void testGetPositionAlongPathExceptionsLess() {
// Create new position objects
Position p1 = new Position(36.12, -86.67);
Position p2 = new Position(33.94, -118.4);
p1.getPositionAlongPath(p2, -0.1);
}
@Test(expected = NullPointerException.class)
public final void testGetPositionAlongPathExceptionsNull() {
// Create new position objects
Position p1 = new Position(36.12, -86.67);
p1.getPositionAlongPath(null, 0.7);
}
@Test
public final void testEnsureContinuous() {
{
Position a = new Position(-35, 179);
Position b = new Position(-35, -178);
Position c = b.ensureContinuous(a);
Assert.assertEquals(182, c.getLon(), 0.0001);
Assert.assertEquals(b.getLat(), c.getLat(), 0.0001);
}
{
Position a = new Position(-35, -2);
Position b = new Position(-35, 360);
Position c = b.ensureContinuous(a);
Assert.assertEquals(0, c.getLon(), 0.0001);
}
}
@Test
public final void testIsWithin() {
final List<Position> testRegion;
// square polygon with v cut out shape
testRegion = Lists.newArrayList();
testRegion.add(new Position(-20, 130));
testRegion.add(new Position(-20, 140));
testRegion.add(new Position(-30, 140));
testRegion.add(new Position(-25, 135));
testRegion.add(new Position(-30, 130));
Position bothLatAndLongInsideRegion = new Position(-24, 135);
Position bothLatAndLongOutsideRegion = new Position(-35, 145);
Position latInAndLongOutRegion = new Position(-25, 145);
Position latOutAndLongInRegion = new Position(-35, 135);
Position latInAndLongInVRegion = new Position(-28, 138);
Position latOutAndLongOutVRegion = new Position(-26, 135);
Position bothLatAndLongOnBorder = new Position(-20, 135);
Position bothLatAndLongOnOutsideCorner = new Position(-20, 130);
Position bothLatAndLongOnInsideCorner = new Position(-25, 135);
Assert.assertTrue(bothLatAndLongInsideRegion.isWithin(testRegion));
Assert.assertTrue(latInAndLongInVRegion.isWithin(testRegion));
Assert.assertTrue(bothLatAndLongOnInsideCorner.isWithin(testRegion));
Assert.assertFalse(bothLatAndLongOutsideRegion.isWithin(testRegion));
Assert.assertFalse(latInAndLongOutRegion.isWithin(testRegion));
Assert.assertFalse(latOutAndLongInRegion.isWithin(testRegion));
Assert.assertFalse(latOutAndLongOutVRegion.isWithin(testRegion));
Assert.assertFalse(bothLatAndLongOnBorder.isWithin(testRegion));
Assert.assertFalse(bothLatAndLongOnOutsideCorner.isWithin(testRegion));
}
/**
* Returned intersection occurs in the centre of the segment and the segment
* latitude is constant.
*/
@Test
public void testGetClosestIntersectionWithSegment1() {
Position p = new Position(-30, 120);
Position r = p.getClosestIntersectionWithSegment(
new Position(-20, 110), new Position(-20, 130));
log.info(r.getLon());
log.info(r.getLat());
assertEquals(-20.0, r.getLat(), 1);
assertEquals(120.0, r.getLon(), 1);
}
/**
* Returned intersection doesn't occur in the centre of the segment and the
* segment latitude is constant.
*/
@Test
public void testGetClosestIntersectionWithSegment2() {
Position p = new Position(-30, 110);
Position r = p.getClosestIntersectionWithSegment(
new Position(-20, 100), new Position(-20, 130));
log.info(r.getLon());
log.info(r.getLat());
assertEquals(-20.58106, r.getLat(), PRECISION);
assertEquals(110.218334, r.getLon(), PRECISION);
}
/**
* Returned intersection occurs in the centre of the segment and the segment
* longitude is constant.
*/
@Test
public void testGetClosestIntersectionWithSegment3() {
Position p = new Position(-30, 120);
Position r = p.getClosestIntersectionWithSegment(
new Position(-20, 110), new Position(-20, 130));
log.info(r.getLon());
log.info(r.getLat());
assertEquals(-20.28353, r.getLat(), PRECISION);
assertEquals(119.90349, r.getLon(), PRECISION);
}
/**
* Returned intersection doesn't occur in the centre of the segment and the
* segment longitude is constant.
*/
@Test
public void testGetClosestIntersectionWithSegment4() {
Position p = new Position(-30, 110);
Position r = p.getClosestIntersectionWithSegment(
new Position(-20, 100), new Position(-20, 130));
// log.info(r.getLon());
// log.info(r.getLat());
assertEquals(-20.58106, r.getLat(), PRECISION);
assertEquals(110.218334, r.getLon(), PRECISION);
}
/**
* The test position should return the closest distance to the segment when
* it's perpendicular to the segment.
*/
@Test
public void testGetDistanceToSegmentKm1() {
Position p = new Position(-30, 110);
Position sp1 = new Position(-20, 100);
Position sp2 = new Position(-20, 130);
double r = p.getDistanceToSegmentKm(sp1, sp2);
// log.info(r);
Position intersection = p.getClosestIntersectionWithSegment(sp1, sp2);
log.info("Position of intersection, used to manually calculate the distance via http://www.nhc.noaa.gov/gccalc.shtml : "
+ intersection);
// 1047 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(1047, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* The test position should return the distance to the closest segment end
* when the intersection falls out of the given segment. In this test the
* position is closest to the <b>first</b> point of the segment.
*/
public void testGetDistanceToSegmentKm2() {
Position p = new Position(-10, 115);
// Segment made of two points
Position sp1 = new Position(-30, 140);
Position sp2 = new Position(-30, 140);
Position r1 = p.getClosestIntersectionWithSegment(sp1, sp2);
// log.info(r1.getLat());
// log.info(r1.getLon());
assertEquals(sp1.getLat(), r1.getLat(), PRECISION);
assertEquals(sp1.getLon(), r1.getLon(), PRECISION);
}
/**
* The test position should return the distance to the closest segment end
* when the intersection falls out of the given segment. In this test the
* position is closest to the <b>second</b> point of the segment.
*/
public void testGetDistanceToSegmentKm3() {
Position p = new Position(-10, 150);
// Segment made of two points
Position sp1 = new Position(-20, 120);
Position sp2 = new Position(-30, 140);
Position r = p.getClosestIntersectionWithSegment(sp1, sp2);
// log.info(r.getLat());
// log.info(r.getLon());
assertEquals(sp2.getLat(), r.getLat(), PRECISION);
assertEquals(sp2.getLon(), r.getLon(), PRECISION);
}
/**
* Test the position when the segment's start and end points are identical.
* In this test the position is closest to the both the start and end
* points.
*/
@Test
public void testGetDistanceToSegmentKm4() {
Position p = new Position(-10, 150);
// Segment made of two points
Position sp1 = new Position(-20, 120);
Position sp2 = new Position(-20, 120);
double r = p.getDistanceToSegmentKm(sp1, sp2);
log.info(r);
// log.info(r.getLon());
// 3399.0 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(3399.0, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* Test the position when the it lies on segment. In this test the position
* should return 0 since it lies on the line.
*/
@Test
public void testGetDistanceToSegmentKm5() {
// Segment made of two points
Position sp1 = new Position(-10, 120);
Position p = sp1.getPositionAlongPath(sp1, 0.4);
Position sp2 = new Position(-10, 150);
double r = p.getDistanceToSegmentKm(sp1, sp2);
assertEquals(0, r, PRECISION);
}
/**
* Test the position when it lies outside of the segment but in line(great
* cirle path) with the two segment points. In this test the position is
* closest to the <b>second</b> segment point.
*/
@Test
public void testGetDistanceToSegmentKm6() {
// Segment made of two points
Position sp1 = new Position(-10, 120);
Position p = new Position(-10, 150);
Position sp2 = sp1.getPositionAlongPath(p, 0.5);
log.info(sp2);
double r = p.getDistanceToSegmentKm(sp1, sp2);
// 1641 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(1641.00, r, ACCEPTABLE_DISTANCE_PRECISION);
log.info(r);
}
/**
* The test position should return the closest distance to either a segment
* point or segment intersection on the path. The path constitutes several
* valid {@link Position}'s. In this test the point is closest to the
* <b>first segment</b>.
*/
@Test
public void testGetDistanceToPathKm1() {
// positions to test
Position p = new Position(-10, 115);
// segment positions constituting a path
Position sp1 = new Position(-30, 100);
Position sp2 = new Position(-20, 120);
Position sp3 = new Position(-30, 140);
// path with two segments
List<Position> path = new ArrayList<Position>();
path.add(sp1);
path.add(sp2);
path.add(sp3);
// expect that the closes point will be sp2 itself since the test
// position can't be perpendicular to the segment and sp2 is the closest
// point.
double r = p.getDistanceToPathKm(path);
log.info(r);
Position intersection = p.getClosestIntersectionWithSegment(sp1, sp2);
log.info("Position of intersection, used to manually calculate the distance via http://www.nhc.noaa.gov/gccalc.shtml : "
+ intersection);
// 1234 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(1234, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* The test position should return the closest distance to either a segment
* point or segment intersection on the path. The path constitutes several
* valid {@link Position}'s. In this test the point is closest to the
* <b>first segment start position</b> .
*/
@Test
public void testGetDistanceToPathKm2() {
// positions to test
Position p = new Position(-10, 80);
// segment positions constituting a path
Position sp1 = new Position(-30, 100);
Position sp2 = new Position(-20, 120);
Position sp3 = new Position(-30, 140);
// path with two segments
List<Position> path = new ArrayList<Position>();
path.add(sp1);
path.add(sp2);
path.add(sp3);
// expect that the closes point will be sp2 itself since the test
// position can't be perpendicular to the segment and sp2 is the closest
// point.
double r = p.getDistanceToPathKm(path);
log.info(r);
// 3039 accroding to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(3039, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* The test position should return the closest distance to either a segment
* point or segment intersection on the path. The path constitutes several
* valid {@link Position}'s. In this test the point is closest to the
* <b>second segment</b>.
*/
@Test
public void testGetDistanceToPathKm3() {
// positions to test
Position p = new Position(-10, 115);
// segment positions constituting a path
Position sp1 = new Position(-30, 100);
Position sp2 = new Position(-20, 120);
Position sp3 = new Position(-30, 140);
// path with two segments
List<Position> path = new ArrayList<Position>();
path.add(sp1);
path.add(sp2);
path.add(sp3);
// expect that the closes point will be sp2 itself since the test
// position can't be perpendicular to the segment and sp2 is the closest
// point.
double r = p.getDistanceToPathKm(path);
log.info(r);
Position intersection = p.getClosestIntersectionWithSegment(sp1, sp2);
log.info("Position of intersection, used to manually calculate the distance via http://www.nhc.noaa.gov/gccalc.shtml : "
+ intersection);
// 1234 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(1234, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* The test position should return the closest distance to either a segment
* point or segment intersection on the path. The path constitutes several
* valid {@link Position}'s. In this test the point is closest to the
* <b>second segment end position</b>.
*/
@Test
public void testGetDistanceToPathKm4() {
// positions to test
Position p = new Position(-10, 150);
// segment positions constituting a path
Position sp1 = new Position(-30, 100);
Position sp2 = new Position(-20, 120);
Position sp3 = new Position(-30, 140);
// path with two segments
List<Position> path = new ArrayList<Position>();
path.add(sp1);
path.add(sp2);
path.add(sp3);
// expect that the closes point will be sp2 itself since the test
// position can't be perpendicular to the segment and sp2 is the closest
// point.
double r = p.getDistanceToPathKm(path);
log.info(r);
// 2452 according http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(2452, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* Test when a position is given an empty path.
*/
@Test(expected = RuntimeException.class)
public void testGetDistanceToPathKm5() {
// empty initialized list
List<Position> path = new ArrayList<Position>();
// positions to test
Position p = new Position(-10, 150);
p.getDistanceToPathKm(path);
}
/**
* Test when a position is given a null path.
*/
@Test(expected = NullPointerException.class)
public void testGetDistanceToPathKm6() {
// empty initialized list
List<Position> path = null;
// positions to test
Position p = new Position(-10, 150);
p.getDistanceToPathKm(path);
}
/**
* Test when a position is given a path with only one position in it.
*/
@Test
public void testGetDistanceToPathKm7() {
// empty initialized list
List<Position> path = new ArrayList<Position>();
path.add(new Position(-30, 100));
// positions to test
Position p = new Position(-30, 120);
double r = p.getDistanceToPathKm(path);
// 1922 according to http://www.nhc.noaa.gov/gccalc.shtml
assertEquals(1922, r, ACCEPTABLE_DISTANCE_PRECISION);
}
/**
* Test when a position is outside a given region consisting of several
* joining points. In this test the region is a roughly square region
* consisting of four segments or eight {@link Position}s. The test position
* is outside the region but within minimum distance in km.
*/
@Test
public void testIsOutside1() {
Position p = new Position(30, 19.99);
assertFalse(p.isOutside(squareRegion, MIN_DISTANCE_KM));
}
/**
* Test when a position is outside a given region consisting of several
* joining points. In this test the region is a roughly square region
* consisting of four segments or eight {@link Position}s. The test position
* is outside both the region and the minimum distance in km.
*/
@Test
public void testIsOutside2() {
Position p = new Position(-10, 110);
assertTrue(p.isOutside(squareRegion, MIN_DISTANCE_KM));
}
/**
* Test when a position is outside a given region consisting of several
* joining points. In this test the region is a roughly square region
* consisting of four segments or eight {@link Position}s. The test position
* is on the region path.
*/
@Test
public void testIsOutside3() {
Position p = new Position(20.07030897931526, 24.999999999999996);
assertFalse(p.isOutside(squareRegion, MIN_DISTANCE_KM));
}
/**
* Test when a position is outside a given region consisting of several
* joining points. In this test the region is a roughly square region
* consisting of four segments or eight {@link Position}s. The test position
* is within the region path.
*/
@Test
public void testIsOutside4() {
Position p = new Position(30, 30);
assertFalse(p.isOutside(squareRegion, MIN_DISTANCE_KM));
}
@Test
public void testTo180() {
assertEquals(0, to180(0), PRECISION);
assertEquals(10, to180(10), PRECISION);
assertEquals(-10, to180(-10), PRECISION);
assertEquals(180, to180(180), PRECISION);
assertEquals(-180, to180(-180), PRECISION);
assertEquals(-170, to180(190), PRECISION);
assertEquals(170, to180(-190), PRECISION);
assertEquals(-170, to180(190 + 360), PRECISION);
}
@Test
public void testLongitudeDiff() {
assertEquals(10, longitudeDiff(15, 5), PRECISION);
assertEquals(10, longitudeDiff(-175, 175), PRECISION);
assertEquals(350, longitudeDiff(175, -175), PRECISION);
}
@Test
public void testGetLatitudeOnGreatCircleSameLatitudeHalfwayToSouthPole() {
Position a = Position.create(-45, 20);
Position b = Position.create(-45, 30);
System.out.println(a.getBearingDegrees(b));
Double halfwayLat = a.getLatitudeOnGreatCircle(b, 25);
assertEquals(-45, halfwayLat, 1.0);
}
@Test
public void testGetLatitudeOnGreatCircleBothPointsOnEquator() {
Position a = Position.create(0, 20);
Position b = Position.create(0, 30);
System.out.println(a.getBearingDegrees(b));
Double halfwayLat = a.getLatitudeOnGreatCircle(b, 25);
assertEquals(0, halfwayLat, 0.1);
}
@Test
public void testGetLatitudeOnGreatCircleFromLaxToJfk() {
Position a = Position.create(33 + 57 / 60.0, -118 - 24 / 60.0);
Position b = Position.create(40 + 38 / 60.0, -73 - 47 / 60.0);
System.out.println(a.getBearingDegrees(b));
Double halfwayLat = a.getLatitudeOnGreatCircle(b, -111);
assertEquals(36 + 24 / 60.0, halfwayLat, 0.1);
}
@Test
public void testGetLatitudeOnGreatCircleForSmallSegment() {
Position a = Position.create(-40, 100);
Position b = Position.create(-40, 100.016);
System.out.println(a.getBearingDegrees(b));
Double halfwayLat = a.getLatitudeOnGreatCircle(b, 100.008);
assertEquals(-40, halfwayLat, 0.001);
}
@Test
public void testGetLongitudeOnGreatCircleFromLaxToJfk() {
Position a = Position.create(33 + 57 / 60.0, -118 - 24 / 60.0);
Position b = Position.create(40 + 38 / 60.0, -73 - 47 / 60.0);
System.out.println(a.getBearingDegrees(b));
LongitudePair candidates = a.getLongitudeOnGreatCircle(b,
36 + 23.65967428 / 60.0);
System.out.println(candidates);
assertEquals(-111, candidates.getLon1(), PRECISION);
assertEquals(-48.391565812643, candidates.getLon2(), PRECISION);
}
}