geo_swap 0.0.1 → 0.0.2

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/geo_swap.gemspec CHANGED
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_development_dependency 'rake', '10.0.3'
21
+ gem.add_development_dependency 'rspec', '2.12.0'
21
22
  end
@@ -0,0 +1,10 @@
1
+
2
+ module GeoSwap::Utilities
3
+
4
+ def degrees_to_radians(degrees)
5
+ degrees * (Math::PI / 180)
6
+ end
7
+
8
+ module_function :degrees_to_radians
9
+
10
+ end
@@ -1,3 +1,3 @@
1
1
  module GeoSwap
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,19 @@
1
+ module GeoSwap
2
+ class Zone
3
+ def initialize(longitude)
4
+ @longitude = longitude.to_f
5
+ end
6
+
7
+ def number
8
+ @number ||= begin
9
+ number = ((@longitude + 180.0) / 6.0).floor + 1
10
+ #special case for longitude 180.0
11
+ (number > 60) ? 60 : number
12
+ end
13
+ end
14
+
15
+ def origin
16
+ @origin ||= ((number - 1) * 6) - 177
17
+ end
18
+ end
19
+ end
data/lib/geo_swap.rb CHANGED
@@ -1,5 +1,74 @@
1
1
  require "geo_swap/version"
2
+ require 'geo_swap/zone'
3
+ require 'geo_swap/utilities'
2
4
 
3
5
  module GeoSwap
4
- # Your code goes here...
6
+ extend Utilities
7
+
8
+ def lat_long_to_utm(lat, long)
9
+ validate_range(lat, long)
10
+ lat_radians = degrees_to_radians(lat)
11
+ long_radians = degrees_to_radians(long)
12
+
13
+ zone = Zone.new(long)
14
+ origin_radians = degrees_to_radians(zone.origin)
15
+
16
+ equator_factor = (EQUATORIAL_RADIUS / Math.sqrt(1 - (ECC_SQUARED * (Math.sin(lat_radians) ** 2)))
17
+ squared_lat_tangent = Math.tan(lat_radians) ** 2
18
+ ecc_prime_factor = ECC_PRIME_SQUARED * (Math.cos(lat_radians) ** 2)
19
+ origin_factor = Math.cos(lat_radians) * (long_radians - origin_radians)
20
+
21
+
22
+ ecc_1 = (1 - ecc(1, 1, 4) - ecc(2, 3, 64) - ecc(3, 5, 256))
23
+ ecc_2 = ecc(1, 3, 8) + ecc(2, 3, 32) + ecc(3, 45, 1024)
24
+ ecc_3 = ecc(2, 15, 256) + ecc(3, 45, 1024)
25
+ ecc_4 = ecc(3, 35, 3072)
26
+
27
+ latRad_1 = lat_radians
28
+ latRad_2 = Math.sin(2 * lat_radians)
29
+ latRad_3 = Math.sin(4 * lat_radians)
30
+ latRad_4 = Math.sin(6 * lat_radians)
31
+
32
+ northing_factor = EQUATORIAL_RADIUS * (
33
+ ecc_1 * latRad_1 -
34
+ ecc_2 * latRad_2 +
35
+ ecc_3 * latRad_3 -
36
+ ecc_4 * latRad_4
37
+ )
38
+
39
+ end
40
+
41
+ module_function :lat_long_to_utm
42
+
43
+
44
+ private
45
+
46
+ MAX_LATITUDE = 90.0
47
+ MIN_LATITUDE = -90.0
48
+ MAX_LONGITUDE = 180
49
+ MIN_LONGITUDE = -180
50
+ MAX_CONVERSION_LATITUDE = 84.0
51
+ MIN_CONVERSION_LATITUDE = -80.0
52
+
53
+ EQUATORIAL_RADIUS = 6378137.0
54
+ ECC_SQUARED = 0.006694380023
55
+ ECC_PRIME_SQUARED = ECC_SQUARED / (1 - ECC_SQUARED)
56
+
57
+ def self.validate_range(lat, long)
58
+ unless lat.between?(MIN_LATITUDE, MAX_LATITUDE) && long.between?(MIN_LONGITUDE, MAX_LONGITUDE)
59
+ raise InputError, 'Input coordinates are invalid'
60
+ end
61
+
62
+ unless lat.between?(MIN_CONVERSION_LATITUDE, MAX_CONVERSION_LATITUDE)
63
+ raise InputError, 'Conversions are unreliable close to the polar regions'
64
+ end
65
+ end
66
+
67
+ def self.ecc(power, numerator, denominator)
68
+ ecc = ECC_SQUARED ** power
69
+ (numerator * ecc) / denominator
70
+ end
71
+
5
72
  end
73
+
74
+ class GeoSwap::InputError < StandardError; end
@@ -0,0 +1,15 @@
1
+ require_relative '../../lib/geo_swap/utilities'
2
+
3
+ module GeoSwap
4
+ describe Utilities do
5
+ describe 'degrees_to_radians' do
6
+ DEG_RAD_DATA = [[180, Math::PI], [0, 0], [360, (2 * Math::PI)]]
7
+
8
+ it 'converts numbers accurately' do
9
+ DEG_RAD_DATA.each do |(deg, rad)|
10
+ Utilities.degrees_to_radians(deg).should == rad
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ require_relative '../../lib/geo_swap/zone'
2
+
3
+ module GeoSwap
4
+ describe Zone do
5
+
6
+
7
+ describe 'finding number from lat long' do
8
+
9
+
10
+ ZONE_DATA = [
11
+ { long: -180.0, zone_number: 1 },
12
+ { long: -147.0, zone_number: 6 },
13
+ { long: -139.0, zone_number: 7 },
14
+ { long: 0.0, zone_number: 31 },
15
+ { long: 62.0, zone_number: 41 },
16
+ { long: 71.0, zone_number: 42 },
17
+ { long: 110.0, zone_number: 49 },
18
+ { long: 141.0, zone_number: 54 },
19
+ { long: 180.0, zone_number: 60 },
20
+ ]
21
+
22
+ it 'applys the zone formula correctly' do
23
+ ZONE_DATA.each do |data|
24
+ Zone.new(data[:long]).number.should == data[:zone_number]
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ describe 'determining the zone origin' do
31
+ it 'can migrate from too far left' do
32
+ Zone.new(-180).origin.should == -177
33
+ end
34
+
35
+ it 'can migrate from too far right' do
36
+ Zone.new(180).origin.should == 177
37
+ end
38
+
39
+ it 'doesnt change the value when the long is already the origin' do
40
+ Zone.new(3).origin.should == 3
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ require_relative '../lib/geo_swap'
2
+
3
+ module GeoSwap
4
+
5
+ describe GeoSwap do
6
+ DATA = [
7
+ {
8
+ lat: 29.979175,
9
+ long: 31.1343583,
10
+ utm: "36R 320010mE 3317942mN",
11
+ },
12
+ {
13
+ lat: 41.8901694,
14
+ long: 12.4922694,
15
+ utm: "33T 291952mE 4640623mN",
16
+ }
17
+ ]
18
+
19
+ describe 'lat_long_to_utm' do
20
+ def conversion(lat, long)
21
+ GeoSwap.lat_long_to_utm(lat, long)
22
+ end
23
+
24
+ def check_error(lat, long, message)
25
+ expect { conversion(lat, long) }.
26
+ to raise_error(InputError, message)
27
+ end
28
+
29
+ it 'rejects data too close to the north pole' do
30
+ check_error(84.1, 0.0, 'Conversions are unreliable close to the polar regions')
31
+ end
32
+
33
+ it 'rejects data too close to the south pole' do
34
+ check_error(-80.1, 0.0, 'Conversions are unreliable close to the polar regions')
35
+ end
36
+
37
+ it 'rejects data outside the possible lat/long range' do
38
+ check_error(0.0,200.0, 'Input coordinates are invalid')
39
+ end
40
+
41
+ it 'correctly converts several reference points' do
42
+ DATA.each do |data|
43
+ GeoSwap.lat_long_to_utm(data[:lat], data[:long]).should == data[:utm]
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geo_swap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 10.0.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.12.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.12.0
30
46
  description: Simple utility functions for converting between coordinate systems (Lat/Long,
31
47
  UTM, USNG)
32
48
  email:
@@ -43,7 +59,12 @@ files:
43
59
  - Rakefile
44
60
  - geo_swap.gemspec
45
61
  - lib/geo_swap.rb
62
+ - lib/geo_swap/utilities.rb
46
63
  - lib/geo_swap/version.rb
64
+ - lib/geo_swap/zone.rb
65
+ - spec/geo_swap/utilities_spec.rb
66
+ - spec/geo_swap/zone_spec.rb
67
+ - spec/geo_swap_spec.rb
47
68
  homepage: ''
48
69
  licenses: []
49
70
  post_install_message:
@@ -58,7 +79,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
58
79
  version: '0'
59
80
  segments:
60
81
  - 0
61
- hash: 3296913527661097903
82
+ hash: -10926259193031771
62
83
  required_rubygems_version: !ruby/object:Gem::Requirement
63
84
  none: false
64
85
  requirements:
@@ -67,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
88
  version: '0'
68
89
  segments:
69
90
  - 0
70
- hash: 3296913527661097903
91
+ hash: -10926259193031771
71
92
  requirements: []
72
93
  rubyforge_project:
73
94
  rubygems_version: 1.8.23
@@ -75,4 +96,7 @@ signing_key:
75
96
  specification_version: 3
76
97
  summary: Simple utility functions for converting between coordinate systems (Lat/Long,
77
98
  UTM, USNG)
78
- test_files: []
99
+ test_files:
100
+ - spec/geo_swap/utilities_spec.rb
101
+ - spec/geo_swap/zone_spec.rb
102
+ - spec/geo_swap_spec.rb