create changelog entry
[debian/openrocket] / core / test / net / sf / openrocket / util / GeodeticComputationStrategyTest.java
1 package net.sf.openrocket.util;
2
3 import static org.junit.Assert.*;
4
5 import org.junit.Test;
6
7 public class GeodeticComputationStrategyTest {
8         
9         @Test
10         public void testSpericalAddCoordinate() {
11                 
12                 double arcmin = (1.0 / 60.0);
13                 double arcsec = (1.0 / (60.0 * 60.0));
14                 
15                 double lat1 = 50.0 + 3 * arcmin + 59 * arcsec;
16                 double lon1 = -1.0 * (5 + 42 * arcmin + 53 * arcsec); //W 
17                 
18                 double lat2 = 58 + 38 * arcmin + 38 * arcsec;
19                 double lon2 = -1.0 * (3 + 4 * arcmin + 12 * arcsec);
20                 
21                 double range = 968.9 * 1000.0;
22                 double bearing = (9.0 + 7 * arcmin + 11 * arcsec) * (Math.PI / 180.0);
23                 
24                 Coordinate coord = new Coordinate(range * Math.sin(bearing), range * Math.cos(bearing), 1000.0);
25                 WorldCoordinate wc = new WorldCoordinate(lat1, lon1, 0.0);
26                 wc = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
27                 
28                 System.out.println(wc.getLatitudeDeg());
29                 System.out.println(lat2);
30                 
31                 System.out.println(wc.getLongitudeDeg());
32                 System.out.println(lon2);
33                 
34                 assertEquals(lat2, wc.getLatitudeDeg(), 0.001);
35                 assertEquals(lon2, wc.getLongitudeDeg(), 0.001);
36                 assertEquals(1000.0, wc.getAltitude(), 0.0);
37         }
38         
39         
40         @Test
41         public void testAddCoordinates() {
42                 
43                 double min = 1 / 60.0;
44                 double sec = 1 / 3600.0;
45                 
46
47                 // Test zero movement
48                 System.out.println("\nTesting zero movement");
49                 testAddCoordinate(50.0, 20.0, 0, 123, 50.0, 20.0, false);
50                 
51
52                 /*
53                  * These example values have been computed using the calculator at
54                  * http://www.movable-type.co.uk/scripts/latlong.html
55                  */
56
57                 // Long distance NE over England, crosses Greenwich meridian
58                 // 50 03N  005 42W  to  58 38N  003 04E  is  1109km at 027 16'07"
59                 System.out.println("\nTesting 1109km NE over England");
60                 testAddCoordinate(50 + 3 * min, -5 - 42 * min, 1109000, 27 + 16 * min + 7 * sec, 58 + 38 * min, 3 + 4 * min, false);
61                 
62                 // SW over Brazil
63                 // -10N  -60E  to  -11N  -61E  is  155.9km at 224 25'34"
64                 System.out.println("\nTesting 155km SW over Brazil");
65                 testAddCoordinate(-10, -60, 155900, 224 + 25 * min + 34 * sec, -11, -61, true);
66                 
67                 // NW over the 180 meridian
68                 // 63N  -179E  to  63 01N  179E  is  100.9km at 271 56'34"
69                 System.out.println("\nTesting 100km NW over 180 meridian");
70                 testAddCoordinate(63, -179, 100900, 271 + 56 * min + 34 * sec, 63 + 1 * min, 179, true);
71                 
72                 // NE near the north pole
73                 // 89 50N  0E  to 89 45N  175E  is 46.29 km at 003 00'01"
74                 System.out.println("\nTesting 46km NE near north pole");
75                 testAddCoordinate(89 + 50 * min, 0, 46290, 3 + 0 * min + 1 * sec, 89 + 45 * min, 175, false);
76                 
77                 // S directly over south pole
78                 // -89 50N  12E  to  -89 45N  192E  is  46.33km at 180 00'00"
79                 System.out.println("\nTesting 46km directly over south pole ");
80                 testAddCoordinate(-89 - 50 * min, 12, 46330, 180, -89 - 45 * min, -168, false);
81                 
82         }
83         
84         private void testAddCoordinate(double initialLatitude, double initialLongitude, double distance, double bearing,
85                                 double finalLatitude, double finalLongitude, boolean testFlat) {
86                 
87                 double tolerance;
88                 
89                 bearing = Math.toRadians(bearing);
90                 
91                 // positive X is EAST, positive Y is NORTH
92                 double deltaX = distance * Math.sin(bearing);
93                 double deltaY = distance * Math.cos(bearing);
94                 
95                 Coordinate coord = new Coordinate(deltaX, deltaY, 1000.0);
96                 WorldCoordinate wc = new WorldCoordinate(initialLatitude, initialLongitude, 0.0);
97                 
98                 // Test SPHERICAL
99                 tolerance = 0.0015 * distance / 111325;
100                 System.out.println("\nSpherical tolerance: " + tolerance);
101                 WorldCoordinate result = GeodeticComputationStrategy.SPHERICAL.addCoordinate(wc, coord);
102                 
103                 System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
104                 System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
105                 assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
106                 assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
107                 assertEquals(1000.0, result.getAltitude(), 0.0);
108                 
109
110                 // Test WGS84
111                 /*
112                  * Note: Since the example values are computed using a spherical earth approximation,
113                  * the WGS84 method will have significantly larger errors.  A tolerance of 1% accommodates
114                  * all cases except the NE flight near the north pole, where the ellipsoidal effect is
115                  * the greatest.
116                  */
117                 tolerance = 0.04 * distance / 111325;
118                 System.out.println("\nWGS84 tolerance: " + tolerance);
119                 result = GeodeticComputationStrategy.WGS84.addCoordinate(wc, coord);
120                 
121                 System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
122                 System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
123                 assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
124                 assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
125                 assertEquals(1000.0, result.getAltitude(), 0.0);
126                 
127
128                 // Test FLAT
129                 if (testFlat) {
130                         tolerance = 0.02 * distance / 111325;
131                         System.out.println("\nFlat tolerance: " + tolerance);
132                         result = GeodeticComputationStrategy.FLAT.addCoordinate(wc, coord);
133                         
134                         System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
135                         System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
136                         assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
137                         assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
138                         assertEquals(1000.0, result.getAltitude(), 0.0);
139                         
140                 }
141                 
142         }
143         
144         
145
146         @Test
147         public void testSpericalGetCoriolisAcceleration() {
148                 
149                 // For positive latitude and rotational velocity, a movement due east results in an acceleration due south
150                 Coordinate velocity = new Coordinate(-1000, 0, 0);
151                 WorldCoordinate wc = new WorldCoordinate(45, 0, 0);
152                 double north_accel = GeodeticComputationStrategy.SPHERICAL.getCoriolisAcceleration(wc, velocity).y;
153                 System.out.println("North accel " + north_accel);
154                 assertTrue(north_accel < 0.0);
155                 
156         }
157         
158 }