vincenty 1.0.6 → 1.0.10

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.
data/lib/vincenty.rb CHANGED
@@ -1,192 +1,201 @@
1
- require 'core_extensions.rb'
2
- require 'angle.rb'
3
- require 'latitude.rb'
4
- require 'longitude.rb'
5
- require 'track_and_distance.rb'
6
- require '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.
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.6'
16
-
15
+ VERSION = '1.0.10'
16
+
17
17
  # @return [String] constant VERSION
18
18
  def version
19
19
  VERSION
20
20
  end
21
-
22
- #Great Circle formulae http://en.wikipedia.org/wiki/Great-circle_distance
23
- #Reference calculation for testing, assumes the earth is a sphere, which it isn't.
24
- #This gives us an approximation to verify Vincenty algorithm.
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.
25
30
  # @param [Coordinate] p2 is target coordinate that we want the bearing to.
26
31
  # @return [TrackAndDistance] with the compass bearing and distance in meters to P2
27
- def sphericalDistanceAndAngle( p2 )
28
- a = 6378137 #equatorial radius in meters (+/-2 m)
29
- b = 6356752.31424518 #polar radius in meters
30
- r = (a+b)/2 #average diametre as a rough estimate for our tests.
31
-
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
+
32
42
  sin_lat1 = Math.sin(@latitude.to_rad)
33
43
  sin_lat2 = Math.sin(p2.latitude.to_rad)
34
44
  cos_lat1 = Math.cos(@latitude.to_rad)
35
45
  atan1_2 = Math.atan(1) * 2
36
- t1 = cos_lat1 * Math.cos(p2.latitude.to_rad) * ( Math.cos(@longitude.to_rad - p2.longitude.to_rad) ) + sin_lat1 * sin_lat2
37
- 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.
38
48
 
39
49
  t2 = (sin_lat2 - sin_lat1 * Math.cos(angular_distance)) / (cos_lat1 * Math.sin(angular_distance))
40
- if(Math.sin(p2.longitude.to_rad - @longitude.to_rad) < 0)
41
- bearing = 2 * Math::PI - (Math.atan(-t2 / Math.sqrt(-t2 * t2 + 1)) + atan1_2) #Compass Bearing in radians (clockwise)
42
- else
43
- bearing = Math.atan(-t2 / Math.sqrt(-t2 * t2 + 1)) + atan1_2 #Compass Bearing in radians (clockwise)
44
- end
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
45
55
 
46
- #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.
47
57
  return TrackAndDistance.new(bearing, angular_distance * r, true)
48
58
  end
49
59
 
50
- #Vincenty's algorithm for finding bearing and distance between to coordinates.
51
- #Assumes earth is a WGS-84 Ellipsod.
60
+ # Vincenty's algorithm for finding bearing and distance between to coordinates.
61
+ # Assumes earth is a WGS-84 Ellipsod.
52
62
  # @param [Coordinate] p2 is target coordinate that we want the bearing to.
53
63
  # @return [TrackAndDistance] with the compass bearing and distance in meters to P2
54
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
+
55
69
  # a, b = major & minor semiaxes of the ellipsoid
56
- a = 6378137 #equatorial radius in meters (+/-2 m)
57
- b = 6356752.31424518 #polar radius in meters
58
- f = (a-b)/a # flattening
59
-
60
- lat1 = @latitude.to_rad
61
- lon1 = @longitude.to_rad
62
- lat2 = p2.latitude.to_rad
63
- lon2 = p2.longitude.to_rad
64
- lat1 = lat1.sign * (Math::PI/2-(1e-10)) if (Math::PI/2-lat1.abs).abs < 1.0e-10
65
- lat2 = lat2.sign * (Math::PI/2-(1e-10)) if (Math::PI/2-lat2.abs).abs < 1.0e-10
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
66
80
 
67
81
  # lat1, lat2 = geodetic latitude
68
-
69
- l = (lon2 - lon1).abs #difference in longitude
70
- l = 2*Math::PI - l if l > Math::PI
71
- u1 = Math.atan( ( 1 - f) * Math.tan( lat1 ) ) #U is 'reduced latitude'
72
- u2 = Math.atan( ( 1 - f) * Math.tan( lat2 ) )
73
- sin_u1 = Math.sin(u1)
74
- cos_u1 = Math.cos(u1)
75
- sin_u2 = Math.sin(u2)
76
- cos_u2 = Math.cos(u2)
77
-
78
- lambda_v = l
79
- lambda_dash = Math::PI * 2
80
- while( (lambda_v - lambda_dash).abs > 1.0e-12 ) #i.e. 0.06 mm error
81
- sin_lambda_v = Math.sin(lambda_v)
82
- cos_lambda_v = Math.cos(lambda_v)
83
- sin_sigma = Math.sqrt( ( cos_u2 * sin_lambda_v ) ** 2 + ( cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v ) ** 2 )
84
- cos_sigma = sin_u1 * sin_u2 + cos_u1 * cos_u2 * cos_lambda_v
85
- sigma = Math.atan2(sin_sigma, cos_sigma)
86
- sin_alpha= cos_u1 * cos_u2 * sin_lambda_v / sin_sigma
87
- cos_2_alpha = 1 - sin_alpha * sin_alpha #trig identity
88
- cos_2_sigma_m = cos_sigma - 2 * sin_u1 * sin_u2/cos_2_alpha
89
- c = f / 16 * cos_2_alpha * (4 + f*(4-3*cos_2_alpha))
90
- lambda_dash = lambda_v
91
- 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
92
- if lambda_v > Math::PI
93
- lambda_v = Math::PI
94
- break
95
- end
96
- end
97
82
 
98
- u_2 = cos_2_alpha * (a * a - b * b) / (b * b)
99
- a1 = 1 + u_2 / 16384 * (4096 + u_2 * (-768 + u_2 * (320 - 175 * u_2)))
100
- b1 = u_2 / 1024 * (256 + u_2 * (-128 + u_2 * (74 - 47 * u_2)))
101
- 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)))
102
- s = b * a1 * (sigma - delta_sigma)
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
103
95
  sin_lambda_v = Math.sin(lambda_v)
104
96
  cos_lambda_v = Math.cos(lambda_v)
105
-
106
- #This test isn't in original formulae, and fixes the problem of all angles returned being between 0 - PI (0-180)
107
- #Also converts the result to compass bearing, rather than the mathmatical anticlockwise angles.
108
- if(Math.sin(p2.longitude.to_rad - @longitude.to_rad) < 0)
109
- alpha_1 = Math::PI*2-Math.atan2( cos_u2 * sin_lambda_v, cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v)
110
- #alpha_2 = Math::PI*2-Math.atan2(cos_u1 * sin_lambda_v, -sin_u1 * cos_u2 + cos_u1 * sin_u2 * cos_lambda_v)
111
- else
112
- alpha_1 = Math.atan2( cos_u2 * sin_lambda_v, cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda_v)
113
- #alpha_2 = Math.atan2(cos_u1 * sin_lambda_v, -sin_u1 * cos_u2 + cos_u1 * sin_u2 * cos_lambda_v)
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
114
109
  end
115
-
116
- #Note that the bearing is a compass (i.e. clockwise) angle.
117
- return TrackAndDistance.new(alpha_1, s, true) #What to do with alpha_2?
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?
118
132
  end
119
133
 
120
- #spherical earth estimate of calculation for finding target coordinate from start coordinate, bearing and distance
121
- #Used to run checks on the Vincenty algorithm
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
122
136
  # @param [TrackAndDistance] track_and_distance specifying bearing and distance.
123
137
  # @return [Vincenty] with the destination coordinates.
124
138
  def sphereDestination( track_and_distance )
125
- a = 6378137 #equatorial radius in meters (+/-2 m)
126
- b = 6356752.31424518 #polar radius in meters
127
- r = (a+b)/2 #average diametre as a rough estimate for our tests.
128
-
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
+
129
143
  d = track_and_distance.distance.abs
130
- sin_dor = Math.sin(d/r)
131
- cos_dor = Math.cos(d/r)
144
+ sin_dor = Math.sin(d / r)
145
+ cos_dor = Math.cos(d / r)
132
146
  sin_lat1 = Math.sin(@latitude.to_rad)
133
147
  cos_lat1 = Math.cos(@latitude.to_rad)
134
148
  lat2 = Math.asin( sin_lat1 * cos_dor + cos_lat1 * sin_dor * Math.cos(track_and_distance.bearing.to_rad) )
135
- 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))
136
-
137
- Vincenty.new(lat2, lon2, 0, true);
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)
138
152
  end
139
153
 
140
154
  #
141
155
  # Calculate destination point given start point lat/long, bearing and distance.
142
- #Assumes earth is a WGS-84 Ellipsod.
156
+ # Assumes earth is a WGS-84 Ellipsod.
143
157
  # @param [TrackAndDistance] specifying bearing and distance.
144
158
  # @return [Vincenty] with the destination coordinates.
145
- def destination( track_and_distance )
159
+ def destination( track_and_distance )
146
160
  # a, b = major & minor semiaxes of the ellipsoid
147
- a = 6378137 #equatorial radius in meters (+/-2 m)
148
- b = 6356752.31424518 #polar radius in meters
149
- f = (a-b)/a # flattening
150
-
151
- s = track_and_distance.distance.abs;
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
152
166
  alpha1 = track_and_distance.bearing.to_rad
153
167
  sin_alpha1 = Math.sin(alpha1)
154
168
  cos_alpha1 = Math.cos(alpha1)
155
-
156
- tanU1 = (1-f) * Math.tan(@latitude.to_rad);
157
- cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1))
169
+
170
+ tanU1 = (1 - f) * Math.tan(@latitude.to_rad)
171
+ cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1))
158
172
  sinU1 = tanU1 * cosU1
159
173
  sigma1 = Math.atan2(tanU1, cos_alpha1)
160
- sin_alpha = cosU1 * sin_alpha1
161
- cos_2_alpha = 1 - sin_alpha * sin_alpha #Trig identity
162
- u_2 = cos_2_alpha * (a * a - b * b) / (b * b)
163
- a1 = 1 + u_2/16384 * (4096 + u_2 * (-768 + u_2 * (320-175 * u_2)))
164
- b1 = u_2/1024 * (256 + u_2 * (-128 + u_2 * (74-47 * u_2)))
165
-
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
+
166
180
  sigma = s / (b * a1)
167
181
  sigma_dash = 2 * Math::PI
168
- while ((sigma-sigma_dash).abs > 1.0e-12) #i.e 0.06mm
169
- cos_2_sigma_m = Math.cos(2 * sigma1 + sigma)
182
+ while (sigma - sigma_dash).abs > 1.0e-12 # i.e 0.06mm
183
+ cos_2_sigma_m = Math.cos(2 * sigma1 + sigma)
170
184
  sin_sigma = Math.sin(sigma)
171
185
  cos_sigma = Math.cos(sigma)
172
- 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)))
173
187
  sigma_dash = sigma
174
- sigma = s / (b * a1) + delta_sigma
188
+ sigma = s / (b * a1) + delta_sigma
175
189
  end
176
190
 
177
191
  tmp = sinU1 * sin_sigma - cosU1 * cos_sigma * cos_alpha1
178
- lat2 = Math.atan2(sinU1 * cos_sigma + cosU1 * sin_sigma * cos_alpha1, (1-f) * Math.sqrt(sin_alpha * sin_alpha + tmp * tmp))
192
+ lat2 = Math.atan2(sinU1 * cos_sigma + cosU1 * sin_sigma * cos_alpha1, (1 - f) * Math.sqrt(sin_alpha * sin_alpha + tmp * tmp))
179
193
  lambda_v = Math.atan2(sin_sigma * sin_alpha1, cosU1 * cos_sigma - sinU1 * sin_sigma * cos_alpha1)
180
- c = f/16 * cos_2_alpha * (4 + f * (4-3 * cos_2_alpha))
181
- 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
182
-
183
- #sigma2 = Math.atan2(sin_alpha, -tmp) # reverse azimuth
184
-
185
- return Vincenty.new(lat2, @longitude + l, 0, true);
186
- 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
187
196
 
197
+ # sigma2 = Math.atan2(sin_alpha, -tmp) # reverse azimuth
188
198
 
199
+ return Vincenty.new(lat2, @longitude + l, 0, true)
200
+ end
189
201
  end
190
-
191
-
192
-
data/test/ts_all.rb CHANGED
@@ -1,11 +1,10 @@
1
- require 'ts_angle.rb'
2
- require 'ts_vincenty.rb'
3
- require 'ts_latitude.rb'
4
- require 'ts_longitude.rb'
5
- require 'ts_coordinate.rb'
6
- require 'ts_track_and_distance.rb'
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
 
8
- puts "Testing from source"
9
+ puts 'Testing from source'
9
10
  puts Vincenty.new.version
10
-
11
-
data/test/ts_angle.rb CHANGED
@@ -1,19 +1,20 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'test/unit'
2
- require 'vincenty.rb'
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(), 0)
8
- assert_equal(Angle.new("S37 01'7.5\"").to_deg, -37.01875) #Leading NSEW
9
- assert_equal(Angle.new("37 01'7.5\"S").to_deg , -37.01875) #Trailing NSEW
10
- assert_equal(Angle.new("-37 01'7.5\"").to_deg, -37.01875) #Use of - rather than S or W
11
- assert_equal(Angle.new("-37 1.125'").to_deg, -37.01875) #Decimal minutes, rather than minutes and seconds.
12
- assert_equal(Angle.new("-37 01'.125").to_deg, -37.01875) #Nb. the minute marker ' between the minutes and fraction
13
- assert_equal(Angle.new("S37 01'.125").to_deg, -37.01875) #Nb. the minute marker ' between the minutes and fraction
14
- assert_equal(Angle.new("37 01'.125S").to_deg, -37.01875) #Nb. the minute marker ' between the minutes and fraction
15
- assert_equal(Angle.new("-37.01875 ").to_deg, -37.01875) #decimal degrees, rather than deg, min, sec.
16
- assert_equal(Angle.new([-37, 1, 7.5]).to_deg, -37.01875) #an array of deg,min,sec
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
17
18
  assert_equal(Angle.new(-37.01875).to_deg, -37.01875)
18
19
  assert_equal(Angle.degrees(-37.01875).to_deg, -37.01875)
19
20
  assert_equal(Angle.degrees(-37.01875).to_rad.round(15), -0.646099072472651)
@@ -21,61 +22,61 @@ class TestAngle< Test::Unit::TestCase
21
22
  assert_equal(Angle.new(-0.646099072472651, true).to_rad, -0.646099072472651)
22
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) )),-(1.0 + 5/60.0 + 1.0/3600.0)) #double call, rounding error always produced a failure.
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("-37.01875 ", a.strf("%0.5D " ))
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) + 3) # +
59
- assert_equal(-1, Angle.radians(2) - 3) # -
60
- assert_equal(6, Angle.radians(2) * 3) # *
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) ** 3) # **
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
@@ -1,10 +1,11 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'test/unit'
2
- require 'vincenty.rb'
3
+ require_relative '../lib/vincenty.rb'
3
4
 
4
- class TestAngle< Test::Unit::TestCase
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
10
  assert_equal(-36.9923293459124, ca[0].to_deg)
10
11
  assert_equal(174.485341187381, ca[1].to_deg)
@@ -15,4 +16,4 @@ class TestAngle< Test::Unit::TestCase
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
- require 'vincenty.rb'
3
+ require_relative '../lib/vincenty.rb'
3
4
 
4
- class TestAngle< Test::Unit::TestCase
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,12 +11,14 @@ 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).to_rad)
15
- assert_equal(Math::PI/4, Latitude.degrees(135).to_rad)
16
- assert_equal(-Math::PI/4, Latitude.degrees(225).to_rad)
17
- assert_equal(-Math::PI/4, Latitude.degrees(315).to_rad)
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
23
  assert_equal(45, Latitude.degrees(45).to_deg)
21
24
  assert_equal(45, Latitude.degrees(135).to_deg)
@@ -28,4 +31,4 @@ class TestAngle< Test::Unit::TestCase
28
31
  assert_equal(89, Latitude.degrees(89).to_deg)
29
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
- require 'vincenty.rb'
3
+ require_relative '../lib/vincenty.rb'
3
4
 
4
- class TestAngle< Test::Unit::TestCase
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).to_rad)
15
- assert_equal(3*Math::PI/4, Longitude.degrees(135).to_rad)
16
- assert_equal(-3*Math::PI/4, Longitude.degrees(225).to_rad)
17
- assert_equal(-Math::PI/4, Longitude.degrees(315).to_rad)
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
23
  assert_equal(45, Longitude.degrees(45).to_deg)
21
24
  assert_equal(135, Longitude.degrees(135).to_deg)
22
25
  assert_equal(-135, Longitude.degrees(225).to_deg)
23
26
  assert_equal(-45, Longitude.degrees(315).to_deg)
24
27
  end
25
- end
28
+ end
@@ -1,16 +1,19 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'test/unit'
2
- require 'vincenty.rb'
3
+ require_relative '../lib/vincenty.rb'
3
4
 
4
- class TestAngle< Test::Unit::TestCase
5
- #test TrackAndDistance
5
+ class TestTrackAndDistance < Test::Unit::TestCase
6
+ # test TrackAndDistance
6
7
  def test_track_and_distance
7
- assert_equal("140 14'10.0000\" 12.0m", TrackAndDistance.new(Angle.new("320,14,10").reverse, 12.0).to_s)
8
- assert_equal("215 03'00.0000\" 19.73m", TrackAndDistance.new("215,3,0", 19.73 ).to_s)
9
- a = TrackAndDistance.new("215,3,0", 19.73 ).to_ary
8
+ assert_equal("140 14'10.0000\" 12.0m", TrackAndDistance.new(Angle.new('320,14,10').reverse, 12.0).to_s)
9
+ assert_equal("215 03'00.0000\" 19.73m", TrackAndDistance.new('215,3,0', 19.73 ).to_s)
10
+
11
+ a = TrackAndDistance.new('215,3,0', 19.73 ).to_ary
10
12
  assert_equal("215 03'00.0000\"", a[0].strf)
11
- assert_equal("19.73", a[1].to_s)
12
- a = TrackAndDistance.new("215,3,0", 19.73 ).to_hash
13
+ assert_equal('19.73', a[1].to_s)
14
+
15
+ a = TrackAndDistance.new('215,3,0', 19.73 ).to_hash
13
16
  assert_equal("215 03'00.0000\"", a[:bearing].strf)
14
- assert_equal("19.73", a[:distance].to_s)
17
+ assert_equal('19.73', a[:distance].to_s)
15
18
  end
16
19
  end