geo_units 0.2.6 → 0.3.1
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/.rspec +1 -1
- data/Gemfile +1 -0
- data/README.textile +15 -0
- data/VERSION +1 -1
- data/geo_units.gemspec +21 -5
- data/lib/geo_units.rb +48 -19
- data/lib/geo_units/constants.rb +5 -17
- data/lib/geo_units/converter.rb +11 -55
- data/lib/geo_units/converter/dms.rb +112 -0
- data/lib/geo_units/converter/normalizer.rb +52 -0
- data/lib/geo_units/converter/units.rb +41 -0
- data/lib/geo_units/core_ext.rb +60 -25
- data/lib/geo_units/maps.rb +6 -58
- data/lib/geo_units/maps/earth.rb +49 -0
- data/lib/geo_units/maps/meters.rb +25 -0
- data/lib/geo_units/numeric.rb +50 -0
- data/lib/geo_units/numeric/dms.rb +18 -0
- data/lib/geo_units/numeric/normalizer.rb +62 -0
- data/spec/geo_units/{dms_converter_spec.rb → converter/dms_spec.rb} +5 -5
- data/spec/geo_units/converter/normalizer_spec.rb +0 -0
- data/spec/geo_units/converter/units_spec.rb +0 -0
- data/spec/geo_units/converter_spec.rb +7 -7
- data/spec/geo_units/core_ext_spec.rb +62 -7
- data/spec/geo_units/maps/earth_spec.rb +25 -0
- data/spec/geo_units/maps/meters_spec.rb +24 -0
- data/spec/geo_units/maps_spec.rb +25 -0
- data/spec/geo_units/numeric/dms_spec.rb +0 -0
- data/spec/geo_units/numeric/normalizer_spec.rb +0 -0
- data/spec/geo_units/numeric_spec.rb +21 -0
- data/spec/geo_units_spec.rb +7 -1
- metadata +35 -6
- data/lib/geo_units/dms_converter.rb +0 -107
- data/lib/geo_units/numeric_ext.rb +0 -117
- data/spec/geo_units/numeric_ext_spec.rb +0 -12
data/.rspec
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--color
|
1
|
+
--color --format nested
|
data/Gemfile
CHANGED
data/README.textile
CHANGED
@@ -15,6 +15,21 @@ Then run the bundler!
|
|
15
15
|
|
16
16
|
@$ bundle@
|
17
17
|
|
18
|
+
h2. Status update (Sept 21, 2011)
|
19
|
+
|
20
|
+
GeoUnits is currently undergoing a major refactoring effort in order to group functionality in a more granular fashion, to allow for greater flexibility.
|
21
|
+
Also, the new GeoUnits will not specifically target use for geo calculations for Earth, but also other globes/worlds, such as in a fantasy setting, planets, suns etc.
|
22
|
+
Please help in this effort :)
|
23
|
+
|
24
|
+
The master branch has now been updated in order to allow specification of the order:
|
25
|
+
Set the `GeoUnit.default_coords_order` to fit your usage scenario.
|
26
|
+
|
27
|
+
`GeoUnit.default_coords_order = :lng_lat`
|
28
|
+
|
29
|
+
`GeoUnit.default_coords_order = :lat_lng`
|
30
|
+
|
31
|
+
All specs pass again and the dependencies have been updated :)
|
32
|
+
|
18
33
|
h2. GeoUnits API
|
19
34
|
|
20
35
|
<pre>GeoUnits.key(:foot) # will convert any kind of unit into one of (:feet, :meters, :kms, :miles, :radians)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
data/geo_units.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "geo_units"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kristian Mandrup"]
|
@@ -28,15 +28,28 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/geo_units.rb",
|
29
29
|
"lib/geo_units/constants.rb",
|
30
30
|
"lib/geo_units/converter.rb",
|
31
|
+
"lib/geo_units/converter/dms.rb",
|
32
|
+
"lib/geo_units/converter/normalizer.rb",
|
33
|
+
"lib/geo_units/converter/units.rb",
|
31
34
|
"lib/geo_units/core_ext.rb",
|
32
|
-
"lib/geo_units/dms_converter.rb",
|
33
35
|
"lib/geo_units/maps.rb",
|
34
|
-
"lib/geo_units/
|
36
|
+
"lib/geo_units/maps/earth.rb",
|
37
|
+
"lib/geo_units/maps/meters.rb",
|
38
|
+
"lib/geo_units/numeric.rb",
|
39
|
+
"lib/geo_units/numeric/dms.rb",
|
40
|
+
"lib/geo_units/numeric/normalizer.rb",
|
35
41
|
"lib/geo_units/unit_conversions.rb",
|
42
|
+
"spec/geo_units/converter/dms_spec.rb",
|
43
|
+
"spec/geo_units/converter/normalizer_spec.rb",
|
44
|
+
"spec/geo_units/converter/units_spec.rb",
|
36
45
|
"spec/geo_units/converter_spec.rb",
|
37
46
|
"spec/geo_units/core_ext_spec.rb",
|
38
|
-
"spec/geo_units/
|
39
|
-
"spec/geo_units/
|
47
|
+
"spec/geo_units/maps/earth_spec.rb",
|
48
|
+
"spec/geo_units/maps/meters_spec.rb",
|
49
|
+
"spec/geo_units/maps_spec.rb",
|
50
|
+
"spec/geo_units/numeric/dms_spec.rb",
|
51
|
+
"spec/geo_units/numeric/normalizer_spec.rb",
|
52
|
+
"spec/geo_units/numeric_spec.rb",
|
40
53
|
"spec/geo_units_spec.rb",
|
41
54
|
"spec/spec_helper.rb"
|
42
55
|
]
|
@@ -51,6 +64,7 @@ Gem::Specification.new do |s|
|
|
51
64
|
|
52
65
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
53
66
|
s.add_runtime_dependency(%q<sugar-high>, [">= 0.6.0"])
|
67
|
+
s.add_runtime_dependency(%q<sweetloader>, [">= 0"])
|
54
68
|
s.add_runtime_dependency(%q<i18n>, [">= 0"])
|
55
69
|
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
56
70
|
s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
|
@@ -58,6 +72,7 @@ Gem::Specification.new do |s|
|
|
58
72
|
s.add_development_dependency(%q<jeweler>, [">= 1.6.4"])
|
59
73
|
else
|
60
74
|
s.add_dependency(%q<sugar-high>, [">= 0.6.0"])
|
75
|
+
s.add_dependency(%q<sweetloader>, [">= 0"])
|
61
76
|
s.add_dependency(%q<i18n>, [">= 0"])
|
62
77
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
63
78
|
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
@@ -66,6 +81,7 @@ Gem::Specification.new do |s|
|
|
66
81
|
end
|
67
82
|
else
|
68
83
|
s.add_dependency(%q<sugar-high>, [">= 0.6.0"])
|
84
|
+
s.add_dependency(%q<sweetloader>, [">= 0"])
|
69
85
|
s.add_dependency(%q<i18n>, [">= 0"])
|
70
86
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
71
87
|
s.add_dependency(%q<rspec>, [">= 2.5.0"])
|
data/lib/geo_units.rb
CHANGED
@@ -16,34 +16,63 @@
|
|
16
16
|
# @throws ArgumentError
|
17
17
|
|
18
18
|
require 'sugar-high/numeric'
|
19
|
-
require '
|
19
|
+
require 'sweetloader'
|
20
20
|
|
21
21
|
module GeoUnits
|
22
|
-
autoload_modules :
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
autoload_modules :Constants, :Converter, :Maps, :Numeric
|
23
|
+
|
24
|
+
class << self
|
25
|
+
attr_accessor :default_coords_order
|
26
|
+
|
27
|
+
def default_coords_order
|
28
|
+
@default_coords_order ||= :lng_lat
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.included(base)
|
33
|
+
[:Maps, :Constants, :"Converter::Units"].each do |module_name|
|
34
|
+
module_name = "GeoUnits::#{module_name.to_s.camelize}".constantize
|
26
35
|
base.send :include, module_name
|
27
|
-
base.extend module_name
|
36
|
+
base.extend module_name
|
28
37
|
end
|
29
38
|
end
|
30
39
|
|
31
40
|
def self.units
|
32
|
-
[:feet, :meters, :kms, :miles, :radians]
|
41
|
+
[:feet, :meters, :kms, :kilometers, :miles, :radians]
|
33
42
|
end
|
34
43
|
|
35
|
-
units.each do |
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
(units - [:radians]).each do |unit_type|
|
45
|
+
define_singleton_method "#{unit_type}_to" do |unit, number = 0|
|
46
|
+
return 0 if number <= 0
|
47
|
+
unit = normalized(unit)
|
48
|
+
|
49
|
+
converter = GeoUnits::Maps::Meters
|
50
|
+
from = converter.from_unit[unit_type]
|
51
|
+
to = converter.to_unit[unit]
|
52
|
+
|
53
|
+
m = number * from * to
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.radians_to unit, number, lat = 0
|
58
|
+
unit = normalized(unit)
|
59
|
+
# factor = GeoUnits::Converter::Units.units_per_longitude_degree(lat, unit)
|
60
|
+
# puts "factor: #{factor} - #{unit}"
|
61
|
+
(GeoUnits::Maps::Earth.distance_per_latitude_degree[unit] * number.to_f)
|
44
62
|
end
|
45
63
|
|
46
64
|
module ClassMethods
|
65
|
+
def normalized unit = :km
|
66
|
+
unit = key(unit)
|
67
|
+
return :feet if feet_unit.include? unit
|
68
|
+
return :meters if meters_unit.include? unit
|
69
|
+
return :kilometers if kms_unit.include? unit
|
70
|
+
return :miles if miles_unit.include? unit
|
71
|
+
return :radians if radins_unit.include? unit
|
72
|
+
|
73
|
+
raise ArgumentError, "Normalize unit error, unit key: #{unit}"
|
74
|
+
end
|
75
|
+
|
47
76
|
def key unit = :km
|
48
77
|
unit = unit.to_sym
|
49
78
|
methods.grep(/_unit$/).each do |meth|
|
@@ -76,11 +105,11 @@ module GeoUnits
|
|
76
105
|
|
77
106
|
def radians_unit
|
78
107
|
[:rad, :radians]
|
79
|
-
end
|
108
|
+
end
|
80
109
|
end
|
81
|
-
|
110
|
+
|
82
111
|
extend ClassMethods
|
83
|
-
end
|
112
|
+
end
|
84
113
|
|
85
114
|
require 'geo_units/core_ext'
|
86
115
|
|
data/lib/geo_units/constants.rb
CHANGED
@@ -4,30 +4,18 @@ module GeoUnits
|
|
4
4
|
Math::PI / 180.0
|
5
5
|
end
|
6
6
|
|
7
|
-
def pi_div_rad
|
7
|
+
def pi_div_rad
|
8
8
|
0.0174
|
9
9
|
end
|
10
10
|
|
11
|
-
def kms_per_mile
|
11
|
+
def kms_per_mile
|
12
12
|
1.609
|
13
13
|
end
|
14
14
|
|
15
|
-
def meters_per_feet
|
15
|
+
def meters_per_feet
|
16
16
|
3.2808399
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
69.1
|
21
|
-
end
|
22
|
-
|
23
|
-
def kms_per_latitude_degree
|
24
|
-
miles_per_latitude_degree * kms_per_mile
|
25
|
-
end
|
26
|
-
|
27
|
-
def latitude_degrees
|
28
|
-
earth_radius_map[:miles] / miles_per_latitude_degree
|
29
|
-
end
|
30
|
-
|
31
|
-
extend self
|
19
|
+
extend self
|
32
20
|
end
|
33
|
-
end
|
21
|
+
end
|
data/lib/geo_units/converter.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module GeoUnits
|
2
2
|
module Converter
|
3
|
+
autoload_modules :Normalizer, :Dms, :Units
|
4
|
+
|
5
|
+
include Normalizer
|
6
|
+
|
3
7
|
# Convert numeric degrees to deg/min/sec latitude (suffixed with N/S)
|
4
8
|
#
|
5
9
|
# @param {Number} deg: Degrees
|
@@ -9,7 +13,7 @@ module GeoUnits
|
|
9
13
|
|
10
14
|
def to_lat deg, format = :dms, dp = 0
|
11
15
|
deg = deg.normalize_lat
|
12
|
-
_lat =
|
16
|
+
_lat = Dms.to_dms deg, format, dp
|
13
17
|
_lat == '' ? '' : _lat[1..-1] + (deg<0 ? 'S' : 'N') # knock off initial '0' for lat!
|
14
18
|
end
|
15
19
|
|
@@ -22,7 +26,7 @@ module GeoUnits
|
|
22
26
|
|
23
27
|
def to_lon deg, format = :dms, dp = 0
|
24
28
|
deg = deg.normalize_lng
|
25
|
-
lon =
|
29
|
+
lon = Dms.to_dms deg, format, dp
|
26
30
|
lon == '' ? '' : lon + (deg<0 ? 'W' : 'E')
|
27
31
|
end
|
28
32
|
|
@@ -36,14 +40,12 @@ module GeoUnits
|
|
36
40
|
|
37
41
|
def to_brng deg, format = :dms, dp = 0
|
38
42
|
deg = (deg.to_f + 360) % 360 # normalise -ve values to 180º..360º
|
39
|
-
brng =
|
43
|
+
brng = Dms.to_dms deg, format, dp
|
40
44
|
brng.gsub /360/, '0' # just in case rounding took us up to 360º!
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
45
|
+
end
|
44
46
|
|
45
47
|
include NumericCheckExt # from sugar-high/numeric
|
46
|
-
|
48
|
+
|
47
49
|
# Converts numeric degrees to radians
|
48
50
|
def to_rad degrees
|
49
51
|
degrees * Math::PI / 180
|
@@ -67,54 +69,8 @@ module GeoUnits
|
|
67
69
|
alias_method :as_degrees, :to_deg
|
68
70
|
alias_method :in_deg, :to_deg
|
69
71
|
alias_method :in_degrees, :to_deg
|
70
|
-
|
71
|
-
extend self
|
72
|
-
end
|
73
72
|
|
74
|
-
|
75
|
-
def normalize_lng deg
|
76
|
-
case deg
|
77
|
-
when -360..-180
|
78
|
-
deg % 180
|
79
|
-
when -180..0
|
80
|
-
-180 + (deg % 180)
|
81
|
-
when 0..180
|
82
|
-
deg
|
83
|
-
when 180..360
|
84
|
-
deg % 180
|
85
|
-
else
|
86
|
-
raise ArgumentError, "Degrees #{deg} out of range, must be between -360 to 360"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# all degrees between -90 and 90
|
91
|
-
def normalize_lat deg
|
92
|
-
case deg
|
93
|
-
when -360..-270
|
94
|
-
deg % 90
|
95
|
-
when -270..-180
|
96
|
-
90 - (deg % 90)
|
97
|
-
when -180..-90
|
98
|
-
- (deg % 90)
|
99
|
-
when -90..0
|
100
|
-
-90 + (deg % 90)
|
101
|
-
when 0..90
|
102
|
-
deg
|
103
|
-
when 90..180
|
104
|
-
deg % 90
|
105
|
-
when 180..270
|
106
|
-
- (deg % 90)
|
107
|
-
when 270..360
|
108
|
-
- 90 + (deg % 90)
|
109
|
-
else
|
110
|
-
raise ArgumentError, "Degrees #{deg} out of range, must be between -360 to 360"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def normalize_deg degrees, shift = 0
|
115
|
-
(degrees + shift) % 360
|
73
|
+
extend self
|
116
74
|
end
|
117
|
-
alias_method :normalize_degrees, :normalize_deg
|
118
|
-
|
119
75
|
extend self
|
120
|
-
end
|
76
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'sugar-high/numeric'
|
2
|
+
require 'sugar-high/string'
|
3
|
+
|
4
|
+
module GeoUnits
|
5
|
+
module Converter
|
6
|
+
module Dms
|
7
|
+
include NumericCheckExt
|
8
|
+
|
9
|
+
def parse_dms dms_str, options= {}
|
10
|
+
# check for signed decimal degrees without NSEW, if so return it directly
|
11
|
+
return dms_str if is_numeric?(dms_str)
|
12
|
+
|
13
|
+
raise "DMS parse error: #{dms_str}" if !(dms_str =~ /[NSEW]$/) || (dms_str =~ /\./)
|
14
|
+
|
15
|
+
# strip off any sign or compass dir'n & split out separate d/m/s
|
16
|
+
dms = dms_str.strip.gsub(/^-/,'').gsub(/[NSEW]$/i,'').split(/[^0-9.,]+/).map(&:strip).map(&:to_f)
|
17
|
+
return nil if dms.empty?
|
18
|
+
|
19
|
+
# and convert to decimal degrees...
|
20
|
+
deg = case dms.length
|
21
|
+
when 3 # interpret 3-part result as d/m/s
|
22
|
+
dms[0]/1 + dms[1]/60 + dms[2]/3600
|
23
|
+
when 2 # interpret 2-part result as d/m
|
24
|
+
dms[0]/1 + dms[1]/60
|
25
|
+
when 1 # just d (possibly decimal) or non-separated dddmmss
|
26
|
+
d = dms[0];
|
27
|
+
# check for fixed-width unseparated format eg 0033709W
|
28
|
+
d = "0#{d}" if (/[NS]/i.match(dms_str)) # - normalise N/S to 3-digit degrees
|
29
|
+
d = "#{d.slice(0,3)/1}#{deg.slice(3,5)/60}#{deg.slice(5)/3600}" if (/[0-9]{7}/.match(deg))
|
30
|
+
d
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
raise "DMS parse error: #{deg} for #{dms_str}" if !deg
|
36
|
+
|
37
|
+
deg = (deg * -1) if (/^-|[WS]$/i.match(dms_str.strip)) # take '-', west and south as -ve
|
38
|
+
deg.to_f
|
39
|
+
end
|
40
|
+
|
41
|
+
# Convert decimal degrees to deg/min/sec format
|
42
|
+
# - degree, prime, double-prime symbols are added, but sign is discarded, though no compass
|
43
|
+
# direction is added
|
44
|
+
#
|
45
|
+
#
|
46
|
+
# @param {Number} deg: Degrees
|
47
|
+
# @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'
|
48
|
+
# @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d
|
49
|
+
# @returns {String} deg formatted as deg/min/secs according to specified format
|
50
|
+
# @throws {TypeError} deg is an object, perhaps DOM object without .value?
|
51
|
+
|
52
|
+
def to_dms deg, format = :dms, dp = nil
|
53
|
+
deg = begin
|
54
|
+
deg.to_f
|
55
|
+
rescue
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
return nil if !deg # give up here if we can't make a number from deg
|
59
|
+
|
60
|
+
# default values
|
61
|
+
format ||= :dms
|
62
|
+
dp = if dp.nil?
|
63
|
+
case format.to_sym
|
64
|
+
when :d
|
65
|
+
4
|
66
|
+
when :dm
|
67
|
+
2
|
68
|
+
else
|
69
|
+
0 # default
|
70
|
+
end
|
71
|
+
end
|
72
|
+
dp ||= 0
|
73
|
+
|
74
|
+
deg = deg.abs # (unsigned result ready for appending compass dir'n)
|
75
|
+
|
76
|
+
case format
|
77
|
+
when :d
|
78
|
+
d = deg.round(dp) # round degrees
|
79
|
+
ds = "0#{d}" if (d <100) # pad with leading zeros
|
80
|
+
ds = "0#{ds}" if (d <10)
|
81
|
+
dms = ds.to_s.concats("\u00B0") # add º symbol
|
82
|
+
when :dm
|
83
|
+
min = (deg*60).round(dp) # convert degrees to minutes & round
|
84
|
+
d = d.to_i
|
85
|
+
d = (min / 60).floor # get component deg/min
|
86
|
+
m = (min % 60).round(dp) # pad with trailing zeros
|
87
|
+
ds = d
|
88
|
+
ms = m
|
89
|
+
ds = "0#{d}" if (d<100) # pad with leading zeros
|
90
|
+
ds = "0#{d}" if (d<10)
|
91
|
+
ms = "0#{m}" if (m<10)
|
92
|
+
dms = ds.to_s.concats("\u00B0", ms, "\u2032") # add º, ' symbols
|
93
|
+
when :dms
|
94
|
+
sec = (deg * 3600).round # convert degrees to seconds & round
|
95
|
+
d = (sec / 3600).floor # get component deg/min/sec
|
96
|
+
m = ((sec / 60) % 60).floor
|
97
|
+
s = (sec % 60).round(dp) # pad with trailing zeros
|
98
|
+
ds = d
|
99
|
+
ms = m
|
100
|
+
ss = s
|
101
|
+
ds = "0#{d}" if (d < 100) # pad with leading zeros
|
102
|
+
ds = "0#{ds}" if (d < 10)
|
103
|
+
ms = "0#{m}" if (m < 10)
|
104
|
+
ss = "0#{s}" if (s < 10)
|
105
|
+
dms = ds.to_s.concats("\u00B0", ms, "\u2032", ss, "\u2033") # add º, ', " symbols
|
106
|
+
end
|
107
|
+
return dms
|
108
|
+
end
|
109
|
+
extend self
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|