+
+ @Test
+ public void testAddCoordinates() {
+
+ double min = 1 / 60.0;
+ double sec = 1 / 3600.0;
+
+
+ // Test zero movement
+ testAddCoordinate(50.0, 20.0, 0, 123, 50.0, 20.0, false);
+
+
+ /*
+ * These example values have been computed using the calculator at
+ * http://www.movable-type.co.uk/scripts/latlong.html
+ */
+
+ // Long distance NE over England, crosses Greenwich meridian
+ // 50 03N 005 42W to 58 38N 003 04E is 1109km at 027 16'07"
+ testAddCoordinate(50 + 3 * min, -5 - 42 * min, 1109000, 27 + 16 * min + 7 * sec, 58 + 38 * min, 3 + 4 * min, false);
+
+ // SW over Brazil
+ // -10N -60E to -11N -61E is 155.9km at 224 25'34"
+ testAddCoordinate(-10, -60, 155900, 224 + 25 * min + 34 * sec, -11, -61, true);
+
+ // NW over the 180 meridian
+ // 63N -179E to 63 01N 179E is 100.9km at 271 56'34"
+ testAddCoordinate(63, -179, 100900, 271 + 56 * min + 34 * sec, 63 + 1 * min, 179, true);
+
+ // NE near the north pole
+ // 89 50N 0E to 89 45N 175E is 46.29 km at 003 00'01"
+ testAddCoordinate(89 + 50 * min, 0, 46290, 3 + 0 * min + 1 * sec, 89 + 45 * min, 175, false);
+
+ // S directly over south pole
+ // -89 50N 12E to -89 45N 192E is 46.33km at 180 00'00"
+ testAddCoordinate(-89 - 50 * min, 12, 46330, 180, -89 - 45 * min, -168, false);
+
+ }
+
+ private void testAddCoordinate(double initialLatitude, double initialLongitude, double distance, double bearing,
+ double finalLatitude, double finalLongitude, boolean testFlat) {
+
+ double tolerance;
+
+ bearing = Math.toRadians(bearing);
+
+ // positive X is EAST, positive Y is NORTH
+ double deltaX = distance * Math.sin(bearing);
+ double deltaY = distance * Math.cos(bearing);
+
+ Coordinate coord = new Coordinate(deltaX, deltaY, 1000.0);
+ WorldCoordinate wc = new WorldCoordinate(initialLatitude, initialLongitude, 0.0);
+
+ // Test SPHERICAL
+ tolerance = 0.0015 * distance / 111325;
+ System.out.println("\nSpherical tolerance: " + tolerance);
+ WorldCoordinate result = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ assertEquals(1000.0, result.getAltitude(), 0.0);
+
+
+ // Test WGS84
+ /*
+ * TODO: Since the example values are computed using a spherical earth approximation,
+ * the WGS84 method will have significantly larger errors. The tolerance should be
+ * increased correspondingly.
+ */
+ //tolerance = ...
+ System.out.println("\nWGS84 tolerance: " + tolerance);
+ result = GeodeticComputationStrategy.WGS84.addCoordinate(result, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ // FIXME: Re-enable these when they function
+ // assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ // assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ // assertEquals(1000.0, result.getAltitude(), 0.0);
+
+
+ // Test FLAT
+ if (testFlat) {
+ tolerance = 0.02 * distance / 111325;
+ System.out.println("\nFlat tolerance: " + tolerance);
+ result = GeodeticComputationStrategy.FLAT.addCoordinate(wc, coord);
+
+ System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
+ System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
+ assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
+ assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
+ assertEquals(1000.0, result.getAltitude(), 0.0);
+
+ }
+
+ }
+
+
+