geo_units 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+
4
+ gem "sugar-high", '~> 0.4.6.2'
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", ">= 2.5.0"
10
+ gem "bundler", "~> 1.0.6"
11
+ gem "jeweler", "~> 1.6.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Kristian Mandrup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,22 @@
1
+ h1. Geo Units
2
+
3
+ Distance unit functionality (conversions etc.) for Geo libraries. See specs for details.
4
+
5
+ This gem is used by the _geo_point_ and _geo_calc_ gems and perhaps by others. The aim is that it will contain most of the basic
6
+ distance unit functionality required by typical Geo projects.
7
+
8
+ h2. Contributing to geo_units
9
+
10
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
11
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
12
+ * Fork the project
13
+ * Start a feature/bugfix branch
14
+ * Commit and push until you are happy with your contribution
15
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
16
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
17
+
18
+ h2. Copyright
19
+
20
+ Copyright (c) 2011 Kristian Mandrup. See LICENSE.txt for
21
+ further details.
22
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "geo_units"
18
+ gem.homepage = "http://github.com/kristianmandrup/geo_units"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Distance unit modules and functionality for use in geo libraries}
21
+ gem.description = %Q{Easily convert between different distance units such as kms, miles etc.}
22
+ gem.email = "kmandrup@gmail.com"
23
+ gem.authors = ["Kristian Mandrup"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "geo_units #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/geo_units.gemspec ADDED
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{geo_units}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Kristian Mandrup}]
12
+ s.date = %q{2011-06-13}
13
+ s.description = %q{Easily convert between different distance units such as kms, miles etc.}
14
+ s.email = %q{kmandrup@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.textile"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.textile",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "geo_units.gemspec",
28
+ "lib/geo_units.rb",
29
+ "lib/geo_units/converter.rb",
30
+ "lib/geo_units/core_ext.rb",
31
+ "lib/geo_units/dms_converter.rb",
32
+ "lib/geo_units/numeric_ext.rb",
33
+ "spec/geo_units/converter_spec.rb",
34
+ "spec/geo_units/dms_converter_spec.rb",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/kristianmandrup/geo_units}
38
+ s.licenses = [%q{MIT}]
39
+ s.require_paths = [%q{lib}]
40
+ s.rubygems_version = %q{1.8.5}
41
+ s.summary = %q{Distance unit modules and functionality for use in geo libraries}
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<sugar-high>, ["~> 0.4.6.2"])
48
+ s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.6"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<sugar-high>, ["~> 0.4.6.2"])
54
+ s.add_dependency(%q<rspec>, [">= 2.5.0"])
55
+ s.add_dependency(%q<bundler>, ["~> 1.0.6"])
56
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
57
+ s.add_dependency(%q<rcov>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<sugar-high>, ["~> 0.4.6.2"])
61
+ s.add_dependency(%q<rspec>, [">= 2.5.0"])
62
+ s.add_dependency(%q<bundler>, ["~> 1.0.6"])
63
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
64
+ s.add_dependency(%q<rcov>, [">= 0"])
65
+ end
66
+ end
67
+
@@ -0,0 +1,120 @@
1
+ module GeoUnits
2
+ module Converter
3
+ # Convert numeric degrees to deg/min/sec latitude (suffixed with N/S)
4
+ #
5
+ # @param {Number} deg: Degrees
6
+ # @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'
7
+ # @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d
8
+ # @returns {String} Deg/min/seconds
9
+
10
+ def to_lat deg, format = :dms, dp = 0
11
+ deg = deg.normalize_lat
12
+ _lat = DmsConverter.to_dms deg, format, dp
13
+ _lat == '' ? '' : _lat[1..-1] + (deg<0 ? 'S' : 'N') # knock off initial '0' for lat!
14
+ end
15
+
16
+ # Convert numeric degrees to deg/min/sec longitude (suffixed with E/W)
17
+ #
18
+ # @param {Number} deg: Degrees
19
+ # @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'
20
+ # @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d
21
+ # @returns {String} Deg/min/seconds
22
+
23
+ def to_lon deg, format = :dms, dp = 0
24
+ deg = deg.normalize_lng
25
+ lon = DmsConverter.to_dms deg, format, dp
26
+ lon == '' ? '' : lon + (deg<0 ? 'W' : 'E')
27
+ end
28
+
29
+
30
+ # Convert numeric degrees to deg/min/sec as a bearing (0º..360º)
31
+ #
32
+ # @param {Number} deg: Degrees
33
+ # @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'
34
+ # @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d
35
+ # @returns {String} Deg/min/seconds
36
+
37
+ def to_brng deg, format = :dms, dp = 0
38
+ deg = (deg.to_f + 360) % 360 # normalise -ve values to 180º..360º
39
+ brng = DmsConverter.to_dms deg, format, dp
40
+ brng.gsub /360/, '0' # just in case rounding took us up to 360º!
41
+ end
42
+
43
+ protected
44
+
45
+ include NumericCheckExt # from sugar-high/numeric
46
+
47
+ # Converts numeric degrees to radians
48
+ def to_rad degrees
49
+ degrees * Math::PI / 180
50
+ end
51
+ alias_method :to_radians, :to_rad
52
+ alias_method :as_rad, :to_rad
53
+ alias_method :as_radians, :to_rad
54
+ alias_method :in_rad, :to_rad
55
+ alias_method :in_radians, :to_rad
56
+
57
+
58
+ # Converts radians to numeric (signed) degrees
59
+ # latitude (north to south) from equator +90 up then -90 down (equator again) = 180 then 180 for south = 360 total
60
+ # longitude (west to east) east +180, west -180 = 360 total
61
+ def to_deg radians
62
+ radians * 180 / Math::PI
63
+ end
64
+
65
+ alias_method :to_degrees, :to_deg
66
+ alias_method :as_deg, :to_deg
67
+ alias_method :as_degrees, :to_deg
68
+ alias_method :in_deg, :to_deg
69
+ alias_method :in_degrees, :to_deg
70
+
71
+ extend self
72
+ end
73
+
74
+ # all degrees between -180 and 180
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
116
+ end
117
+ alias_method :normalize_degrees, :normalize_deg
118
+
119
+ extend self
120
+ end
@@ -0,0 +1,13 @@
1
+ class Fixnum
2
+ include ::GeoUnits::NumericExt
3
+ end
4
+
5
+ class Float
6
+ include ::GeoUnits::NumericExt
7
+ end
8
+
9
+ class String
10
+ def parse_dms
11
+ GeoUnits::DmsConverter.parse_dms self
12
+ end
13
+ end
@@ -0,0 +1,107 @@
1
+ require 'sugar-high/numeric'
2
+ require 'sugar-high/string'
3
+
4
+ module GeoUnits
5
+ module DmsConverter
6
+ include NumericCheckExt
7
+
8
+ def parse_dms dms_str
9
+ # check for signed decimal degrees without NSEW, if so return it directly
10
+ return dms_str if is_numeric?(dms_str)
11
+
12
+ # strip off any sign or compass dir'n & split out separate d/m/s
13
+ dms = dms_str.strip.gsub(/^-/,'').gsub(/[NSEW]$/i,'').split(/[^0-9.,]+/).map(&:strip).map(&:to_f)
14
+ return nil if dms.empty?
15
+
16
+ # and convert to decimal degrees...
17
+ deg = case dms.length
18
+ when 3 # interpret 3-part result as d/m/s
19
+ dms[0]/1 + dms[1]/60 + dms[2]/3600
20
+ when 2 # interpret 2-part result as d/m
21
+ dms[0]/1 + dms[1]/60
22
+ when 1 # just d (possibly decimal) or non-separated dddmmss
23
+ d = dms[0];
24
+ # check for fixed-width unseparated format eg 0033709W
25
+ d = "0#{d}" if (/[NS]/i.match(dms_str)) # - normalise N/S to 3-digit degrees
26
+ d = "#{d.slice(0,3)/1}#{deg.slice(3,5)/60}#{deg.slice(5)/3600}" if (/[0-9]{7}/.match(deg))
27
+ d
28
+ else
29
+ nil
30
+ end
31
+ return nil if !deg
32
+ deg = (deg * -1) if (/^-|[WS]$/i.match(dms_str.strip)) # take '-', west and south as -ve
33
+ deg.to_f
34
+ end
35
+
36
+ # Convert decimal degrees to deg/min/sec format
37
+ # - degree, prime, double-prime symbols are added, but sign is discarded, though no compass
38
+ # direction is added
39
+ #
40
+ #
41
+ # @param {Number} deg: Degrees
42
+ # @param {String} [format=dms]: Return value as 'd', 'dm', 'dms'
43
+ # @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d
44
+ # @returns {String} deg formatted as deg/min/secs according to specified format
45
+ # @throws {TypeError} deg is an object, perhaps DOM object without .value?
46
+
47
+ def to_dms deg, format = :dms, dp = nil
48
+ deg = begin
49
+ deg.to_f
50
+ rescue
51
+ nil
52
+ end
53
+ return nil if !deg # give up here if we can't make a number from deg
54
+
55
+ # default values
56
+ format ||= :dms
57
+ dp = if dp.nil?
58
+ case format.to_sym
59
+ when :d
60
+ 4
61
+ when :dm
62
+ 2
63
+ else
64
+ 0 # default
65
+ end
66
+ end
67
+ dp ||= 0
68
+
69
+ deg = deg.abs # (unsigned result ready for appending compass dir'n)
70
+
71
+ case format
72
+ when :d
73
+ d = deg.round(dp) # round degrees
74
+ ds = "0#{d}" if (d <100) # pad with leading zeros
75
+ ds = "0#{ds}" if (d <10)
76
+ dms = ds.to_s.concat("\u00B0") # add º symbol
77
+ when :dm
78
+ min = (deg*60).round(dp) # convert degrees to minutes & round
79
+ d = d.to_i
80
+ d = (min / 60).floor # get component deg/min
81
+ m = (min % 60).round(dp) # pad with trailing zeros
82
+ ds = d
83
+ ms = m
84
+ ds = "0#{d}" if (d<100) # pad with leading zeros
85
+ ds = "0#{d}" if (d<10)
86
+ ms = "0#{m}" if (m<10)
87
+ dms = ds.to_s.concat("\u00B0", ms, "\u2032") # add º, ' symbols
88
+ when :dms
89
+ sec = (deg * 3600).round # convert degrees to seconds & round
90
+ d = (sec / 3600).floor # get component deg/min/sec
91
+ m = ((sec / 60) % 60).floor
92
+ s = (sec % 60).round(dp) # pad with trailing zeros
93
+ ds = d
94
+ ms = m
95
+ ss = s
96
+ ds = "0#{d}" if (d < 100) # pad with leading zeros
97
+ ds = "0#{ds}" if (d < 10)
98
+ ms = "0#{m}" if (m < 10)
99
+ ss = "0#{s}" if (s < 10)
100
+ dms = ds.to_s.concat("\u00B0", ms, "\u2032", ss, "\u2033") # add º, ', " symbols
101
+ end
102
+ return dms
103
+ end
104
+
105
+ extend self
106
+ end
107
+ end
@@ -0,0 +1,117 @@
1
+ module GeoUnits
2
+ module NumericExt
3
+ def to_lat
4
+ normalize_lat
5
+ end
6
+
7
+ def to_lng
8
+ normalize_lng
9
+ end
10
+
11
+ def is_between? lower, upper
12
+ (lower..upper).cover? self
13
+ end
14
+
15
+
16
+ def to_dms format = :dms, dp = nil
17
+ GeoCalc::DmsConverter.to_dms self, format, dp
18
+ end
19
+
20
+ def to_lat_dms format = :dms, dp = nil
21
+ GeoUnits::Converter.to_lat self, format, dp
22
+ end
23
+
24
+ def to_lon_dms format = :dms, dp = nil
25
+ GeoUnits::Converter.to_lon self, format, dp
26
+ end
27
+
28
+ # Converts numeric degrees to radians
29
+ def to_rad
30
+ self * Math::PI / 180
31
+ end
32
+ alias_method :to_radians, :to_rad
33
+ alias_method :as_rad, :to_rad
34
+ alias_method :as_radians, :to_rad
35
+ alias_method :in_rad, :to_rad
36
+ alias_method :in_radians, :to_rad
37
+
38
+
39
+ # Converts radians to numeric (signed) degrees
40
+ # latitude (north to south) from equator +90 up then -90 down (equator again) = 180 then 180 for south = 360 total
41
+ # longitude (west to east) east +180, west -180 = 360 total
42
+ def to_deg
43
+ self * 180 / Math::PI
44
+ end
45
+
46
+ alias_method :to_degrees, :to_deg
47
+ alias_method :as_deg, :to_deg
48
+ alias_method :as_degrees, :to_deg
49
+ alias_method :in_deg, :to_deg
50
+ alias_method :in_degrees, :to_deg
51
+
52
+
53
+ # Formats the significant digits of a number, using only fixed-point notation (no exponential)
54
+ #
55
+ # @param {Number} precision: Number of significant digits to appear in the returned string
56
+ # @returns {String} A string representation of number which contains precision significant digits
57
+ def to_precision precision
58
+ self.round(precision).to_s
59
+ end
60
+ alias_method :to_fixed, :to_precision
61
+
62
+ # all degrees between -180 and 180
63
+ def normalize_lng
64
+ case self
65
+ when -360, 0, 360
66
+ 0
67
+ when -360..-180
68
+ self % 180
69
+ when -180..0
70
+ -180 + (self % 180)
71
+ when 0..180
72
+ self
73
+ when 180..360
74
+ self % 180
75
+ else
76
+ return (self % 360).normalize_lng if self > 360
77
+ return (360 - (self % 360)).normalize_lng if self < -360
78
+ raise ArgumentError, "Degrees #{self} out of range"
79
+ end
80
+ end
81
+
82
+ # all degrees between -90 and 90
83
+ def normalize_lat
84
+ case self
85
+ when -360, 0, 360
86
+ 0
87
+ when -180, 180
88
+ 0
89
+ when -360..-270
90
+ self % 90
91
+ when -270..-180
92
+ 90 - (self % 90)
93
+ when -180..-90
94
+ - (self % 90)
95
+ when -90..0
96
+ -90 + (self % 90)
97
+ when 0..90
98
+ self
99
+ when 90..180
100
+ self % 90
101
+ when 180..270
102
+ - (self % 90)
103
+ when 270..360
104
+ - 90 + (self % 90)
105
+ else
106
+ return (self % 360).normalize_lat if self > 360
107
+ return (360 - (self % 360)).normalize_lat if self < -360
108
+ raise ArgumentError, "Degrees #{self} out of range"
109
+ end
110
+ end
111
+
112
+ def normalize_deg shift = 0
113
+ (self + shift) % 360
114
+ end
115
+ alias_method :normalize_degrees, :normalize_deg
116
+ end
117
+ end
data/lib/geo_units.rb ADDED
@@ -0,0 +1,101 @@
1
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2
+ # Geodesy representation conversion functions (c) Chris Veness 2002-2010
3
+ # - www.movable-type.co.uk/scripts/latlong.html
4
+ #
5
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6
+
7
+ # Parses string representing degrees/minutes/seconds into numeric degrees
8
+ #
9
+ # This is very flexible on formats, allowing signed decimal degrees, or deg-min-sec optionally
10
+ # suffixed by compass direction (NSEW). A variety of separators are accepted (eg 3º 37' 09"W)
11
+ # or fixed-width format without separators (eg 0033709W). Seconds and minutes may be omitted.
12
+ # (Note minimal validation is done).
13
+ #
14
+ # @param {String|Number} dmsStr: Degrees or deg/min/sec in variety of formats
15
+ # @returns {Number} Degrees as decimal number
16
+ # @throws ArgumentError
17
+
18
+ require 'sugar-high/numeric'
19
+
20
+ module GeoUnits
21
+ autoload :Converter, 'geo_units/converter'
22
+ autoload :DmsConverter, 'geo_units/dms_converter'
23
+ autoload :NumericExt, 'geo_units/numeric_ext'
24
+
25
+ module ClassMethods
26
+ def key unit = :km
27
+ unit = unit.to_sym
28
+ methods.grep(/_unit/).each do |meth|
29
+ return meth.to_s.chomp('_unit').to_sym if send(meth).include? unit
30
+ end
31
+ raise ArgumentError, "Unknown unit key: #{unit}"
32
+ end
33
+
34
+ def precision
35
+ {
36
+ :feet => 0,
37
+ :meters => 2,
38
+ :kms => 4,
39
+ :miles => 4,
40
+ :radians => 4
41
+ }
42
+ end
43
+
44
+ # from mongoid-geo, as suggested by niedhui :)
45
+ def radian_multiplier
46
+ {
47
+ :feet => 364491.8,
48
+ :meters => 111170,
49
+ :kms => 111.17,
50
+ :miles => 69.407,
51
+ :radians => 1
52
+ }
53
+ end
54
+
55
+ def meters_multiplier
56
+ {
57
+ :feet => 0.305,
58
+ :meters => 1,
59
+ :kms => 6371,
60
+ :miles => 3959
61
+ }
62
+ end
63
+
64
+ def meters_map
65
+ {
66
+ :feet => 3.2808,
67
+ :meters => 1,
68
+ :kms => 0.001,
69
+ :miles => 0.00062137,
70
+ :radians => 111170
71
+ }
72
+ end
73
+
74
+ protected
75
+
76
+ def feet_unit
77
+ [:ft, :feet, :foot]
78
+ end
79
+
80
+ def meters_unit
81
+ [:m, :meter, :meters]
82
+ end
83
+
84
+ def kms_unit
85
+ [:km, :kms, :kilometer, :kilometers]
86
+ end
87
+
88
+ def miles_unit
89
+ [:mil, :mile, :miles]
90
+ end
91
+
92
+ def radians_unit
93
+ [:rad, :radians]
94
+ end
95
+ end
96
+
97
+ extend ClassMethods
98
+ end
99
+
100
+ require 'geo_units/core_ext'
101
+
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ class Converter
4
+ include GeoUnits::Converter
5
+ end
6
+
7
+ def converter
8
+ Converter.new
9
+ end
10
+
11
+ # - www.movable-type.co.uk/scripts/latlong.html
12
+ describe GeoUnits::Converter do
13
+ # deg, format, dp
14
+ describe '#to_lat' do
15
+ it 'should convert 58.3 to a latitude String in North direction' do
16
+ str_lat = converter.to_lat(58.3)
17
+ str_lat.should be_a(String)
18
+ expr = Regexp.escape "58".concat("\u00B0", "18", "\u2032", "00", "\u2033", "N")
19
+ str_lat.should match expr
20
+ end
21
+
22
+ it 'should convert -58.3 to a latitude String in South direction' do
23
+ str_lat = converter.to_lat(-58.3)
24
+ str_lat.should be_a(String)
25
+ expr = Regexp.escape "58".concat("\u00B0", "18", "\u2032", "00", "\u2033", "S")
26
+ str_lat.should match expr
27
+ end
28
+ end
29
+
30
+ # deg, format, dp
31
+ describe '#to_lon' do
32
+ it 'should convert 58.3 to a longitude String' do
33
+ str_lat = converter.to_lon(58.3)
34
+ str_lat.should be_a(String)
35
+ expr = Regexp.escape "58".concat("\u00B0", "18", "\u2032", "00", "\u2033", "E")
36
+ str_lat.should match expr
37
+ end
38
+
39
+ it 'should convert 58.3 to a longitude String' do
40
+ str_lat = converter.to_lon(-58.3)
41
+ str_lat.should be_a(String)
42
+ expr = Regexp.escape "58".concat("\u00B0", "18", "\u2032", "00", "\u2033", "W")
43
+ str_lat.should match expr
44
+ end
45
+ end
46
+
47
+ # Convert numeric degrees to deg/min/sec as a bearing (0º..360º)
48
+ # deg, format, dp
49
+ describe '#to_brng' do
50
+ it 'should convert 58.3 to a longitude String' do
51
+ brng = converter.to_brng(-58.3)
52
+ brng.to_f.should be_between(0, 360)
53
+ expr = Regexp.escape "301".concat("\u00B0", "42", "\u2032", "00")
54
+ brng.should match expr
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ class Parser
4
+ include GeoUnits::DmsConverter
5
+ end
6
+
7
+ def parser
8
+ Parser.new
9
+ end
10
+
11
+ # - www.movable-type.co.uk/scripts/latlong.html
12
+ describe GeoUnits::DmsConverter do
13
+ # # @param {String|Number} dmsStr: Degrees or deg/min/sec in variety of formats
14
+ # @returns {Number} Degrees as decimal number
15
+ describe '#parse_dms' do
16
+ it 'should convert "58 38 38N" to a Float of degrees (58..59)' do
17
+ deg = parser.parse_dms("58 38 38N")
18
+ deg.should be_a(Float)
19
+ deg.should be_between(58, 59)
20
+ end
21
+
22
+ it 'should convert "01 38 38W" to a Float of degrees (1..2)' do
23
+ deg = parser.parse_dms("01 38 38W")
24
+ deg.should be_a(Float)
25
+ deg.should < 0
26
+ deg.should > -2
27
+ end
28
+
29
+ it 'should convert "005 38 E" to a Float of degrees (5..6)' do
30
+ deg = parser.parse_dms("005 38 E")
31
+ deg.should be_a(Float)
32
+ deg.should be_between(5, 6)
33
+ end
34
+ end
35
+
36
+ # deg, format = :dms, dp = 0
37
+ describe '#to_dms' do
38
+ it 'should convert 58.3 to a String in DMS format' do
39
+ dms = parser.to_dms(58.3)
40
+ dms.should be_a(String)
41
+ expr = Regexp.escape "058".concat("\u00B0", "18", "\u2032", "00", "\u2033")
42
+ dms.should match expr
43
+ end
44
+
45
+ it 'should convert 58.3 to a String in DM format' do
46
+ dm = parser.to_dms(58.3, :dm, 2)
47
+ dm.should be_a(String)
48
+ expr = Regexp.escape "058".concat("\u00B0", "18", "\u2032")
49
+ dm.should match expr
50
+ end
51
+
52
+ it 'should convert 58.3 to a String in D format' do
53
+ d = parser.to_dms(58.3, :d, 2)
54
+ d.should be_a(String)
55
+ m = Regexp.escape "058".concat("\u00B0")
56
+ d.should match m
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'geo_units'
3
+
4
+ RSpec.configure do |config|
5
+
6
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geo_units
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kristian Mandrup
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-13 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sugar-high
16
+ requirement: &2154936400 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.4.6.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2154936400
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2154935800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 2.5.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2154935800
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &2154935220 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.6
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2154935220
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &2154934640 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.2
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2154934640
58
+ - !ruby/object:Gem::Dependency
59
+ name: rcov
60
+ requirement: &2154934040 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2154934040
69
+ description: Easily convert between different distance units such as kms, miles etc.
70
+ email: kmandrup@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files:
74
+ - LICENSE.txt
75
+ - README.textile
76
+ files:
77
+ - .document
78
+ - .rspec
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.textile
82
+ - Rakefile
83
+ - VERSION
84
+ - geo_units.gemspec
85
+ - lib/geo_units.rb
86
+ - lib/geo_units/converter.rb
87
+ - lib/geo_units/core_ext.rb
88
+ - lib/geo_units/dms_converter.rb
89
+ - lib/geo_units/numeric_ext.rb
90
+ - spec/geo_units/converter_spec.rb
91
+ - spec/geo_units/dms_converter_spec.rb
92
+ - spec/spec_helper.rb
93
+ homepage: http://github.com/kristianmandrup/geo_units
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ segments:
107
+ - 0
108
+ hash: 2458043336653105499
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.5
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Distance unit modules and functionality for use in geo libraries
121
+ test_files: []