1 // Copyright 2008, Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 // This file contains the unit tests for the mathematical functions.
27
28 #include "kml/base/math_util.h"
29 #include "boost/scoped_ptr.hpp"
30 #include "gtest/gtest.h"
31
32 namespace kmlbase {
33
TEST(BaseMathTest,TestAzimuthBetweenPoints)34 TEST(BaseMathTest, TestAzimuthBetweenPoints) {
35 // Sanity checks.
36 ASSERT_DOUBLE_EQ(0.0, AzimuthBetweenPoints(0,0,1,0));
37 ASSERT_DOUBLE_EQ(90.0, AzimuthBetweenPoints(0,0,0,1));
38 ASSERT_DOUBLE_EQ(180.0, AzimuthBetweenPoints(0,0,-1,0));
39 ASSERT_DOUBLE_EQ(-90.0, AzimuthBetweenPoints(0,0,0,-1));
40 ASSERT_NEAR(-180.0, AzimuthBetweenPoints(0,0,-1,-0.0000001), 0.0001);
41 // The example from the Aviation Formulary.
42 const double kLAX_lat = 33.944066;
43 const double kLAX_lng = -118.408294;
44 const double kJFK_lat = 40.642480;
45 const double kJFK_lng = -73.788071;
46 // The known azimuth from LAX to JFK.
47 const double kAzimuth = 65.8687;
48 double az1 = AzimuthBetweenPoints(kLAX_lat, kLAX_lng, kJFK_lat, kJFK_lng);
49 ASSERT_NEAR(kAzimuth, az1, 0.0001);
50 // The return flight.
51 const double kAzimuthReturn = -86.1617;
52 double az2 = AzimuthBetweenPoints(kJFK_lat, kJFK_lng, kLAX_lat, kLAX_lng);
53 ASSERT_NEAR(kAzimuthReturn, az2, 0.0001);
54 }
55
TEST(BaseMathTest,TestDistanceBetweenPoints)56 TEST(BaseMathTest, TestDistanceBetweenPoints) {
57 const double kLAX_lat = 33.944066;
58 const double kLAX_lng = -118.408294;
59 const double kJFK_lat = 40.642480;
60 const double kJFK_lng = -73.788071;
61 // The known great circle distance in meters between LAX and JFK.
62 const double kDistance = 3970683.0;
63 double d = DistanceBetweenPoints(kLAX_lat, kLAX_lng, kJFK_lat, kJFK_lng);
64 ASSERT_NEAR(kDistance, d, 0.1);
65 }
66
TEST(BaseMathTest,TestDistanceBetweenPoints3d)67 TEST(BaseMathTest, TestDistanceBetweenPoints3d) {
68 ASSERT_DOUBLE_EQ(0.0, DistanceBetweenPoints3d(0,0,0,0,0,0));
69 ASSERT_DOUBLE_EQ(1.0, DistanceBetweenPoints3d(0,0,0,0,0,1));
70 ASSERT_DOUBLE_EQ(1000.0, DistanceBetweenPoints3d(0,0,0,0,0,1000));
71 // Assert the 2d example works here.
72 double expected = 3970683.0;
73 ASSERT_NEAR(expected,
74 DistanceBetweenPoints3d(33.944066, -118.408294, 0,
75 40.642480, -73.788071, 0), 0.1);
76 // Put JFK 10,000 km in the sky:
77 expected = 4094670.171;
78 ASSERT_NEAR(expected,
79 DistanceBetweenPoints3d(33.944066, -118.408294, 0,
80 40.642480, -73.788071, 1000000.0), 0.1);
81 }
82
TEST(BaseMathTest,TestElevationBetweenPoints)83 TEST(BaseMathTest, TestElevationBetweenPoints) {
84 double lat_from = 0;
85 double lng_from = 0;
86 double alt_from = 0;
87 double lat_to = 0.0000000000001;
88 double lng_to = 0.0000000000001;
89 // This is basically a flat line.
90 double alt_to = 0.0;
91 ASSERT_NEAR(
92 0.0, ElevationBetweenPoints(lat_from, lng_from, alt_from,
93 lat_to, lng_to, alt_to),
94 0.001);
95 // Near-vertical.
96 alt_to = 10000;
97 ASSERT_NEAR(
98 90.0, ElevationBetweenPoints(lat_from, lng_from, alt_from,
99 lat_to, lng_to, alt_to),
100 0.001);
101 lat_to = 0.145;
102 alt_to = 609.6;
103 ASSERT_NEAR(
104 2.1667, ElevationBetweenPoints(lat_from, lng_from, alt_from,
105 lat_to, lng_to, alt_to),
106 0.001);
107 lat_from = 37.0;
108 lng_from = -121.98;
109 alt_from = 600;
110 lat_to = 37.0;
111 lng_to = -122.0;
112 alt_to = 200;
113 ASSERT_NEAR(
114 -12.7004, ElevationBetweenPoints(lat_from, lng_from, alt_from,
115 lat_to, lng_to, alt_to),
116 0.001);
117 }
118
TEST(BaseMathTest,TestLatLngOnRadialFromPoint)119 TEST(BaseMathTest, TestLatLngOnRadialFromPoint) {
120 // See http://williams.best.vwh.net/avform.htm#Example
121 // Coordinates of LAX.
122 const double kLAX_lat = 33.944066;
123 const double kLAX_lng = -118.408294;
124 // A distance and radial.
125 const double kDistance = 185200.0;
126 const double kRadial = 66.0;
127 // The known-accurate coordinates of the point along that radial from LAX.
128 const double kRadial_lat = 34.608154;
129 const double kRadial_lng = -116.558327;
130
131 Vec3 v = LatLngOnRadialFromPoint(kLAX_lat, kLAX_lng, kDistance, kRadial);
132 ASSERT_NEAR(kRadial_lat, v.get_latitude(), 0.000001);
133 ASSERT_NEAR(kRadial_lng, v.get_longitude(), 0.000001);
134 }
135
136
137 // Tests the GroundDistanceFromRangeAndElevation() function.
TEST(BaseMathTest,TestGroundDistanceFromRangeAndElevation)138 TEST(BaseMathTest, TestGroundDistanceFromRangeAndElevation) {
139 ASSERT_NEAR(100.0, GroundDistanceFromRangeAndElevation(100.0, 0.0),
140 0.000001);
141 ASSERT_NEAR(99.939083, GroundDistanceFromRangeAndElevation(100.0, 2.0),
142 0.000001);
143 ASSERT_NEAR(17.364818, GroundDistanceFromRangeAndElevation(100.0, 80.0),
144 0.000001);
145 ASSERT_NEAR(0.0, GroundDistanceFromRangeAndElevation(100.0, 90.0),
146 0.000001);
147 ASSERT_NEAR(17.364818, GroundDistanceFromRangeAndElevation(100.0, 100.0),
148 0.000001);
149 }
150
151 // Tests the HeightFromRangeAndElevation() function.
TEST(BaseMathTest,TestHeightFromRangeAndElevation)152 TEST(BaseMathTest, TestHeightFromRangeAndElevation) {
153 ASSERT_NEAR(0.0, HeightFromRangeAndElevation(100.0, 0.0),
154 0.000001);
155 ASSERT_NEAR(3.489950, HeightFromRangeAndElevation(100.0, 2.0),
156 0.000001);
157 ASSERT_NEAR(98.480775, HeightFromRangeAndElevation(100.0, 80.0),
158 0.000001);
159 ASSERT_NEAR(100.0, HeightFromRangeAndElevation(100.0, 90.0),
160 0.000001);
161 ASSERT_NEAR(98.480775, HeightFromRangeAndElevation(100.0, 100.0),
162 0.000001);
163 }
164
165 // Tese test the conversion functions.
TEST(BaseMathTest,TestDegToRad)166 TEST(BaseMathTest, TestDegToRad) {
167 ASSERT_DOUBLE_EQ(0.0, DegToRad(0.0));
168 ASSERT_DOUBLE_EQ(M_PI, DegToRad(180.0));
169 ASSERT_DOUBLE_EQ(M_PI / 2, DegToRad(90.0));
170 ASSERT_DOUBLE_EQ(M_PI / -2, DegToRad(-90.0));
171 }
172
TEST(BaseMathTest,TestRadToDeg)173 TEST(BaseMathTest, TestRadToDeg) {
174 ASSERT_DOUBLE_EQ(0.0, RadToDeg(0));
175 ASSERT_DOUBLE_EQ(360.0, RadToDeg(2 * M_PI));
176 ASSERT_DOUBLE_EQ(90.0, RadToDeg(M_PI / 2));
177 ASSERT_DOUBLE_EQ(-90.0, RadToDeg(M_PI / -2));
178 }
179
TEST(BaseMathTest,TestMetersToRadians)180 TEST(BaseMathTest, TestMetersToRadians) {
181 ASSERT_DOUBLE_EQ(0, MetersToRadians(0));
182 ASSERT_DOUBLE_EQ(1, MetersToRadians(6366710));
183 }
184
TEST(BaseMathTest,TestRadiansToMeters)185 TEST(BaseMathTest, TestRadiansToMeters) {
186 ASSERT_DOUBLE_EQ(0, RadiansToMeters(0));
187 ASSERT_DOUBLE_EQ(6366710, RadiansToMeters(1));
188 }
189
190 } // end namespace kmlbase
191