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.
@@ -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
@@ -1,43 +1,78 @@
1
1
  require 'sugar-high/numeric'
2
2
 
3
3
  module GeoUnitExt
4
- ::GeoUnits.units.each do |unit|
5
- class_eval %{
6
- def #{unit}_to unit
7
- unit = GeoUnits.key(unit)
8
- (self.to_f / GeoUnits.meters_map[:#{unit}]) * GeoUnits.meters_map[unit]
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 rpd
16
- self * GeoUnits.radians_per_degree
17
- end
18
- alias_method :to_radians, :rpd
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 Fixnum
21
+ class Numeric
22
22
  include GeoUnitExt
23
- include ::GeoUnits::NumericExt
23
+ include ::GeoUnits::Numeric
24
+ include ::GeoUnits::Numeric::Dms
25
+ include ::GeoUnits::Numeric::Normalizer
24
26
  end
25
27
 
26
- class Float
27
- include GeoUnitExt
28
- include ::GeoUnits::NumericExt
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
- class String
32
- def parse_dms
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 = self.respond_to?(:to_lat) ? self.to_lat : self[0]
40
- lng = self.respond_to?(:to_lng) ? self.to_lng : self[1]
41
- [lat.to_lat_dms, lng.to_lng_dms].join(', ')
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
@@ -1,61 +1,10 @@
1
1
  module GeoUnits
2
2
  module Maps
3
- def earth_radius_map
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 meters_map
52
- {
53
- :feet => 3.2808399,
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