geodistance 0.0.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,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in geodistance.gemspec
4
+ gemspec
@@ -0,0 +1,3 @@
1
+ Please go to Wiki for help
2
+
3
+ Any questions? E-mail denniss@cal.berkeley.edu
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "geodistance/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "geodistance"
7
+ s.version = Geodistance::VERSION
8
+ s.authors = ["Dennis Suratna"]
9
+ s.email = ["denniss@cal.berkeley.edu"]
10
+ s.homepage = ""
11
+ s.summary = %q{These are helper methods for doing any geolocation operation}
12
+ s.description = %q{Helper methods for calculating geolocation distance based on longitude and latitude. It will also have other methods that I feel are tedious and boring to re-write}
13
+
14
+ s.rubyforge_project = "geodistance"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec"
22
+ end
@@ -0,0 +1,82 @@
1
+ require "geodistance/version"
2
+
3
+ module Geodistance
4
+ UNITS_OF_DISTANCE = [:mile, :kilometer]
5
+ EARTH_RADIUS_IN_MILE = 3959
6
+ EARTH_RADIUS_IN_KILOMETER = 6371
7
+
8
+ def haversine_distance(lon, lat)
9
+ distance_in_unit(haversine(lon, lat))
10
+ end
11
+
12
+ def distance(lon, lat)
13
+ distance_in_unit(spherical_law_of_cosines(lon, lat))
14
+ end
15
+
16
+ def distance_in_unit(delta_sigma_hat)
17
+ case __unit
18
+ when :mile
19
+ EARTH_RADIUS_IN_MILE * delta_sigma_hat
20
+ else
21
+ EARTH_RADIUS_IN_KILOMETER * delta_sigma_hat
22
+ end
23
+ end
24
+
25
+ def haversine(lon, lat)
26
+ phi_s = to_rad __latitude
27
+ lambda_s = to_rad __longitude
28
+ phi_f = to_rad lat
29
+ lambda_f = to_rad lon
30
+ delta_lambda = (lambda_f - lambda_s).abs
31
+ delta_phi = (phi_f - phi_s).abs
32
+
33
+ a = Math.sin(delta_phi/2)**2
34
+ b = Math.cos(phi_s) * Math.cos(phi_f) * Math.sin(delta_lambda/2)**2
35
+ 2 * Math.asin(Math.sqrt(a + b)) #delta sigma hat
36
+ end
37
+
38
+ def spherical_law_of_cosines(lon, lat)
39
+ phi_s = to_rad __latitude
40
+ lambda_s = to_rad __longitude
41
+ phi_f = to_rad lat
42
+ lambda_f = to_rad lon
43
+ delta_lambda = (lambda_f - lambda_s).abs
44
+
45
+ Math.acos(Math.sin(phi_s) * Math.sin(phi_f) + Math.cos(phi_s) * Math.cos(phi_f) * Math.cos(delta_lambda))
46
+ end
47
+
48
+ def __longitude
49
+ self.instance_variable_get("@#{self.class.instance_variable_get(:@longitude_attr)}".to_sym)
50
+ end
51
+
52
+ def __latitude
53
+ self.instance_variable_get("@#{self.class.instance_variable_get(:@latitude_attr)}".to_sym)
54
+ end
55
+
56
+ def __unit
57
+ self.class.instance_variable_get(:@unit_of_distance)
58
+ end
59
+
60
+ module ClassMethods
61
+ def longitude_attr(name)
62
+ @longitude_attr = name
63
+ end
64
+
65
+ def latitude_attr(name)
66
+ @latitude_attr = name
67
+ end
68
+
69
+ def unit_of_distance(name)
70
+ raise "Unrecognize unit of distance #{name}. Use one of these: #{UNITS_OF_DISTANCE} " unless UNITS_OF_DISTANCE.include? name.to_sym
71
+ @unit_of_distance = name
72
+ end
73
+ end
74
+
75
+ def self.included(base)
76
+ base.extend(ClassMethods)
77
+ end
78
+
79
+ def to_rad(angle)
80
+ angle/180 * Math::PI
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ module Geodistance
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,129 @@
1
+ require File.expand_path('../../lib/geodistance.rb', __FILE__)
2
+
3
+
4
+ describe Geodistance do
5
+ describe ".longitude_attr" do
6
+ it "should set the attribute to get the longitude" do
7
+ class TestClass
8
+ include Geodistance
9
+ longitude_attr :lon
10
+ end
11
+ TestClass.instance_variable_get(:@longitude_attr).should == :lon
12
+ end
13
+ end
14
+
15
+ describe ".latitude_attr" do
16
+ it "should set the attribute to get the latitude" do
17
+ class TestClass
18
+ include Geodistance
19
+ latitude_attr :lat
20
+ end
21
+ TestClass.instance_variable_get(:@latitude_attr).should == :lat
22
+ end
23
+ end
24
+
25
+ describe ".unit_of_distance" do
26
+ context "with invalid unit of distance" do
27
+ it "raises an error" do
28
+ lambda { Class.new do
29
+ include Geodistance
30
+ unit_of_distance :rofl
31
+ end }.should raise_error
32
+ end
33
+ end
34
+
35
+ context "with valid unit of distance" do
36
+ it "sets the instance variable with the right unit" do
37
+ class TestClass
38
+ include Geodistance
39
+ unit_of_distance :mile
40
+ end
41
+ TestClass.instance_variable_get(:@unit_of_distance).should == :mile
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "longitude and latitude and unit" do
47
+ before do
48
+ class DummyClass
49
+ include Geodistance
50
+ latitude_attr :lat
51
+ longitude_attr :lon
52
+ unit_of_distance :mile
53
+
54
+ def initialize(lon, lat)
55
+ @lon = lon
56
+ @lat = lat
57
+ end
58
+ end
59
+
60
+ @dummy = DummyClass.new(30, 20)
61
+ end
62
+
63
+ it "longitude returns the longitude" do
64
+ @dummy.__longitude.should == 30
65
+ end
66
+
67
+ it "latitude returns the latitude" do
68
+ @dummy.__latitude.should == 20
69
+ end
70
+
71
+ it "unit returns unit of distance" do
72
+ @dummy.__unit.should == :mile
73
+ end
74
+ end
75
+
76
+ describe "haversine_distance" do
77
+ before do
78
+ class DummyClass
79
+ include Geodistance
80
+ latitude_attr :lat
81
+ longitude_attr :lon
82
+ unit_of_distance :kilometer
83
+
84
+ def initialize(lon, lat)
85
+ @lon = lon
86
+ @lat = lat
87
+ end
88
+ end
89
+ lon_s = -22.534 #22 32 2 W
90
+ lat_s = 40.512 #40 30 43 N
91
+
92
+ @dummy = DummyClass.new(lon_s, lat_s)
93
+
94
+ @lon_f = 53.456 #53 27 22 E
95
+ @lat_f = 62.123 #62 7 23 N
96
+ end
97
+
98
+ it "gives right distance" do
99
+ @dummy.haversine_distance(@lon_f, @lat_f).should be_within(1).of(5413)
100
+ end
101
+ end
102
+
103
+ describe "distance" do
104
+ before do
105
+ class DummyClass
106
+ include Geodistance
107
+ latitude_attr :lat
108
+ longitude_attr :lon
109
+ unit_of_distance :kilometer
110
+
111
+ def initialize(lon, lat)
112
+ @lon = lon
113
+ @lat = lat
114
+ end
115
+ end
116
+ lon_s = -86.67
117
+ lat_s = 36.12
118
+
119
+ @dummy = DummyClass.new(lon_s, lat_s)
120
+
121
+ @lon_f = -118.40
122
+ @lat_f = 33.94
123
+ end
124
+
125
+ it "gives right distance" do
126
+ @dummy.distance(@lon_f, @lat_f).should be_within(1).of(2887)
127
+ end
128
+ end
129
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geodistance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dennis Suratna
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-31 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &2152693500 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2152693500
25
+ description: Helper methods for calculating geolocation distance based on longitude
26
+ and latitude. It will also have other methods that I feel are tedious and boring
27
+ to re-write
28
+ email:
29
+ - denniss@cal.berkeley.edu
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - README.markdown
37
+ - Rakefile
38
+ - geodistance.gemspec
39
+ - lib/geodistance.rb
40
+ - lib/geodistance/version.rb
41
+ - spec/geodistance_spec.rb
42
+ homepage: ''
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: geodistance
62
+ rubygems_version: 1.8.15
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: These are helper methods for doing any geolocation operation
66
+ test_files:
67
+ - spec/geodistance_spec.rb