vincenty 1.0.4 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/History.txt +62 -52
- data/README.md +3 -3
- data/Rakefile +17 -10
- data/lib/angle.rb +215 -203
- data/lib/coordinate.rb +24 -23
- data/lib/core_extensions.rb +67 -59
- data/lib/latitude.rb +30 -29
- data/lib/longitude.rb +22 -23
- data/lib/track_and_distance.rb +36 -32
- data/lib/vincenty.rb +153 -143
- data/test/ts_all.rb +8 -8
- data/test/ts_angle.rb +55 -54
- data/test/ts_coordinate.rb +10 -9
- data/test/ts_latitude.rb +20 -17
- data/test/ts_longitude.rb +14 -11
- data/test/ts_track_and_distance.rb +12 -9
- data/test/ts_vincenty.rb +80 -71
- metadata +33 -39
- data/.gemtest +0 -0
data/lib/vincenty.rb
CHANGED
@@ -1,191 +1,201 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#Vincenty's algorithms for finding the bearing and distance between two coordinates and
|
9
|
-
#for finding the latitude and longitude, given a start coordinate, distance and bearing.
|
1
|
+
require_relative 'core_extensions.rb'
|
2
|
+
require_relative 'angle.rb'
|
3
|
+
require_relative 'latitude.rb'
|
4
|
+
require_relative 'longitude.rb'
|
5
|
+
require_relative 'track_and_distance.rb'
|
6
|
+
require_relative 'coordinate.rb'
|
7
|
+
|
8
|
+
# Vincenty's algorithms for finding the bearing and distance between two coordinates and
|
9
|
+
# for finding the latitude and longitude, given a start coordinate, distance and bearing.
|
10
10
|
#
|
11
11
|
# Coded from formulae from Wikipedia http://en.wikipedia.org/wiki/Vincenty%27s_formulae
|
12
12
|
# Modified to incorporate corrections to formulae as found in script on http://www.movable-type.co.uk/scripts/LatLongVincenty.html
|
13
13
|
# Added my Modification of the distanceAndAngle formulae to correct the compass bearing.
|
14
14
|
class Vincenty < Coordinate
|
15
|
-
VERSION = '1.0.
|
16
|
-
|
15
|
+
VERSION = '1.0.9'
|
16
|
+
|
17
|
+
# @return [String] constant VERSION
|
17
18
|
def version
|
18
19
|
VERSION
|
19
20
|
end
|
20
|
-
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
|
22
|
+
WGS84_ER = 6378137 # Equatorial Radius of earth
|
23
|
+
WGS84_IF = 298.257223563 # Inverse Flattening
|
24
|
+
GRS80_ER = 6378137 # Equatorial Radius of earth
|
25
|
+
GRS80_IF = 298.25722210882711 # Inverse Flattening
|
26
|
+
|
27
|
+
# Great Circle formulae http://en.wikipedia.org/wiki/Great-circle_distance
|
28
|
+
# Reference calculation for testing, assumes the earth is a sphere, which it isn't.
|
29
|
+
# This gives us an approximation to verify Vincenty algorithm.
|
30
|
+
# @param [Coordinate] p2 is target coordinate that we want the bearing to.
|
31
|
+
# @return [TrackAndDistance] with the compass bearing and distance in meters to P2
|
32
|
+
def sphericalDistanceAndAngle( p2, equatorial_radius = WGS84_ER, inverse_flattening = WGS84_IF )
|
33
|
+
if self.latitude == p2.latitude && self.longitude == p2.longitude
|
34
|
+
return TrackAndDistance.new(0, 0, true) # No calculations necessary
|
35
|
+
end
|
36
|
+
|
37
|
+
a = equatorial_radius # equatorial radius in meters (+/-2 m)
|
38
|
+
f = inverse_flattening
|
39
|
+
b = a - a / f # WGS84 = 6356752.314245179 polar radius in meters
|
40
|
+
r = (a + b) / 2 # average diametre as a rough estimate for our tests.
|
41
|
+
|
42
|
+
sin_lat1 = Math.sin(@latitude.to_rad)
|
43
|
+
sin_lat2 = Math.sin(p2.latitude.to_rad)
|
44
|
+
cos_lat1 = Math.cos(@latitude.to_rad)
|
34
45
|
atan1_2 = Math.atan(1) * 2
|
35
|
-
t1 = cos_lat1 * Math.cos(p2.latitude.
|
36
|
-
angular_distance = Math.atan(-t1/Math.sqrt(-t1 * t1 +1)) + atan1_2 #central angle in radians so we can calculate the arc length.
|
46
|
+
t1 = cos_lat1 * Math.cos(p2.latitude.to_rad) * Math.cos(@longitude.to_rad - p2.longitude.to_rad) + sin_lat1 * sin_lat2
|
47
|
+
angular_distance = Math.atan(-t1 / Math.sqrt(-t1 * t1 + 1)) + atan1_2 # central angle in radians so we can calculate the arc length.
|
37
48
|
|
38
49
|
t2 = (sin_lat2 - sin_lat1 * Math.cos(angular_distance)) / (cos_lat1 * Math.sin(angular_distance))
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
bearing = if Math.sin(p2.longitude.to_rad - @longitude.to_rad) < 0
|
51
|
+
2 * Math::PI - (Math.atan(-t2 / Math.sqrt(-t2 * t2 + 1)) + atan1_2) # Compass Bearing in radians (clockwise)
|
52
|
+
else
|
53
|
+
Math.atan(-t2 / Math.sqrt(-t2 * t2 + 1)) + atan1_2 # Compass Bearing in radians (clockwise)
|
54
|
+
end
|
44
55
|
|
45
|
-
#Note that the bearing is a compass angle. That is angles are positive clockwise.
|
56
|
+
# Note that the bearing is a compass angle. That is angles are positive clockwise.
|
46
57
|
return TrackAndDistance.new(bearing, angular_distance * r, true)
|
47
58
|
end
|
48
59
|
|
49
|
-
#Vincenty's algorithm for finding bearing and distance between to coordinates.
|
50
|
-
#Assumes earth is a WGS-84 Ellipsod.
|
51
|
-
#
|
52
|
-
#
|
60
|
+
# Vincenty's algorithm for finding bearing and distance between to coordinates.
|
61
|
+
# Assumes earth is a WGS-84 Ellipsod.
|
62
|
+
# @param [Coordinate] p2 is target coordinate that we want the bearing to.
|
63
|
+
# @return [TrackAndDistance] with the compass bearing and distance in meters to P2
|
53
64
|
def distanceAndAngle( p2 )
|
65
|
+
if self.latitude == p2.latitude && self.longitude == p2.longitude
|
66
|
+
return TrackAndDistance.new(0, 0, true) # No calculations necessary. Solv NAN issue
|
67
|
+
end
|
68
|
+
|
54
69
|
# a, b = major & minor semiaxes of the ellipsoid
|
55
|
-
a = 6378137 #equatorial radius in meters (+/-2 m)
|
56
|
-
b = 6356752.31424518 #polar radius in meters
|
57
|
-
f = (a-b)/a # flattening
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
70
|
+
a = 6378137 # equatorial radius in meters (+/-2 m)
|
71
|
+
b = 6356752.31424518 # polar radius in meters
|
72
|
+
f = (a - b) / a # flattening
|
73
|
+
|
74
|
+
lat1 = @latitude.to_rad
|
75
|
+
lon1 = @longitude.to_rad
|
76
|
+
lat2 = p2.latitude.to_rad
|
77
|
+
lon2 = p2.longitude.to_rad
|
78
|
+
lat1 = lat1.sign * (Math::PI / 2 - 1e-10) if (Math::PI / 2 - lat1.abs).abs < 1.0e-10
|
79
|
+
lat2 = lat2.sign * (Math::PI / 2 - 1e-10) if (Math::PI / 2 - lat2.abs).abs < 1.0e-10
|
65
80
|
|
66
81
|
# lat1, lat2 = geodetic latitude
|
67
|
-
|
68
|
-
l = (lon2 - lon1).abs #difference in longitude
|
69
|
-
l = 2*Math::PI - l if l > Math::PI
|
70
|
-
u1 = Math.atan( ( 1 - f) * Math.tan( lat1 ) ) #U is 'reduced latitude'
|
71
|
-
u2 = Math.atan( ( 1 - f) * Math.tan( lat2 ) )
|
72
|
-
sin_u1 = Math.sin(u1)
|
73
|
-
cos_u1 = Math.cos(u1)
|
74
|
-
sin_u2 = Math.sin(u2)
|
75
|
-
cos_u2 = Math.cos(u2)
|
76
|
-
|
77
|
-
lambda_v = l
|
78
|
-
lambda_dash = Math::PI * 2
|
79
|
-
while( (lambda_v - lambda_dash).abs > 1.0e-12 ) #i.e. 0.06 mm error
|
80
|
-
sin_lambda_v = Math.sin(lambda_v)
|
81
|
-
cos_lambda_v = Math.cos(lambda_v)
|
82
|
-
sin_sigma = Math.sqrt( ( cos_u2 * sin_lambda_v ) ** 2 + ( cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v ) ** 2 )
|
83
|
-
cos_sigma = sin_u1 * sin_u2 + cos_u1 * cos_u2 * cos_lambda_v
|
84
|
-
sigma = Math.atan2(sin_sigma, cos_sigma)
|
85
|
-
sin_alpha= cos_u1 * cos_u2 * sin_lambda_v / sin_sigma
|
86
|
-
cos_2_alpha = 1 - sin_alpha * sin_alpha #trig identity
|
87
|
-
cos_2_sigma_m = cos_sigma - 2 * sin_u1 * sin_u2/cos_2_alpha
|
88
|
-
c = f / 16 * cos_2_alpha * (4 + f*(4-3*cos_2_alpha))
|
89
|
-
lambda_dash = lambda_v
|
90
|
-
lambda_v = l + (1-c) * f * sin_alpha * (sigma + c * sin_sigma * (cos_2_sigma_m + c * cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m) ) ) # use cos_2_sigma_m=0 when over equatorial lines
|
91
|
-
if lambda_v > Math::PI
|
92
|
-
lambda_v = Math::PI
|
93
|
-
break
|
94
|
-
end
|
95
|
-
end
|
96
82
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
83
|
+
l = (lon2 - lon1).abs # difference in longitude
|
84
|
+
l = 2 * Math::PI - l if l > Math::PI
|
85
|
+
u1 = Math.atan( ( 1 - f) * Math.tan( lat1 ) ) # U is 'reduced latitude'
|
86
|
+
u2 = Math.atan( ( 1 - f) * Math.tan( lat2 ) )
|
87
|
+
sin_u1 = Math.sin(u1)
|
88
|
+
cos_u1 = Math.cos(u1)
|
89
|
+
sin_u2 = Math.sin(u2)
|
90
|
+
cos_u2 = Math.cos(u2)
|
91
|
+
|
92
|
+
lambda_v = l
|
93
|
+
lambda_dash = Math::PI * 2
|
94
|
+
while (lambda_v - lambda_dash).abs > 1.0e-12 # i.e. 0.06 mm error
|
102
95
|
sin_lambda_v = Math.sin(lambda_v)
|
103
96
|
cos_lambda_v = Math.cos(lambda_v)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
97
|
+
sin_sigma = Math.sqrt( ( cos_u2 * sin_lambda_v )**2 + ( cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v )**2 )
|
98
|
+
cos_sigma = sin_u1 * sin_u2 + cos_u1 * cos_u2 * cos_lambda_v
|
99
|
+
sigma = Math.atan2(sin_sigma, cos_sigma)
|
100
|
+
sin_alpha = cos_u1 * cos_u2 * sin_lambda_v / sin_sigma
|
101
|
+
cos_2_alpha = 1 - sin_alpha * sin_alpha # trig identity
|
102
|
+
cos_2_sigma_m = cos_sigma - 2 * sin_u1 * sin_u2 / cos_2_alpha
|
103
|
+
c = f / 16 * cos_2_alpha * (4 + f * (4 - 3 * cos_2_alpha))
|
104
|
+
lambda_dash = lambda_v
|
105
|
+
lambda_v = l + (1 - c) * f * sin_alpha * (sigma + c * sin_sigma * (cos_2_sigma_m + c * cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m) ) ) # use cos_2_sigma_m=0 when over equatorial lines
|
106
|
+
if lambda_v > Math::PI
|
107
|
+
lambda_v = Math::PI
|
108
|
+
break
|
113
109
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
110
|
+
end
|
111
|
+
|
112
|
+
u_2 = cos_2_alpha * (a * a - b * b) / (b * b)
|
113
|
+
a1 = 1 + u_2 / 16384 * (4096 + u_2 * (-768 + u_2 * (320 - 175 * u_2)))
|
114
|
+
b1 = u_2 / 1024 * (256 + u_2 * (-128 + u_2 * (74 - 47 * u_2)))
|
115
|
+
delta_sigma = b1 * sin_sigma * (cos_2_sigma_m + b1 / 4 * (cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m) - b1 / 6 * cos_2_sigma_m * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * cos_2_sigma_m * cos_2_sigma_m)))
|
116
|
+
s = b * a1 * (sigma - delta_sigma)
|
117
|
+
sin_lambda_v = Math.sin(lambda_v)
|
118
|
+
cos_lambda_v = Math.cos(lambda_v)
|
119
|
+
|
120
|
+
# This test isn't in original formulae, and fixes the problem of all angles returned being between 0 - PI (0-180)
|
121
|
+
# Also converts the result to compass bearing, rather than the mathmatical anticlockwise angles.
|
122
|
+
alpha_1 = if Math.sin(p2.longitude.to_rad - @longitude.to_rad) < 0
|
123
|
+
Math::PI * 2 - Math.atan2( cos_u2 * sin_lambda_v, cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v)
|
124
|
+
# alpha_2 = Math::PI*2-Math.atan2(cos_u1 * sin_lambda_v, -sin_u1 * cos_u2 + cos_u1 * sin_u2 * cos_lambda_v)
|
125
|
+
else
|
126
|
+
Math.atan2( cos_u2 * sin_lambda_v, cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v)
|
127
|
+
# alpha_2 = Math.atan2(cos_u1 * sin_lambda_v, -sin_u1 * cos_u2 + cos_u1 * sin_u2 * cos_lambda_v)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Note that the bearing is a compass (i.e. clockwise) angle.
|
131
|
+
return TrackAndDistance.new(alpha_1, s, true) # What to do with alpha_2?
|
117
132
|
end
|
118
133
|
|
119
|
-
#spherical earth estimate of calculation for finding target coordinate from start coordinate, bearing and distance
|
120
|
-
#Used to run checks on the Vincenty algorithm
|
121
|
-
#
|
122
|
-
#
|
134
|
+
# spherical earth estimate of calculation for finding target coordinate from start coordinate, bearing and distance
|
135
|
+
# Used to run checks on the Vincenty algorithm
|
136
|
+
# @param [TrackAndDistance] track_and_distance specifying bearing and distance.
|
137
|
+
# @return [Vincenty] with the destination coordinates.
|
123
138
|
def sphereDestination( track_and_distance )
|
124
|
-
a = 6378137 #equatorial radius in meters (+/-2 m)
|
125
|
-
b = 6356752.31424518 #polar radius in meters
|
126
|
-
r = (a+b)/2 #average diametre as a rough estimate for our tests.
|
127
|
-
|
139
|
+
a = 6378137 # equatorial radius in meters (+/-2 m)
|
140
|
+
b = 6356752.31424518 # polar radius in meters
|
141
|
+
r = (a + b) / 2 # average diametre as a rough estimate for our tests.
|
142
|
+
|
128
143
|
d = track_and_distance.distance.abs
|
129
|
-
sin_dor = Math.sin(d/r)
|
130
|
-
cos_dor = Math.cos(d/r)
|
131
|
-
sin_lat1 = Math.sin(@latitude.
|
132
|
-
cos_lat1 = Math.cos(@latitude.
|
133
|
-
lat2 = Math.asin( sin_lat1 * cos_dor + cos_lat1 * sin_dor * Math.cos(track_and_distance.bearing.
|
134
|
-
lon2 = @longitude.
|
135
|
-
|
136
|
-
Vincenty.new(lat2, lon2, 0, true)
|
144
|
+
sin_dor = Math.sin(d / r)
|
145
|
+
cos_dor = Math.cos(d / r)
|
146
|
+
sin_lat1 = Math.sin(@latitude.to_rad)
|
147
|
+
cos_lat1 = Math.cos(@latitude.to_rad)
|
148
|
+
lat2 = Math.asin( sin_lat1 * cos_dor + cos_lat1 * sin_dor * Math.cos(track_and_distance.bearing.to_rad) )
|
149
|
+
lon2 = @longitude.to_rad + Math.atan2(Math.sin(track_and_distance.bearing.to_rad) * sin_dor * cos_lat1, cos_dor - sin_lat1 * Math.sin(lat2))
|
150
|
+
|
151
|
+
Vincenty.new(lat2, lon2, 0, true)
|
137
152
|
end
|
138
153
|
|
139
154
|
#
|
140
155
|
# Calculate destination point given start point lat/long, bearing and distance.
|
141
|
-
#Assumes earth is a WGS-84 Ellipsod.
|
142
|
-
#
|
143
|
-
#
|
144
|
-
def destination( track_and_distance )
|
156
|
+
# Assumes earth is a WGS-84 Ellipsod.
|
157
|
+
# @param [TrackAndDistance] specifying bearing and distance.
|
158
|
+
# @return [Vincenty] with the destination coordinates.
|
159
|
+
def destination( track_and_distance )
|
145
160
|
# a, b = major & minor semiaxes of the ellipsoid
|
146
|
-
a = 6378137 #equatorial radius in meters (+/-2 m)
|
147
|
-
b = 6356752.31424518 #polar radius in meters
|
148
|
-
f = (a-b)/a # flattening
|
149
|
-
|
150
|
-
s = track_and_distance.distance.abs
|
151
|
-
alpha1 = track_and_distance.bearing.
|
161
|
+
a = 6378137 # equatorial radius in meters (+/-2 m)
|
162
|
+
b = 6356752.31424518 # polar radius in meters
|
163
|
+
f = (a - b) / a # flattening
|
164
|
+
|
165
|
+
s = track_and_distance.distance.abs
|
166
|
+
alpha1 = track_and_distance.bearing.to_rad
|
152
167
|
sin_alpha1 = Math.sin(alpha1)
|
153
168
|
cos_alpha1 = Math.cos(alpha1)
|
154
|
-
|
155
|
-
tanU1 = (1-f)
|
156
|
-
cosU1 = 1 / Math.sqrt((1
|
169
|
+
|
170
|
+
tanU1 = (1 - f) * Math.tan(@latitude.to_rad)
|
171
|
+
cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1))
|
157
172
|
sinU1 = tanU1 * cosU1
|
158
173
|
sigma1 = Math.atan2(tanU1, cos_alpha1)
|
159
|
-
sin_alpha = cosU1
|
160
|
-
cos_2_alpha = 1 - sin_alpha * sin_alpha #Trig identity
|
161
|
-
u_2 = cos_2_alpha
|
162
|
-
a1 = 1
|
163
|
-
b1 = u_2/1024
|
164
|
-
|
174
|
+
sin_alpha = cosU1 * sin_alpha1
|
175
|
+
cos_2_alpha = 1 - sin_alpha * sin_alpha # Trig identity
|
176
|
+
u_2 = cos_2_alpha * (a * a - b * b) / (b * b)
|
177
|
+
a1 = 1 + u_2 / 16384 * (4096 + u_2 * (-768 + u_2 * (320 - 175 * u_2)))
|
178
|
+
b1 = u_2 / 1024 * (256 + u_2 * (-128 + u_2 * (74 - 47 * u_2)))
|
179
|
+
|
165
180
|
sigma = s / (b * a1)
|
166
181
|
sigma_dash = 2 * Math::PI
|
167
|
-
while (
|
168
|
-
cos_2_sigma_m = Math.cos(2 * sigma1
|
182
|
+
while (sigma - sigma_dash).abs > 1.0e-12 # i.e 0.06mm
|
183
|
+
cos_2_sigma_m = Math.cos(2 * sigma1 + sigma)
|
169
184
|
sin_sigma = Math.sin(sigma)
|
170
185
|
cos_sigma = Math.cos(sigma)
|
171
|
-
delta_sigma = b1 * sin_sigma * (cos_2_sigma_m + b1/4 * (cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m) - b1/6 * cos_2_sigma_m * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * cos_2_sigma_m * cos_2_sigma_m)))
|
186
|
+
delta_sigma = b1 * sin_sigma * (cos_2_sigma_m + b1 / 4 * (cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m) - b1 / 6 * cos_2_sigma_m * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * cos_2_sigma_m * cos_2_sigma_m)))
|
172
187
|
sigma_dash = sigma
|
173
|
-
sigma = s / (b * a1)
|
188
|
+
sigma = s / (b * a1) + delta_sigma
|
174
189
|
end
|
175
190
|
|
176
191
|
tmp = sinU1 * sin_sigma - cosU1 * cos_sigma * cos_alpha1
|
177
|
-
lat2 = Math.atan2(sinU1 * cos_sigma
|
192
|
+
lat2 = Math.atan2(sinU1 * cos_sigma + cosU1 * sin_sigma * cos_alpha1, (1 - f) * Math.sqrt(sin_alpha * sin_alpha + tmp * tmp))
|
178
193
|
lambda_v = Math.atan2(sin_sigma * sin_alpha1, cosU1 * cos_sigma - sinU1 * sin_sigma * cos_alpha1)
|
179
|
-
c = f/16 * cos_2_alpha * (4 + f * (4-3 * cos_2_alpha))
|
180
|
-
l = lambda_v - (1-c)
|
181
|
-
|
182
|
-
#sigma2 = Math.atan2(sin_alpha, -tmp) # reverse azimuth
|
183
|
-
|
184
|
-
return Vincenty.new(lat2, @longitude + l, 0, true);
|
185
|
-
end
|
194
|
+
c = f / 16 * cos_2_alpha * (4 + f * (4 - 3 * cos_2_alpha))
|
195
|
+
l = lambda_v - (1 - c) * f * sin_alpha * (sigma + c * sin_sigma * (cos_2_sigma_m + c * cos_sigma * (-1 + 2 * cos_2_sigma_m * cos_2_sigma_m))) # difference in longitude
|
186
196
|
|
197
|
+
# sigma2 = Math.atan2(sin_alpha, -tmp) # reverse azimuth
|
187
198
|
|
199
|
+
return Vincenty.new(lat2, @longitude + l, 0, true)
|
200
|
+
end
|
188
201
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
data/test/ts_all.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative 'ts_angle.rb'
|
3
|
+
require_relative 'ts_vincenty.rb'
|
4
|
+
require_relative 'ts_latitude.rb'
|
5
|
+
require_relative 'ts_longitude.rb'
|
6
|
+
require_relative 'ts_coordinate.rb'
|
7
|
+
require_relative 'ts_track_and_distance.rb'
|
7
8
|
|
9
|
+
puts 'Testing from source'
|
8
10
|
puts Vincenty.new.version
|
9
|
-
|
10
|
-
|
data/test/ts_angle.rb
CHANGED
@@ -1,81 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
require 'test/unit'
|
2
|
-
|
3
|
+
require_relative '../lib/vincenty.rb'
|
3
4
|
|
4
|
-
class TestAngle< Test::Unit::TestCase
|
5
|
-
#test Angle creation
|
5
|
+
class TestAngle < Test::Unit::TestCase
|
6
|
+
# test Angle creation
|
6
7
|
def test_angle
|
7
|
-
assert_equal(Angle.new
|
8
|
-
assert_equal(Angle.new("S37 01'7.5\"").
|
9
|
-
assert_equal(Angle.new("37 01'7.5\"S").
|
10
|
-
assert_equal(Angle.new("-37 01'7.5\"").
|
11
|
-
assert_equal(Angle.new("-37 1.125'").
|
12
|
-
assert_equal(Angle.new("-37 01'.125").
|
13
|
-
assert_equal(Angle.new("S37 01'.125").
|
14
|
-
assert_equal(Angle.new("37 01'.125S").
|
15
|
-
assert_equal(Angle.new(
|
16
|
-
assert_equal(Angle.new([-37, 1, 7.5]).
|
17
|
-
assert_equal(Angle.new(-37.01875).
|
18
|
-
assert_equal(Angle.degrees(-37.01875).
|
19
|
-
assert_equal(Angle.degrees(-37.01875).
|
20
|
-
assert_equal(Angle.new(-0.646099072472651, true).
|
21
|
-
assert_equal(Angle.new(-0.646099072472651, true).
|
22
|
-
assert_equal(Angle.radians(-0.646099072472651).
|
8
|
+
assert_equal(Angle.new, 0)
|
9
|
+
assert_equal(Angle.new("S37 01'7.5\"").to_deg, -37.01875) # Leading NSEW
|
10
|
+
assert_equal(Angle.new("37 01'7.5\"S").to_deg, -37.01875) # Trailing NSEW
|
11
|
+
assert_equal(Angle.new("-37 01'7.5\"").to_deg, -37.01875) # Use of - rather than S or W
|
12
|
+
assert_equal(Angle.new("-37 1.125'").to_deg, -37.01875) # Decimal minutes, rather than minutes and seconds.
|
13
|
+
assert_equal(Angle.new("-37 01'.125").to_deg, -37.01875) # Nb. the minute marker ' between the minutes and fraction
|
14
|
+
assert_equal(Angle.new("S37 01'.125").to_deg, -37.01875) # Nb. the minute marker ' between the minutes and fraction
|
15
|
+
assert_equal(Angle.new("37 01'.125S").to_deg, -37.01875) # Nb. the minute marker ' between the minutes and fraction
|
16
|
+
assert_equal(Angle.new('-37.01875 ').to_deg, -37.01875) # decimal degrees, rather than deg, min, sec.
|
17
|
+
assert_equal(Angle.new([ -37, 1, 7.5 ]).to_deg, -37.01875) # an array of deg,min,sec
|
18
|
+
assert_equal(Angle.new(-37.01875).to_deg, -37.01875)
|
19
|
+
assert_equal(Angle.degrees(-37.01875).to_deg, -37.01875)
|
20
|
+
assert_equal(Angle.degrees(-37.01875).to_rad.round(15), -0.646099072472651)
|
21
|
+
assert_equal(Angle.new(-0.646099072472651, true).to_deg.round(5), -37.01875)
|
22
|
+
assert_equal(Angle.new(-0.646099072472651, true).to_rad, -0.646099072472651)
|
23
|
+
assert_equal(Angle.radians(-0.646099072472651).to_deg.round(5), -37.01875)
|
23
24
|
assert_equal(Angle.radians(-0.646099072472651).value, Angle.radians(-0.646099072472651).angle)
|
24
|
-
assert_equal(Angle.decimal_deg(1,2,3,'S'), -(1.0 + 2/60.0 + 3/3600.0))
|
25
|
-
assert_equal(Angle.decimal_deg(1,2,3,'E'), (1.0 + 2/60.0 + 3/3600.0))
|
26
|
-
assert_equal(Angle.decimal_deg(1,2,4,'N'), (1.0 + 2/60.0 + 4/3600.0))
|
27
|
-
assert_equal(Angle.decimal_deg(1,5,4,'W'), -(1.0 + 5/60.0 + 4/3600.0))
|
28
|
-
assert_equal(Angle.decimal_deg_from_ary([1,5,4,'W']), -(1.0 + 5/60.0 + 4/3600.0))
|
29
|
-
assert_equal(Angle.decimal_deg_from_ary(Angle.dms( -(1.0 + 5/60.0 + 1.0/3600.0) ))
|
25
|
+
assert_equal(Angle.decimal_deg(1, 2, 3, 'S'), -(1.0 + 2 / 60.0 + 3 / 3600.0))
|
26
|
+
assert_equal(Angle.decimal_deg(1, 2, 3, 'E'), (1.0 + 2 / 60.0 + 3 / 3600.0))
|
27
|
+
assert_equal(Angle.decimal_deg(1, 2, 4, 'N'), (1.0 + 2 / 60.0 + 4 / 3600.0))
|
28
|
+
assert_equal(Angle.decimal_deg(1, 5, 4, 'W'), -(1.0 + 5 / 60.0 + 4 / 3600.0))
|
29
|
+
assert_equal(Angle.decimal_deg_from_ary([ 1, 5, 4, 'W' ]), -(1.0 + 5 / 60.0 + 4 / 3600.0))
|
30
|
+
assert_equal(Angle.decimal_deg_from_ary(Angle.dms( -(1.0 + 5 / 60.0 + 1.0 / 3600.0) )), -(1.0 + 5 / 60.0 + 1.0 / 3600.0)) # double call, rounding error always produced a failure.
|
30
31
|
end
|
31
|
-
|
32
|
+
|
32
33
|
def test_strf
|
33
34
|
a = Angle.new("S37 01'7.5\"")
|
34
|
-
assert_equal("-37 01'07.5000\"", a.strf) #default format of strf
|
35
|
+
assert_equal("-37 01'07.5000\"", a.strf) # default format of strf
|
35
36
|
assert_equal("37 01'07.50000\"S", a.strf( "%d %2m'%2.5s\"%N" ))
|
36
37
|
assert_equal("37 01'07.50000\"W", a.strf("%d %2m'%2.5s\"%E" ))
|
37
38
|
assert_equal("-37 01'07.5000\"", a.strf("%d %2m'%2.4s\"" ))
|
38
39
|
assert_equal("-37 01.1250'\n", a.strf("%d %2.4M'\n" ))
|
39
|
-
assert_equal("*** -37 01'.1250", a.strf( "*** %d %2m'%4W" )) #puting the minute ' before decimal point.
|
40
|
-
assert_equal(
|
40
|
+
assert_equal("*** -37 01'.1250", a.strf( "*** %d %2m'%4W" )) # puting the minute ' before decimal point.
|
41
|
+
assert_equal('-37.01875 ', a.strf('%0.5D ' ))
|
41
42
|
assert_equal("-0.64610 radians\n", a.strf("%0.5r radians\n" ))
|
42
43
|
|
43
|
-
assert_equal("-037 01'7.5000\"", Angle.new("-37 01'7.5\"").to_s('%3d %2m\'%1.4s"')) #testing leading 0 with -deg, no leading 0 %s
|
44
|
-
assert_equal("00 01'07.5000\"S", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"%N')) #testing 0 degrees and leading 0 %s
|
45
|
-
assert_equal("00 -01'07.5000\"", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"')) #testing 0 degrees and -min
|
46
|
-
assert_equal("00 -01'07.5000\"", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"') ) #test of 0 degrees, -min, no NSEW
|
47
|
-
assert_equal("000 00'07.5000\"W", Angle.new("0 0'7.5\"W").to_s('%3d %2m\'%2.4s"%E') ) #testing E W 0 deg and 0 min and -sec
|
48
|
-
assert_equal("00 00'-07.5000\"", Angle.new("0 0'7.5\"S").to_s('%2d %2m\'%2.4s"') ) #testing 0 deg and 0 min and -sec no NSEW
|
44
|
+
assert_equal("-037 01'7.5000\"", Angle.new("-37 01'7.5\"").to_s('%3d %2m\'%1.4s"')) # testing leading 0 with -deg, no leading 0 %s
|
45
|
+
assert_equal("00 01'07.5000\"S", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"%N')) # testing 0 degrees and leading 0 %s
|
46
|
+
assert_equal("00 -01'07.5000\"", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"')) # testing 0 degrees and -min
|
47
|
+
assert_equal("00 -01'07.5000\"", Angle.new("0 01'7.5\"S").to_s('%2d %2m\'%2.4s"') ) # test of 0 degrees, -min, no NSEW
|
48
|
+
assert_equal("000 00'07.5000\"W", Angle.new("0 0'7.5\"W").to_s('%3d %2m\'%2.4s"%E') ) # testing E W 0 deg and 0 min and -sec
|
49
|
+
assert_equal("00 00'-07.5000\"", Angle.new("0 0'7.5\"S").to_s('%2d %2m\'%2.4s"') ) # testing 0 deg and 0 min and -sec no NSEW
|
49
50
|
end
|
50
51
|
|
51
52
|
def test_operators
|
52
|
-
#Comparable.
|
53
|
-
assert_equal(Angle.radians(-0.646099072472651), Angle.radians(-0.646099072472651))
|
54
|
-
#unary-op Angle
|
55
|
-
assert_equal(+Angle.radians(-0.646099072472651), Angle.radians(-0.646099072472651)) #unary +
|
56
|
-
assert_equal(-Angle.radians(-0.646099072472651), Angle.radians(0.646099072472651)) #unary -
|
57
|
-
#Angle op Numeric
|
58
|
-
assert_equal(5, Angle.radians(2) +
|
59
|
-
assert_equal(-1, Angle.radians(2) -
|
60
|
-
assert_equal(6, Angle.radians(2) *
|
61
|
-
assert_equal(2, Angle.radians(4) /2) # /
|
53
|
+
# Comparable.
|
54
|
+
assert_equal(Angle.radians(-0.646099072472651), Angle.radians(-0.646099072472651)) # <=>
|
55
|
+
# unary-op Angle
|
56
|
+
assert_equal(+Angle.radians(-0.646099072472651), Angle.radians(-0.646099072472651)) # unary +
|
57
|
+
assert_equal(-Angle.radians(-0.646099072472651), Angle.radians(0.646099072472651)) # unary -
|
58
|
+
# Angle op Numeric
|
59
|
+
assert_equal(5, Angle.radians(2) + 3) # +
|
60
|
+
assert_equal(-1, Angle.radians(2) - 3) # -
|
61
|
+
assert_equal(6, Angle.radians(2) * 3) # *
|
62
|
+
assert_equal(2, Angle.radians(4) / 2) # /
|
62
63
|
assert_equal(1, Angle.radians(4) % 3) # %
|
63
|
-
assert_equal(64, Angle.radians(4)
|
64
|
-
#Numeric op Angle
|
64
|
+
assert_equal(64, Angle.radians(4)**3) # **
|
65
|
+
# Numeric op Angle
|
65
66
|
assert_equal(5.1, 3.1 + Angle.radians(2) ) # +
|
66
67
|
assert_equal(2.646099072472651, 2 - Angle.radians(-0.646099072472651) ) # -
|
67
68
|
assert_equal(6, 3 * Angle.radians(2) ) # *
|
68
69
|
assert_equal(2, 4 / Angle.radians(2) ) # /
|
69
|
-
#Angle op Angle
|
70
|
-
assert_equal(Angle.radians(3.2+2.1), Angle.radians(3.2) + Angle.radians(2.1) ) # +
|
71
|
-
#Sign method.
|
70
|
+
# Angle op Angle
|
71
|
+
assert_equal(Angle.radians(3.2 + 2.1), Angle.radians(3.2) + Angle.radians(2.1) ) # +
|
72
|
+
# Sign method.
|
72
73
|
assert_equal(1, Angle.radians(3).sign)
|
73
74
|
assert_equal(-1, Angle.radians(-3).sign)
|
74
|
-
#abs
|
75
|
+
# abs
|
75
76
|
assert_equal(3, Angle.radians(-3).abs)
|
76
|
-
#reverse
|
77
|
+
# reverse
|
77
78
|
assert_equal(Angle.degrees(90), Angle.degrees(270).reverse)
|
78
|
-
#bearing
|
79
|
+
# bearing
|
79
80
|
assert_equal(Angle.degrees(340), Angle.degrees(20).to_bearing)
|
80
81
|
end
|
81
|
-
end
|
82
|
+
end
|
data/test/ts_coordinate.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
require 'test/unit'
|
2
|
-
|
3
|
+
require_relative '../lib/vincenty.rb'
|
3
4
|
|
4
|
-
class
|
5
|
-
#test Coordinate
|
5
|
+
class TestCoordinate < Test::Unit::TestCase
|
6
|
+
# test Coordinate
|
6
7
|
def test_coordinate
|
7
|
-
c = Coordinate.new(-36.9923293459124, 174.485341187381,13.5)
|
8
|
+
c = Coordinate.new(-36.9923293459124, 174.485341187381, 13.5)
|
8
9
|
ca = c.to_ary
|
9
|
-
assert_equal(-36.9923293459124, ca[0].
|
10
|
-
assert_equal(174.485341187381, ca[1].
|
10
|
+
assert_equal(-36.9923293459124, ca[0].to_deg)
|
11
|
+
assert_equal(174.485341187381, ca[1].to_deg)
|
11
12
|
assert_equal(13.5, ca[2])
|
12
13
|
ch = c.to_hash
|
13
|
-
assert_equal(-36.9923293459124, ch[:latitude].
|
14
|
-
assert_equal(174.485341187381, ch[:longitude].
|
14
|
+
assert_equal(-36.9923293459124, ch[:latitude].to_deg)
|
15
|
+
assert_equal(174.485341187381, ch[:longitude].to_deg)
|
15
16
|
assert_equal(13.5, ch[:altitude])
|
16
17
|
assert_equal("36 59'32.3856\"S 174 29'07.2283\"E 13.5m", c.to_s)
|
17
18
|
end
|
18
|
-
end
|
19
|
+
end
|
data/test/ts_latitude.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
require 'test/unit'
|
2
|
-
|
3
|
+
require_relative '../lib/vincenty.rb'
|
3
4
|
|
4
|
-
class
|
5
|
+
class TestLatitude < Test::Unit::TestCase
|
5
6
|
def test_strf
|
6
7
|
assert_equal("37 01'07.5000\"S", Latitude.new("S37 01'7.5\"").to_s)
|
7
8
|
assert_equal("37 01'07.5000\"S", Latitude.new("-37 01'7.5\"").to_s)
|
@@ -10,22 +11,24 @@ class TestAngle< Test::Unit::TestCase
|
|
10
11
|
assert_equal("37 01'07.5000\"N", Latitude.new("37 01'7.5\"").to_s)
|
11
12
|
assert_equal("37 01'07.5000\"N", Latitude.new("37 01'7.5\"N").to_s)
|
12
13
|
end
|
14
|
+
|
13
15
|
def test_to_radians
|
14
|
-
assert_equal(Math::PI/4, Latitude.degrees(45).
|
15
|
-
assert_equal(Math::PI/4, Latitude.degrees(135).
|
16
|
-
assert_equal(-Math::PI/4, Latitude.degrees(225).
|
17
|
-
assert_equal(-Math::PI/4, Latitude.degrees(315).
|
16
|
+
assert_equal(Math::PI / 4, Latitude.degrees(45).to_rad)
|
17
|
+
assert_equal(Math::PI / 4, Latitude.degrees(135).to_rad)
|
18
|
+
assert_equal(-Math::PI / 4, Latitude.degrees(225).to_rad)
|
19
|
+
assert_equal(-Math::PI / 4, Latitude.degrees(315).to_rad)
|
18
20
|
end
|
21
|
+
|
19
22
|
def test_to_degrees
|
20
|
-
assert_equal(45, Latitude.degrees(45).
|
21
|
-
assert_equal(45, Latitude.degrees(135).
|
22
|
-
assert_equal(-45, Latitude.degrees(225).
|
23
|
-
assert_equal(-45, Latitude.degrees(315).
|
24
|
-
assert_equal(1, Latitude.degrees(179).
|
25
|
-
assert_equal(-1, Latitude.degrees(181).
|
26
|
-
assert_equal(-89, Latitude.degrees(269).
|
27
|
-
assert_equal(-89, Latitude.degrees(271).
|
28
|
-
assert_equal(89, Latitude.degrees(89).
|
29
|
-
assert_equal(89, Latitude.degrees(91).
|
23
|
+
assert_equal(45, Latitude.degrees(45).to_deg)
|
24
|
+
assert_equal(45, Latitude.degrees(135).to_deg)
|
25
|
+
assert_equal(-45, Latitude.degrees(225).to_deg)
|
26
|
+
assert_equal(-45, Latitude.degrees(315).to_deg)
|
27
|
+
assert_equal(1, Latitude.degrees(179).to_deg)
|
28
|
+
assert_equal(-1, Latitude.degrees(181).to_deg)
|
29
|
+
assert_equal(-89, Latitude.degrees(269).to_deg)
|
30
|
+
assert_equal(-89, Latitude.degrees(271).to_deg)
|
31
|
+
assert_equal(89, Latitude.degrees(89).to_deg)
|
32
|
+
assert_equal(89, Latitude.degrees(91).to_deg)
|
30
33
|
end
|
31
|
-
end
|
34
|
+
end
|
data/test/ts_longitude.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
require 'test/unit'
|
2
|
-
|
3
|
+
require_relative '../lib/vincenty.rb'
|
3
4
|
|
4
|
-
class
|
5
|
+
class TestLongitude < Test::Unit::TestCase
|
5
6
|
def test_strf
|
6
7
|
assert_equal("037 01'07.5000\"W", Longitude.new("W37 01'7.5\"").to_s)
|
7
8
|
assert_equal("037 01'07.5000\"W", Longitude.new("-37 01'7.5\"").to_s)
|
@@ -10,16 +11,18 @@ class TestAngle< Test::Unit::TestCase
|
|
10
11
|
assert_equal("037 01'07.5000\"E", Longitude.new("37 01'7.5\"").to_s)
|
11
12
|
assert_equal("037 01'07.5000\"E", Longitude.new("37 01'7.5\"E").to_s)
|
12
13
|
end
|
14
|
+
|
13
15
|
def test_to_radians
|
14
|
-
assert_equal(Math::PI/4, Longitude.degrees(45).
|
15
|
-
assert_equal(3*Math::PI/4, Longitude.degrees(135).
|
16
|
-
assert_equal(-3*Math::PI/4, Longitude.degrees(225).
|
17
|
-
assert_equal(-Math::PI/4, Longitude.degrees(315).
|
16
|
+
assert_equal(Math::PI / 4, Longitude.degrees(45).to_rad)
|
17
|
+
assert_equal(3 * Math::PI / 4, Longitude.degrees(135).to_rad)
|
18
|
+
assert_equal(-3 * Math::PI / 4, Longitude.degrees(225).to_rad)
|
19
|
+
assert_equal(-Math::PI / 4, Longitude.degrees(315).to_rad)
|
18
20
|
end
|
21
|
+
|
19
22
|
def test_to_degrees
|
20
|
-
assert_equal(45, Longitude.degrees(45).
|
21
|
-
assert_equal(135, Longitude.degrees(135).
|
22
|
-
assert_equal(-135, Longitude.degrees(225).
|
23
|
-
assert_equal(-45, Longitude.degrees(315).
|
23
|
+
assert_equal(45, Longitude.degrees(45).to_deg)
|
24
|
+
assert_equal(135, Longitude.degrees(135).to_deg)
|
25
|
+
assert_equal(-135, Longitude.degrees(225).to_deg)
|
26
|
+
assert_equal(-45, Longitude.degrees(315).to_deg)
|
24
27
|
end
|
25
|
-
end
|
28
|
+
end
|