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
@@ -0,0 +1,52 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Converter
|
3
|
+
module Normalizer
|
4
|
+
# all degrees between -180 and 180
|
5
|
+
def normalize_lng deg
|
6
|
+
case deg
|
7
|
+
when -360..-180
|
8
|
+
deg % 180
|
9
|
+
when -180..0
|
10
|
+
-180 + (deg % 180)
|
11
|
+
when 0..180
|
12
|
+
deg
|
13
|
+
when 180..360
|
14
|
+
deg % 180
|
15
|
+
else
|
16
|
+
raise ArgumentError, "Degrees #{deg} out of range, must be between -360 to 360"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# all degrees between -90 and 90
|
21
|
+
def normalize_lat deg
|
22
|
+
case deg
|
23
|
+
when -360..-270
|
24
|
+
deg % 90
|
25
|
+
when -270..-180
|
26
|
+
90 - (deg % 90)
|
27
|
+
when -180..-90
|
28
|
+
- (deg % 90)
|
29
|
+
when -90..0
|
30
|
+
-90 + (deg % 90)
|
31
|
+
when 0..90
|
32
|
+
deg
|
33
|
+
when 90..180
|
34
|
+
deg % 90
|
35
|
+
when 180..270
|
36
|
+
- (deg % 90)
|
37
|
+
when 270..360
|
38
|
+
- 90 + (deg % 90)
|
39
|
+
else
|
40
|
+
raise ArgumentError, "Degrees #{deg} out of range, must be between -360 to 360"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def normalize_deg degrees, shift = 0
|
45
|
+
(degrees + shift) % 360
|
46
|
+
end
|
47
|
+
alias_method :normalize_degrees, :normalize_deg
|
48
|
+
|
49
|
+
extend self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Converter
|
3
|
+
module Units
|
4
|
+
def degrees_to_radians(degrees)
|
5
|
+
degrees.to_f * GeoUnits::Constants.radians_per_degree
|
6
|
+
end
|
7
|
+
|
8
|
+
def units_sphere_multiplier(units)
|
9
|
+
units = GeoUnits.key units
|
10
|
+
GeoUnits::Mapsearth_radius_map[units]
|
11
|
+
end
|
12
|
+
|
13
|
+
def units_per_latitude_degree(units)
|
14
|
+
units = GeoUnits.key units
|
15
|
+
GeoUnits::Maps.radian_multiplier[units]
|
16
|
+
end
|
17
|
+
|
18
|
+
def pi_div_rad
|
19
|
+
GeoUnits::Constants.pi_div_rad
|
20
|
+
end
|
21
|
+
|
22
|
+
def units_per_longitude_degree(lat, units)
|
23
|
+
miles_per_longitude_degree = (lat * Math.cos(lat * pi_div_rad)).abs
|
24
|
+
units = GeoUnits.key units
|
25
|
+
miles_per_longitude_degree.miles_to(units)
|
26
|
+
end
|
27
|
+
|
28
|
+
def earth_radius units
|
29
|
+
units = GeoUnits.key units
|
30
|
+
GeoUnits::Maps.earth_radius_map[units]
|
31
|
+
end
|
32
|
+
|
33
|
+
def radians_ratio units
|
34
|
+
units = GeoUnits.key units
|
35
|
+
radians_per_degree * earth_radius(units)
|
36
|
+
end
|
37
|
+
|
38
|
+
extend self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/geo_units/core_ext.rb
CHANGED
@@ -1,43 +1,78 @@
|
|
1
1
|
require 'sugar-high/numeric'
|
2
2
|
|
3
3
|
module GeoUnitExt
|
4
|
-
::GeoUnits.units.each do |
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
}
|
4
|
+
::GeoUnits.units.each do |unit_type|
|
5
|
+
define_method "#{unit_type}_to" do |unit|
|
6
|
+
unit = GeoUnits.normalized(unit)
|
7
|
+
self.to_f * GeoUnits::Maps::Meters.from_unit[unit_type] * GeoUnits::Maps::Meters.to_unit[unit]
|
8
|
+
end
|
11
9
|
end
|
12
10
|
|
13
11
|
include NumberDslExt # from sugar-high
|
14
12
|
|
15
|
-
def
|
16
|
-
|
17
|
-
end
|
18
|
-
alias_method :to_radians, :
|
13
|
+
def to_rad
|
14
|
+
GeoUnits::Converter.to_rad self
|
15
|
+
end
|
16
|
+
alias_method :to_radians, :to_rad
|
17
|
+
alias_method :degrees_to_rad, :to_radians
|
18
|
+
alias_method :deg_to_rad, :to_radians
|
19
19
|
end
|
20
20
|
|
21
|
-
class
|
21
|
+
class Numeric
|
22
22
|
include GeoUnitExt
|
23
|
-
include ::GeoUnits::
|
23
|
+
include ::GeoUnits::Numeric
|
24
|
+
include ::GeoUnits::Numeric::Dms
|
25
|
+
include ::GeoUnits::Numeric::Normalizer
|
24
26
|
end
|
25
27
|
|
26
|
-
class
|
27
|
-
|
28
|
-
|
29
|
-
end
|
28
|
+
class String
|
29
|
+
def parse_dms options = {}
|
30
|
+
GeoUnits::Converter::Dms.parse_dms self, options
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_lng
|
34
|
+
self.match(/[E|W]/) ? self.to_i : nil
|
35
|
+
end
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
GeoUnits::DmsConverter.parse_dms self
|
37
|
+
def to_lat
|
38
|
+
self.match(/[N|S]/) ? self.to_i : nil
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
37
42
|
class Array
|
38
|
-
def to_dms
|
39
|
-
lat =
|
40
|
-
|
41
|
-
|
43
|
+
def to_dms direction = nil
|
44
|
+
lng, lat = extract_coords(direction)
|
45
|
+
res = direction == :lat_lng ? [lat.to_lat_dms, lng.to_lng_dms] : [lng.to_lng_dms, lat.to_lat_dms]
|
46
|
+
res.join(', ')
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_dms direction = nil
|
50
|
+
lng, lat = extract_coords(direction)
|
51
|
+
direction == :lat_lng ? [lat.parse_dms, lng.parse_dms] : [lng.parse_dms, lat.parse_dms]
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def extract_coords direction = nil
|
57
|
+
direction ||= GeoUnits.default_coords_order
|
58
|
+
|
59
|
+
unless [:lng_lat, :lat_lng].include? direction
|
60
|
+
raise ArgumentError, "Direction must be either :lng_lat or :lat_lng, was: #{direction}. You can also set the default direction via GeoUnits#default_direction="
|
61
|
+
end
|
62
|
+
|
63
|
+
lat_index = direction == :reverse ? 0 : 1
|
64
|
+
lng_index = direction == :reverse ? 1 : 0
|
65
|
+
|
66
|
+
lat = self.to_lat if self.respond_to?(:to_lat)
|
67
|
+
lat ||= self[lat_index] if self[lat_index].respond_to?(:to_lat) && self[lat_index].to_lat
|
68
|
+
lat ||= self[lng_index] if self[lng_index].respond_to?(:to_lat) && self[lng_index].to_lat
|
69
|
+
lat ||= self[lat_index]
|
70
|
+
|
71
|
+
lng = self.to_lng if self.respond_to?(:to_lng)
|
72
|
+
lng ||= self[lng_index] if self[lng_index].respond_to?(:to_lng) && self[lng_index].to_lng
|
73
|
+
lng ||= self[lat_index] if self[lat_index].respond_to?(:to_lng) && self[lat_index].to_lng
|
74
|
+
lng ||= self[lng_index]
|
75
|
+
|
76
|
+
[lng, lat]
|
42
77
|
end
|
43
|
-
end
|
78
|
+
end
|
data/lib/geo_units/maps.rb
CHANGED
@@ -1,61 +1,10 @@
|
|
1
1
|
module GeoUnits
|
2
2
|
module Maps
|
3
|
-
|
4
|
-
{
|
5
|
-
:miles => 3963.1676,
|
6
|
-
:kilometers => 6378.135,
|
7
|
-
:meters => 6378135,
|
8
|
-
:feet => 20925639.8
|
9
|
-
}
|
10
|
-
end
|
11
|
-
|
12
|
-
def earth_major_axis_radius_map
|
13
|
-
{
|
14
|
-
:miles => 3963.19059,
|
15
|
-
:kilometers => 6378.137,
|
16
|
-
:meters => 6378137,
|
17
|
-
:feet => 20925646.36
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
def earth_minor_axis_radius_map
|
22
|
-
{
|
23
|
-
:kilometers => 6356.7523142,
|
24
|
-
:miles => 3949.90276,
|
25
|
-
:meters => 6356752.3142,
|
26
|
-
:feet => 20855486.627
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
# from mongoid-geo, as suggested by niedhui :)
|
31
|
-
def radian_multiplier
|
32
|
-
{
|
33
|
-
:feet => 364491.8,
|
34
|
-
:meters => 111170,
|
35
|
-
:kms => 111.17,
|
36
|
-
:miles => 69.407,
|
37
|
-
:radians => 1
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
def meters_multiplier
|
42
|
-
{
|
43
|
-
:feet => 0.305,
|
44
|
-
:meters => 1,
|
45
|
-
:kms => 6371,
|
46
|
-
:miles => 3959,
|
47
|
-
:radians => 111170
|
48
|
-
}
|
49
|
-
end
|
3
|
+
autoload_modules :Earth, :Meters
|
50
4
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
:meters => 1,
|
55
|
-
:kms => 0.001,
|
56
|
-
:miles => 0.00062137,
|
57
|
-
:radians => 0.00000899
|
58
|
-
}
|
5
|
+
def self.included(base)
|
6
|
+
base.send :include, Earth
|
7
|
+
base.send :include, Meters
|
59
8
|
end
|
60
9
|
|
61
10
|
def precision
|
@@ -66,8 +15,7 @@ module GeoUnits
|
|
66
15
|
:miles => 4,
|
67
16
|
:radians => 4
|
68
17
|
}
|
69
|
-
end
|
70
|
-
|
18
|
+
end
|
71
19
|
extend self
|
72
20
|
end
|
73
|
-
end
|
21
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Maps
|
3
|
+
module Earth
|
4
|
+
# from mongoid-geo, as suggested by niedhui :)
|
5
|
+
def distance_per_latitude_degree
|
6
|
+
{
|
7
|
+
:feet => 364491.8,
|
8
|
+
:meters => 111170,
|
9
|
+
:kilometers => 111.17,
|
10
|
+
:miles => 69.407,
|
11
|
+
:degrees => 1
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def radius
|
16
|
+
{
|
17
|
+
:miles => 3963.1676,
|
18
|
+
:kilometers => 6378.135,
|
19
|
+
:meters => 6378135,
|
20
|
+
:feet => 20925639.8
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def major_axis_radius
|
25
|
+
{
|
26
|
+
:miles => 3963.19059,
|
27
|
+
:kilometers => 6378.137,
|
28
|
+
:meters => 6378137,
|
29
|
+
:feet => 20925646.36
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def minor_axis_radius
|
34
|
+
{
|
35
|
+
:kilometers => 6356.7523142,
|
36
|
+
:miles => 3949.90276,
|
37
|
+
:meters => 6356752.3142,
|
38
|
+
:feet => 20855486.627
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def latitude_degrees unit = :miles
|
43
|
+
radius[unit] / distance_per_latitude_degree[unit]
|
44
|
+
end
|
45
|
+
|
46
|
+
extend self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Maps
|
3
|
+
module Meters
|
4
|
+
def from_unit
|
5
|
+
{
|
6
|
+
:feet => 0.3048,
|
7
|
+
:meters => 1,
|
8
|
+
:kilometers => 1000,
|
9
|
+
:miles => 1609.344
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_unit
|
14
|
+
{
|
15
|
+
:feet => 3.2808399,
|
16
|
+
:meters => 1,
|
17
|
+
:kilometers => 0.001,
|
18
|
+
:miles => 0.00062137
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
extend self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Numeric
|
3
|
+
autoload_modules :Normalizer, :Dms
|
4
|
+
|
5
|
+
def to_lat
|
6
|
+
normalize_lat
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_lng
|
10
|
+
normalize_lng
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_between? lower, upper
|
14
|
+
(lower..upper).cover? self
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts numeric degrees to radians
|
18
|
+
def to_rad
|
19
|
+
self * Math::PI / 180
|
20
|
+
end
|
21
|
+
alias_method :to_radians, :to_rad
|
22
|
+
alias_method :as_rad, :to_rad
|
23
|
+
alias_method :as_radians, :to_rad
|
24
|
+
alias_method :in_rad, :to_rad
|
25
|
+
alias_method :in_radians, :to_rad
|
26
|
+
|
27
|
+
|
28
|
+
# Converts radians to numeric (signed) degrees
|
29
|
+
# latitude (north to south) from equator +90 up then -90 down (equator again) = 180 then 180 for south = 360 total
|
30
|
+
# longitude (west to east) east +180, west -180 = 360 total
|
31
|
+
def to_deg
|
32
|
+
self * 180 / Math::PI
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :to_degrees, :to_deg
|
36
|
+
alias_method :as_deg, :to_deg
|
37
|
+
alias_method :as_degrees, :to_deg
|
38
|
+
alias_method :in_deg, :to_deg
|
39
|
+
alias_method :in_degrees, :to_deg
|
40
|
+
|
41
|
+
# Formats the significant digits of a number, using only fixed-point notation (no exponential)
|
42
|
+
#
|
43
|
+
# @param {Number} precision: Number of significant digits to appear in the returned string
|
44
|
+
# @returns {String} A string representation of number which contains precision significant digits
|
45
|
+
def to_precision precision
|
46
|
+
self.round(precision).to_s
|
47
|
+
end
|
48
|
+
alias_method :to_fixed, :to_precision
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Numeric
|
3
|
+
module Dms
|
4
|
+
def to_dms format = :dms, dp = nil
|
5
|
+
GeoUnits::DmsConverter.to_dms self, format, dp
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_lat_dms format = :dms, dp = nil
|
9
|
+
GeoUnits::Converter.to_lat self, format, dp
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_lon_dms format = :dms, dp = nil
|
13
|
+
GeoUnits::Converter.to_lon self, format, dp
|
14
|
+
end
|
15
|
+
alias_method :to_lng_dms, :to_lon_dms
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GeoUnits
|
2
|
+
module Numeric
|
3
|
+
module Normalizer
|
4
|
+
# all degrees between -180 and 180
|
5
|
+
def normalize_lng
|
6
|
+
case self
|
7
|
+
when -360, 0, 360
|
8
|
+
0
|
9
|
+
when -360..-180
|
10
|
+
self % 180
|
11
|
+
when -180..0
|
12
|
+
-180 + (self % 180)
|
13
|
+
when 0..180
|
14
|
+
self
|
15
|
+
when 180..360
|
16
|
+
self % 180
|
17
|
+
else
|
18
|
+
return (self % 360).normalize_lng if self > 360
|
19
|
+
return (360 - (self % 360)).normalize_lng if self < -360
|
20
|
+
raise ArgumentError, "Degrees #{self} out of range"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# all degrees between -90 and 90
|
25
|
+
def normalize_lat
|
26
|
+
case self
|
27
|
+
when -360, 0, 360
|
28
|
+
0
|
29
|
+
when -180, 180
|
30
|
+
0
|
31
|
+
when -360..-270
|
32
|
+
self % 90
|
33
|
+
when -270..-180
|
34
|
+
90 - (self % 90)
|
35
|
+
when -180..-90
|
36
|
+
- (self % 90)
|
37
|
+
when -90..0
|
38
|
+
-90 + (self % 90)
|
39
|
+
when 0..90
|
40
|
+
self
|
41
|
+
when 90..180
|
42
|
+
self % 90
|
43
|
+
when 180..270
|
44
|
+
- (self % 90)
|
45
|
+
when 270..360
|
46
|
+
- 90 + (self % 90)
|
47
|
+
else
|
48
|
+
return (self % 360).normalize_lat if self > 360
|
49
|
+
return (360 - (self % 360)).normalize_lat if self < -360
|
50
|
+
raise ArgumentError, "Degrees #{self} out of range"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def normalize_deg shift = 0
|
55
|
+
(self + shift) % 360
|
56
|
+
end
|
57
|
+
alias_method :normalize_degrees, :normalize_deg
|
58
|
+
|
59
|
+
extend self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|