vincenty 1.0.8 → 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 +5 -5
- data/History.txt +16 -0
- data/README.md +3 -3
- data/Rakefile +20 -15
- data/lib/angle.rb +127 -134
- data/lib/coordinate.rb +8 -9
- data/lib/core_extensions.rb +47 -49
- data/lib/latitude.rb +20 -22
- data/lib/longitude.rb +11 -15
- data/lib/track_and_distance.rb +31 -32
- data/lib/vincenty.rb +110 -112
- data/test/ts_all.rb +1 -1
- data/test/ts_angle.rb +46 -45
- data/test/ts_coordinate.rb +4 -3
- data/test/ts_latitude.rb +8 -5
- data/test/ts_longitude.rb +8 -5
- data/test/ts_track_and_distance.rb +9 -9
- data/test/ts_vincenty.rb +53 -53
- metadata +12 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a8c6ea3c3470ff15da8327c1d3a0094a3f3c4b1c8d0796a38b9fd6218a61673c
|
4
|
+
data.tar.gz: 9a648f496428a4c1cf42ae6fcf2d3fdf595c40da7db73bea862e147998d8eded
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9839e6de4ac0d516d29577d6bd0d4594c8967bb793bc19e202c75ee03fd5c1e50e543888ad32e3915324307c11d01e8c7ade41793c811e2e3c99bf48fab519e
|
7
|
+
data.tar.gz: f6ba931e58dc2835d24a8f1a604fac8c14d70c409f4d8667fd0c5ce16b47a9a138f45b816cbb337a0294de0e07a6a763af9f79d646a72d01e854a5c34270b7e1
|
data/History.txt
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
robertburrowes Sun Oct 10 11:39:21 2021 +1300
|
2
|
+
Bump Version, after removing stray '.'
|
3
|
+
robertburrowes Fri Oct 8 16:32:19 2021 +1300
|
4
|
+
rubocop cleanup
|
5
|
+
robertburrowes Sat Oct 31 22:30:50 2020 +1300
|
6
|
+
.yardoc shouldn't be in the repo
|
7
|
+
robertburrowes Sat Oct 31 16:25:23 2020 +1300
|
8
|
+
Include Separate License file
|
9
|
+
robertburrowes Sat Oct 31 16:19:30 2020 +1300
|
10
|
+
Docs at .io, not .com
|
11
|
+
robertburrowes Sat Oct 31 16:19:12 2020 +1300
|
12
|
+
Standard Rakefile
|
13
|
+
robertburrowes Sat Oct 31 16:18:42 2020 +1300
|
14
|
+
Mv dev scripts to sbin
|
15
|
+
rbur004 Sat Dec 3 18:12:35 2016 +1300
|
16
|
+
Changed tests to be individually runable
|
1
17
|
rbur004 Sat Dec 3 17:36:05 2016 +1300
|
2
18
|
Code is old. Needed require change to require_relative
|
3
19
|
Rob Burrowes Fri May 22 14:07:09 2015 +1200
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Vincenty
|
2
2
|
|
3
|
-
* http://rbur004.github.
|
4
|
-
* Source https://github.com/rbur004/vincenty
|
5
|
-
* Gem https://rubygems.org/gems/vincenty
|
3
|
+
* Docs :: http://rbur004.github.io/vincenty/
|
4
|
+
* Source :: https://github.com/rbur004/vincenty
|
5
|
+
* Gem :: https://rubygems.org/gems/vincenty
|
6
6
|
|
7
7
|
## DESCRIPTION:
|
8
8
|
|
data/Rakefile
CHANGED
@@ -1,22 +1,27 @@
|
|
1
|
-
#!/usr/local/bin/ruby
|
2
1
|
# -*- ruby -*-
|
3
|
-
|
4
|
-
# gem install yard
|
5
|
-
# gem install hoe
|
6
|
-
# gem install hoe-yard
|
7
|
-
require 'yard'
|
2
|
+
require 'rubygems'
|
8
3
|
require 'hoe'
|
9
|
-
#require 'lib/vincenty.rb'
|
10
4
|
Hoe.plugin :yard
|
5
|
+
load "#{__dir__}/version"
|
11
6
|
|
12
|
-
Hoe.spec
|
13
|
-
|
7
|
+
Hoe.spec PROJECT do
|
8
|
+
self.readme_file = "README.md"
|
14
9
|
self.developer( "Rob Burrowes","r.burrowes@auckland.ac.nz")
|
15
|
-
|
16
|
-
|
10
|
+
remote_rdoc_dir = '' # Release to root
|
11
|
+
|
12
|
+
self.yard_title = PROJECT
|
17
13
|
self.yard_options = ['--markup', 'markdown', '--protected']
|
18
|
-
#self.url = "http://www.wikarekare.org"
|
19
|
-
#self.summary = "Vincenty Algorithm for Distance, Bearing between Map Coordinates."
|
20
|
-
#self.description = s.paragraphs_of('README.txt', 1..4).join("\n\n")
|
21
|
-
#self.remote_rdoc_dir = '' # Release to root
|
22
14
|
end
|
15
|
+
|
16
|
+
|
17
|
+
#Validate manfest.txt
|
18
|
+
#rake check_manifest
|
19
|
+
|
20
|
+
#Local checking. Creates pkg/
|
21
|
+
#rake gem
|
22
|
+
|
23
|
+
#create doc/
|
24
|
+
#rake docs
|
25
|
+
|
26
|
+
#Copy up to rubygem.org
|
27
|
+
#rake release VERSION=1.0.1
|
data/lib/angle.rb
CHANGED
@@ -1,72 +1,68 @@
|
|
1
1
|
require_relative 'core_extensions.rb'
|
2
2
|
|
3
|
-
#Class Angle is a utility class that allows
|
3
|
+
# Class Angle is a utility class that allows
|
4
4
|
# * Angle arithmetic ( +,-,*,/,**,% and unary +,-)
|
5
5
|
# * Angle comparison ( <=>, hence, <, >, >=, <=, == )
|
6
6
|
# * Conversion to and from degrees and radians
|
7
7
|
# * Conversion to string as radians or DMS format
|
8
|
-
|
9
8
|
class Angle
|
10
9
|
include Comparable
|
11
10
|
|
12
11
|
# @return [Float] stored in radians
|
13
12
|
attr_accessor :angle
|
14
|
-
alias
|
15
|
-
alias
|
13
|
+
alias value angle # Older version of angle used volue rather than angle
|
14
|
+
alias value= angle= # Older version of angle used volue rather than angle
|
16
15
|
|
17
16
|
# @param [#to_f,#to_radians] angle may be anything that has a to_f and to_radians.
|
18
17
|
# @param [true,false, :radians] radians Angle is in degrees unless radians == true (or set to :radians).
|
19
|
-
def initialize(angle=0, radians=false)
|
20
|
-
#assumes that we are getting an angle in degrees.
|
21
|
-
if radians == true || radians == :radians
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
18
|
+
def initialize(angle = 0, radians = false)
|
19
|
+
# assumes that we are getting an angle in degrees.
|
20
|
+
@angle = if radians == true || radians == :radians
|
21
|
+
angle.to_f # works for String, Fixed, other Angles and for Float.
|
22
|
+
elsif angle.instance_of?(Array)
|
23
|
+
self.class.decimal_deg(*angle).to_radians
|
24
|
+
else
|
25
|
+
angle.to_radians # we have a String and Numeric class version of this. Another Angle will work too.
|
26
|
+
end
|
30
27
|
end
|
31
28
|
|
32
|
-
|
33
|
-
#Class level function that converts 4 arguments into decimal degrees.
|
29
|
+
# Class level function that converts 4 arguments into decimal degrees.
|
34
30
|
# @return [Float] signed decimal degrees.
|
35
31
|
# @param [Numeric] degrees
|
36
32
|
# @param [Numeric] minutes
|
37
33
|
# @param [Numeric] seconds
|
38
34
|
# @param ['N', 'S', 'E', 'W'] direction Optional, as the direction might be specified by a negative value for degrees
|
39
|
-
def self.decimal_deg(degrees=0, minutes=0, seconds=0, direction='N')
|
40
|
-
s = { 'N'=>1, 'S'
|
35
|
+
def self.decimal_deg(degrees = 0, minutes = 0, seconds = 0, direction = 'N')
|
36
|
+
s = { 'N' => 1, 'S' => -1, 'E' => 1, 'W' => -1, 'n' => 1, 's' => -1, 'e' => 1, 'w' => -1 }
|
41
37
|
sign = s[direction]
|
42
|
-
sign =
|
43
|
-
#Shouldn't have a negative value for degrees if the direction is specified.
|
44
|
-
#I am defaulting to the degrees sign if it is set, otherwise the direction given
|
45
|
-
sign = degrees.sign == -1 || (degrees == 0 && (minutes < 0 || (minutes == 0 && seconds < 0)))
|
46
|
-
sign * (degrees.abs + minutes/60.0 + seconds/3600.0)
|
38
|
+
sign = 1 if sign.nil? # Assume 'N' or 'E' if the direction is not set.
|
39
|
+
# Shouldn't have a negative value for degrees if the direction is specified.
|
40
|
+
# I am defaulting to the degrees sign if it is set, otherwise the direction given
|
41
|
+
sign = -1 if degrees.sign == -1 || (degrees == 0 && (minutes < 0 || (minutes == 0 && seconds < 0)))
|
42
|
+
return sign * (degrees.abs + (minutes / 60.0) + (seconds / 3600.0))
|
47
43
|
end
|
48
44
|
|
49
|
-
#Class level function that takes an array of [degress,minutes, seconds, direction] or [degrees,minutes,seconds]
|
45
|
+
# Class level function that takes an array of [degress,minutes, seconds, direction] or [degrees,minutes,seconds]
|
50
46
|
# @return [Float] signed decimal degrees.
|
51
47
|
# @param [Array] a Array is expanded and passed as degrees,minutes,seconds,direction to Angle#decimal_deg
|
52
48
|
def self.decimal_deg_from_ary(a)
|
53
|
-
self.decimal_deg(*a)
|
49
|
+
return self.decimal_deg(*a)
|
54
50
|
end
|
55
51
|
|
56
|
-
#Class level utility function to return the angle as deg,min,sec
|
57
|
-
#Assumes decimal degress unless radians == true .
|
52
|
+
# Class level utility function to return the angle as deg,min,sec
|
53
|
+
# Assumes decimal degress unless radians == true .
|
58
54
|
# @return [Array] of signed deg, min, sec.
|
59
|
-
#Nb. * That min will be negative if the angle is negative and deg == 0
|
55
|
+
# Nb. * That min will be negative if the angle is negative and deg == 0
|
60
56
|
# * That sec will be negative if the angle is negative and deg == 0 && min == 0
|
61
57
|
# @param [#to_f,#to_degrees] angle may be anything that has a to_f and to_radians.
|
62
58
|
# @param [true,false, :radians] radians Angle is in degrees unless radians == true (or set to :radians).
|
63
59
|
def self.dms(angle, radians = false)
|
64
|
-
|
60
|
+
angle = angle.to_f # means Strings, Numeric, and anything accepting a #to_f will work.
|
65
61
|
angle = angle.to_degrees if radians == true || radians == :radians
|
66
62
|
v = angle.abs
|
67
63
|
deg = v.floor
|
68
|
-
min = ((v-deg)*60.0).floor
|
69
|
-
sec = ((v-deg-min/60.0)*3600.0)
|
64
|
+
min = ((v - deg) * 60.0).floor
|
65
|
+
sec = ((v - deg - (min / 60.0)) * 3600.0)
|
70
66
|
|
71
67
|
if angle < 0
|
72
68
|
if deg == 0
|
@@ -80,86 +76,86 @@ class Angle
|
|
80
76
|
end
|
81
77
|
end
|
82
78
|
|
83
|
-
return deg,min,sec
|
79
|
+
return deg, min, sec
|
84
80
|
end
|
85
81
|
|
86
|
-
#Class level function equivalent to Angle.new(r, true)
|
82
|
+
# Class level function equivalent to Angle.new(r, true)
|
87
83
|
# @return [Angle]
|
88
84
|
# @param [#to_f] r Value in radians to create the new Angle class with.
|
89
|
-
def self.radians(r=0)
|
90
|
-
self.new(r.to_f, true) #Nb. self is Angle, be we don't Angle.new, as we want subclasses to return their class, not Angle.
|
85
|
+
def self.radians(r = 0)
|
86
|
+
return self.new(r.to_f, true) # Nb. self is Angle, be we don't Angle.new, as we want subclasses to return their class, not Angle.
|
91
87
|
end
|
92
88
|
|
93
|
-
#Class level function equivalent to Angle.new(d, false) or just Angle.new(d)
|
89
|
+
# Class level function equivalent to Angle.new(d, false) or just Angle.new(d)
|
94
90
|
# @return [Angle]
|
95
|
-
# @param [#to_radians] d Angle to convert to radians, to create new Angle object from.
|
96
|
-
def self.degrees(d=0)
|
97
|
-
self.new(d.to_radians, true)
|
91
|
+
# @param [#to_radians] d Angle in degrees, to convert to radians, to create new Angle object from.
|
92
|
+
def self.degrees(d = 0)
|
93
|
+
return self.new(d.to_radians, true)
|
98
94
|
end
|
99
95
|
|
100
|
-
#Provides test for Module Comparable, giving us <,>,<=,>=,== between angles
|
96
|
+
# Provides test for Module Comparable, giving us <,>,<=,>=,== between angles
|
101
97
|
# @return [true,false]
|
102
98
|
# @param [Angle,Float] angle Can be another Angle, or a Numeric value to compare @angle with.
|
103
|
-
def <=>(
|
104
|
-
if
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
99
|
+
def <=>(other)
|
100
|
+
@angle <=> if other.instance_of?(Angle)
|
101
|
+
other.angle
|
102
|
+
else
|
103
|
+
other
|
104
|
+
end
|
109
105
|
end
|
110
106
|
|
111
|
-
#unary +
|
107
|
+
# unary +
|
112
108
|
# @return [Angle,self] equivalent to @angle
|
113
109
|
def +@
|
114
|
-
self.class.radians(@angle) #Nb. Not Angle.new, as we want subclasses to return their class, not Angle.
|
110
|
+
return self.class.radians(@angle) # Nb. Not Angle.new, as we want subclasses to return their class, not Angle.
|
115
111
|
end
|
116
112
|
|
117
|
-
#Unary -
|
113
|
+
# Unary -
|
118
114
|
# @return [Angle,self] -@angle
|
119
115
|
def -@
|
120
|
-
self.class.radians(-@angle)
|
116
|
+
return self.class.radians(-@angle)
|
121
117
|
end
|
122
118
|
|
123
119
|
# Binary addition operator. Can add angles and numbers, or two angles.
|
124
120
|
# @return [Angle,self]
|
125
121
|
# @param [Angle,Numeric] angle
|
126
|
-
def +(
|
127
|
-
self.class.radians(@angle +
|
122
|
+
def +(other)
|
123
|
+
return self.class.radians(@angle + other)
|
128
124
|
end
|
129
125
|
|
130
126
|
# Binary subtraction operator. Can add angles and numbers, or two angles.
|
131
127
|
# @return [Angle,self]
|
132
128
|
# @param [Angle,Numeric] angle
|
133
|
-
def -(
|
134
|
-
self.class.radians(@angle -
|
129
|
+
def -(other)
|
130
|
+
return self.class.radians(@angle - other)
|
135
131
|
end
|
136
132
|
|
137
133
|
# Binary multiply operator. Can add angles and numbers, or two angles.
|
138
134
|
# @return [Angle,self]
|
139
135
|
# @param [Angle,Numeric] angle
|
140
|
-
def *(
|
141
|
-
self.class.radians(@angle *
|
136
|
+
def *(other)
|
137
|
+
self.class.radians(@angle * other)
|
142
138
|
end
|
143
139
|
|
144
140
|
# Binary power of operator. Can add angles and numbers, or two angles.
|
145
141
|
# @return [Angle,self]
|
146
142
|
# @param [Angle,Numeric] angle
|
147
|
-
def **(
|
148
|
-
self.class.radians(@angle
|
143
|
+
def **(other)
|
144
|
+
self.class.radians(@angle**other)
|
149
145
|
end
|
150
146
|
|
151
147
|
# Binary division operator. Can add angles and numbers, or two angles.
|
152
148
|
# @return [Angle,self]
|
153
149
|
# @param [Angle,Numeric] angle
|
154
|
-
def /(
|
155
|
-
self.class.radians(@angle /
|
150
|
+
def /(other)
|
151
|
+
self.class.radians(@angle / other)
|
156
152
|
end
|
157
153
|
|
158
154
|
# Binary mod operator. Can add angles and numbers, or two angles.
|
159
155
|
# @return [Angle,self]
|
160
156
|
# @param [Angle,Numeric] angle
|
161
|
-
def %(
|
162
|
-
self.class.radians(@angle %
|
157
|
+
def %(other)
|
158
|
+
self.class.radians(@angle % other)
|
163
159
|
end
|
164
160
|
|
165
161
|
# @return [Float] angle in degrees
|
@@ -168,7 +164,7 @@ class Angle
|
|
168
164
|
end
|
169
165
|
|
170
166
|
# @return [Float] angle in degrees
|
171
|
-
#alias to_deg to_degrees
|
167
|
+
# alias to_deg to_degrees
|
172
168
|
alias to_deg to_degrees
|
173
169
|
|
174
170
|
# @return [Float] angle in radians
|
@@ -181,13 +177,13 @@ class Angle
|
|
181
177
|
|
182
178
|
# Returns @angle as decimal_degrees
|
183
179
|
# @return [Array] of signed Floats: degrees,minutes,seconds
|
184
|
-
#Nb. * That min will be negative if the angle is negative and deg == 0
|
180
|
+
# Nb. * That min will be negative if the angle is negative and deg == 0
|
185
181
|
# * That sec will be negative if the angle is negative and deg == 0 && min == 0
|
186
182
|
def to_dms
|
187
183
|
d = to_degrees.abs
|
188
184
|
deg = d.floor
|
189
|
-
min = ((d-deg)*60).floor
|
190
|
-
sec = ((d-deg-min/60.0)*3600.0)
|
185
|
+
min = ((d - deg) * 60).floor
|
186
|
+
sec = ((d - deg - (min / 60.0)) * 3600.0)
|
191
187
|
|
192
188
|
if @angle < 0
|
193
189
|
if deg == 0
|
@@ -218,7 +214,7 @@ class Angle
|
|
218
214
|
# @return [Array] the angle parameter as a Float and the @angle parameter from this class.
|
219
215
|
# @param [Numeric] angle
|
220
216
|
def coerce(angle)
|
221
|
-
[Float(angle), @angle]
|
217
|
+
[ Float(angle), @angle ]
|
222
218
|
end
|
223
219
|
|
224
220
|
# @return [Fixnum] the sign of the angle. 1 for positive, -1 for negative.
|
@@ -232,9 +228,9 @@ class Angle
|
|
232
228
|
end
|
233
229
|
|
234
230
|
# @return [Float] angle as compass bearing in radians.
|
235
|
-
#Compass bearings are clockwise, Math angles are counter clockwise.
|
231
|
+
# Compass bearings are clockwise, Math angles are counter clockwise.
|
236
232
|
def to_bearing
|
237
|
-
self.class.new(Math::PI * 2 - @angle,true)
|
233
|
+
self.class.new((Math::PI * 2) - @angle, true)
|
238
234
|
end
|
239
235
|
|
240
236
|
# @return [Float] the reverse angle in radians. i.e. angle + PI (or angle + 180 degrees)
|
@@ -242,20 +238,20 @@ class Angle
|
|
242
238
|
if (angle = @angle + Math::PI) > Math::PI * 2
|
243
239
|
angle -= Math::PI * 2
|
244
240
|
end
|
245
|
-
return self.class.new(angle,true)
|
241
|
+
return self.class.new(angle, true)
|
246
242
|
end
|
247
243
|
|
248
|
-
|
249
244
|
# @return [String] angle in radians as a string.
|
250
245
|
# @param [String] fmt Optional format string passed to Angle#strf
|
251
246
|
def to_s(fmt = nil)
|
252
|
-
return to_radians.to_s if
|
247
|
+
return to_radians.to_s if fmt.nil?
|
248
|
+
|
253
249
|
return strf(fmt)
|
254
250
|
end
|
255
251
|
|
256
|
-
#formated output of the angle.
|
252
|
+
# formated output of the angle.
|
257
253
|
# @param [String] fmt The default format is a signed deg minutes'seconds" with leading 0's in the minutes and seconds and 4 decimal places for seconds.
|
258
|
-
#formats are:
|
254
|
+
# formats are:
|
259
255
|
# * %wd output the degrees as an integer.
|
260
256
|
# ** where w is 0, 1, 2 or 3 and represents the field width.
|
261
257
|
# *** 1 is the default, which indicates that at least 1 digit is displayed
|
@@ -289,50 +285,48 @@ class Angle
|
|
289
285
|
#
|
290
286
|
# Other strings in the format are printed as is.
|
291
287
|
# @return [String]
|
292
|
-
def strf(fmt="%d %2m'%2.4s\"")
|
293
|
-
tokens = fmt.scan(/%[0-9
|
288
|
+
def strf(fmt = "%d %2m'%2.4s\"")
|
289
|
+
tokens = fmt.scan(/%[0-9.]*[%dmsDMNErW]|[^%]*/)
|
294
290
|
have_dir = have_dms = false
|
295
291
|
tokens.collect! do |t|
|
296
|
-
if t[0,1] == '%' #format
|
292
|
+
if t[0, 1] == '%' # format
|
297
293
|
had_dot = false
|
298
294
|
decimals = -1
|
299
295
|
width = -1
|
300
296
|
format = nil
|
301
297
|
t[1..-1].scan(/[0-9]+|\.|[0-9]+|[%dmsDMNErW]/) do |t2|
|
302
298
|
case t2
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
else
|
307
|
-
width = t2.to_i
|
308
|
-
end
|
309
|
-
when '%'
|
310
|
-
format = t2
|
311
|
-
when /[dmsMwW]/
|
312
|
-
have_dms = true
|
313
|
-
format = t2
|
314
|
-
when /[NE]/
|
315
|
-
have_dir = true
|
316
|
-
format = t2
|
317
|
-
when '.'
|
318
|
-
had_dot = true
|
319
|
-
when /[Dr]/
|
320
|
-
format = t2
|
299
|
+
when /[0-9]+/
|
300
|
+
if had_dot
|
301
|
+
decimals = t2.to_i
|
321
302
|
else
|
322
|
-
|
303
|
+
width = t2.to_i
|
304
|
+
end
|
305
|
+
when '%', /[Dr]/
|
306
|
+
format = t2
|
307
|
+
when /[dmsMwW]/
|
308
|
+
have_dms = true
|
309
|
+
format = t2
|
310
|
+
when /[NE]/
|
311
|
+
have_dir = true
|
312
|
+
format = t2
|
313
|
+
when '.'
|
314
|
+
had_dot = true
|
315
|
+
else
|
316
|
+
raise "unknown format character '#{t2}'" # shouldn't be able to get here.
|
323
317
|
end
|
324
318
|
end
|
325
|
-
[:format, width, decimals, format]
|
319
|
+
[ :format, width, decimals, format ]
|
326
320
|
else
|
327
|
-
[:filler, t]
|
321
|
+
[ :filler, t ]
|
328
322
|
end
|
329
323
|
end
|
330
324
|
|
331
|
-
deg,min,sec = to_dms if have_dms
|
325
|
+
deg, min, sec = to_dms if have_dms
|
332
326
|
|
333
|
-
s =
|
327
|
+
s = ''
|
334
328
|
tokens.each do |t|
|
335
|
-
if
|
329
|
+
if t[0] == :format
|
336
330
|
case t[3]
|
337
331
|
when '%'
|
338
332
|
s += '%'
|
@@ -343,81 +337,80 @@ class Angle
|
|
343
337
|
when 'm'
|
344
338
|
s += s_int(min, t[1], have_dir)
|
345
339
|
when 'M'
|
346
|
-
s += s_float(min + sec/60, t[1], t[2], have_dir)
|
340
|
+
s += s_float(min + (sec / 60), t[1], t[2], have_dir)
|
347
341
|
when 'W'
|
348
|
-
s += s_only_places(sec/60,
|
342
|
+
s += s_only_places(sec / 60, t[1])
|
349
343
|
when 's'
|
350
344
|
s += s_float(sec, t[1], t[2], have_dir)
|
351
345
|
when 'r'
|
352
346
|
s += s_float(@angle, t[1], t[2], have_dir)
|
353
347
|
when 'N'
|
354
|
-
s +=
|
348
|
+
s += (@angle < 0 ? 'S' : 'N')
|
355
349
|
when 'E'
|
356
350
|
s += (@angle < 0 ? 'W' : 'E')
|
357
351
|
end
|
358
352
|
else
|
359
|
-
s += t[1] #the fillers.
|
353
|
+
s += t[1] # the fillers.
|
360
354
|
end
|
361
355
|
end
|
362
356
|
|
363
357
|
return s
|
364
358
|
end
|
365
359
|
|
366
|
-
|
367
|
-
#
|
368
|
-
#
|
369
|
-
#
|
370
|
-
#If ploces is -1, then all decimal places are returned.
|
360
|
+
# Output angle_dec as a string to the number of decimal places specified by places.
|
361
|
+
# Assumes the angle is 0 <= angle_dec < 1
|
362
|
+
# No leading '0' is output. The string starts with a '.' if places is non-zero.
|
363
|
+
# If ploces is -1, then all decimal places are returned.
|
371
364
|
# @return [String]
|
372
365
|
# @param [Float] angle_dec Angle's fractional part
|
373
366
|
# @param [Fixnum] places Number of decimal places to output
|
374
|
-
def s_places(angle_dec, places)
|
375
|
-
if places
|
376
|
-
|
367
|
+
private def s_places(angle_dec, places)
|
368
|
+
if places == -1
|
369
|
+
angle_dec.to_s[1..-1] # Output all decimal places stripping the leading 0
|
377
370
|
else
|
378
|
-
|
371
|
+
places > 0 ? ".%0#{places}d" % (angle_dec * (10**places)).round : ''
|
379
372
|
end
|
380
373
|
end
|
381
374
|
|
382
|
-
#return the angle as a string with fixed width decimal portion with leading 0s
|
383
|
-
#to get at least the width specified
|
384
|
-
#Prints the number of places after the decimal point rounded to places places.
|
375
|
+
# return the angle as a string with fixed width decimal portion with leading 0s
|
376
|
+
# to get at least the width specified
|
377
|
+
# Prints the number of places after the decimal point rounded to places places.
|
385
378
|
#-1 width means no width format
|
386
379
|
#-1 places means print all decimal places.
|
387
|
-
#abs means print the absolute value.
|
380
|
+
# abs means print the absolute value.
|
388
381
|
# @return [String]
|
389
382
|
# @param [Float] angle In radians
|
390
383
|
# @param [Fixnum] width Output field width, padded with leading 0's
|
391
384
|
# @param [Fixnum] places Number of decimal places to output
|
392
385
|
# @param [true,false] abs Output absolute value.
|
393
|
-
def s_float(angle, width, places, abs)
|
394
|
-
|
386
|
+
private def s_float(angle, width, places, abs)
|
387
|
+
_angle_int, angle_dec = angle.abs.divmod(1)
|
395
388
|
f = "%0#{width > 0 ? width : ''}d"
|
396
|
-
s =
|
397
|
-
s
|
389
|
+
s = abs == false && angle.sign == -1 ? '-' : '' # catch the case of -0
|
390
|
+
return s + (f % angle.abs) + s_places(angle_dec, places)
|
398
391
|
end
|
399
392
|
|
400
|
-
#Return the integer part of angle as a string of fixed width
|
401
|
-
#If abs == true, then return the absolute value.
|
393
|
+
# Return the integer part of angle as a string of fixed width
|
394
|
+
# If abs == true, then return the absolute value.
|
402
395
|
# @return [Fixnum]
|
403
396
|
# @param [Float] angle In radians
|
404
397
|
# @param [Fixnum] width Output field width, padded with leading 0's
|
405
398
|
# @param [true,false] abs Output absolute value.
|
406
|
-
def s_int(angle, width, abs)
|
399
|
+
private def s_int(angle, width, abs)
|
407
400
|
f = "%0#{width > 0 ? width : ''}d"
|
408
|
-
s =
|
409
|
-
s
|
401
|
+
s = abs == false && angle.sign == -1 ? '-' : '' # catch the case of -0
|
402
|
+
return s + (f % angle.abs)
|
410
403
|
end
|
411
404
|
|
412
|
-
#Return the fractional part of angle as a string,
|
413
|
-
#to the number of decimal places specified by 'places'.
|
414
|
-
#No leading '0' is output. The string starts with a '.'
|
415
|
-
#If ploces is -1, then all decimal places are returned.
|
405
|
+
# Return the fractional part of angle as a string,
|
406
|
+
# to the number of decimal places specified by 'places'.
|
407
|
+
# No leading '0' is output. The string starts with a '.'
|
408
|
+
# If ploces is -1, then all decimal places are returned.
|
416
409
|
# @return [String]
|
417
410
|
# @param [Float] angle In radians
|
418
411
|
# @param [Fixnum] places Number of decimal places to output
|
419
|
-
def s_only_places(angle, places)
|
420
|
-
|
412
|
+
private def s_only_places(angle, places)
|
413
|
+
_angle_int, angle_dec = angle.abs.divmod(1)
|
421
414
|
s_places(angle_dec, places)
|
422
415
|
end
|
423
416
|
end
|
data/lib/coordinate.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
1
|
require_relative 'angle.rb'
|
3
2
|
|
4
|
-
#Holds the latitude, longitude, and the altitude for the coordinate
|
3
|
+
# Holds the latitude, longitude, and the altitude for the coordinate
|
5
4
|
class Coordinate
|
6
5
|
# @return [Latitude]
|
7
6
|
attr_accessor :latitude
|
@@ -10,17 +9,17 @@ class Coordinate
|
|
10
9
|
# @return [Numeric]
|
11
10
|
attr_accessor :altitude
|
12
11
|
|
13
|
-
#latitude and longitude can be Strings or Numeric, or anything else with to_radians and to_f
|
14
|
-
#latitude and longitude are in degrees unless radians == true (or set to :radians)
|
15
|
-
def initialize(latitude=0, longitude=0, altitude=0, radians = false)
|
16
|
-
@latitude = Latitude.new(latitude,radians)
|
17
|
-
@longitude = Longitude.new(longitude,radians)
|
12
|
+
# latitude and longitude can be Strings or Numeric, or anything else with to_radians and to_f
|
13
|
+
# latitude and longitude are in degrees unless radians == true (or set to :radians)
|
14
|
+
def initialize(latitude = 0, longitude = 0, altitude = 0, radians = false)
|
15
|
+
@latitude = Latitude.new(latitude, radians)
|
16
|
+
@longitude = Longitude.new(longitude, radians)
|
18
17
|
@altitude = altitude.to_f
|
19
18
|
end
|
20
19
|
|
21
20
|
# @return [String] Latitude longitude and altitude as a single space separated string.
|
22
21
|
def to_s
|
23
|
-
"#{@latitude
|
22
|
+
"#{@latitude} #{@longitude} #{@altitude}m"
|
24
23
|
end
|
25
24
|
|
26
25
|
# @return [Latitude, Longitude, Float] with members, latitude, longitude and altitude
|
@@ -32,6 +31,6 @@ class Coordinate
|
|
32
31
|
|
33
32
|
# @return [Hash] with keys :latitude, :longitude, and :altitude
|
34
33
|
def to_hash
|
35
|
-
{ :
|
34
|
+
{ latitude: @latitude, longitude: @longitude, altitude: @altitude }
|
36
35
|
end
|
37
36
|
end
|