gis-distance 1.0.0

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/CHANGES ADDED
@@ -0,0 +1,2 @@
1
+ == 0.1.0 - ???
2
+ * Initial release
@@ -0,0 +1,7 @@
1
+ * CHANGES
2
+ * MANIFEST
3
+ * README
4
+ * Rakefile
5
+ * gis-distance.gemspec
6
+ * lib/gis/distance.rb
7
+ * test/test_gis_distance.rb
data/README ADDED
@@ -0,0 +1,22 @@
1
+ == Description
2
+ The gis-distance library allows you to calculate geographic distance between
3
+ two points using the formula of your choice.
4
+
5
+ == Installation
6
+ gem install gis-distance
7
+
8
+ == Synopsis
9
+ require 'gis/distance'
10
+
11
+ # New York to Los Angeles
12
+ gis = GIS::Distance.new(40.47, 73.58, 34.3, 118.15)
13
+
14
+ p gis.distance # Kilometers
15
+ p gis.distance.mi # Miles
16
+
17
+ == License
18
+ Artistic 2.0
19
+
20
+ == Authors
21
+ * Daniel Berger
22
+ * Ardith Faulkner
@@ -0,0 +1,27 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ include Config
4
+
5
+ desc "Install the gis-distance library"
6
+ task :install_lib do
7
+ dest = File.join(CONFIG['sitelibdir'], 'gis')
8
+ Dir.mkdir(dest) unless File.exists? dest
9
+ cp 'lib/gis/distance.rb', dest, :verbose => true
10
+ end
11
+
12
+ desc 'Build the gis-distance gem'
13
+ task :gem do
14
+ spec = eval(IO.read('gis-distance.gemspec'))
15
+ Gem::Builder.new(spec).build
16
+ end
17
+
18
+ desc 'Install the gis-distance library as a gem'
19
+ task :install_gem => [:gem] do
20
+ file = Dir["*.gem"].first
21
+ sh "gem install #{file}"
22
+ end
23
+
24
+ Rake::TestTask.new do |t|
25
+ t.warning = true
26
+ t.verbose = true
27
+ end
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'gis-distance'
5
+ gem.version = '1.0.0'
6
+ gem.authors = ['Daniel J. Berger', 'Ardith Faulkner']
7
+ gem.license = 'Artistic 2.0'
8
+ gem.description = 'Calculate the distance between 2 points on Earth'
9
+ gem.email = 'djberg96@gmail.com'
10
+ gem.files = Dir['**/*'].reject{ |f| f.include?('CVS') }
11
+ gem.test_files = ['test/test_gis_distance.rb']
12
+ gem.has_rdoc = true
13
+ gem.homepage = 'http://github.com/djberg96/gis-distance'
14
+
15
+ gem.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
16
+
17
+ gem.summary = <<-EOF
18
+ The gis-distance library provides a simple interface for
19
+ calculating the distance between two points on Earth using
20
+ latitude and longitude.
21
+ EOF
22
+ end
@@ -0,0 +1,135 @@
1
+ # The GIS module serves as a namespace only.
2
+ module GIS
3
+ # The Distance class encapsulates methods related to geographic distance.
4
+ class Distance
5
+ # Error raised if latitude or longitude values are invalid.
6
+ class Error < StandardError; end
7
+
8
+ # The version of the gis-distance library
9
+ VERSION = '1.0.0'
10
+
11
+ # Create a new GIS::Distance object using the two sets of coordinates
12
+ # that are provided.
13
+ #
14
+ # If invalid coordinates are provided a GIS::Distance::Error is raised.
15
+ #
16
+ def initialize(latitude1, longitude1, latitude2, longitude2)
17
+ validate(latitude1, longitude1, latitude2, longitude2)
18
+
19
+ @latitude1 = latitude1
20
+ @longitude1 = longitude1
21
+ @latitude2 = latitude2
22
+ @longitude2 = longitude2
23
+
24
+ @radius = 6367.45
25
+ @formula = 'haversine'
26
+ @distance = nil
27
+ end
28
+
29
+ # Returns the radius of the Earth in kilometers. The default is 6367.45.
30
+ #
31
+ def radius
32
+ @radius
33
+ end
34
+
35
+ # Sets the radius of the Earth in kilometers. This is variable because
36
+ # the Earth is not perfectly spherical, and you may wish to adjust it.
37
+ #
38
+ # However, the possible range of values is limited from 6357.0 to 6378.0.
39
+ # If a value outside of this range is provided a GIS::Distance::Error
40
+ # is raised.
41
+ #
42
+ # The default value is 6367.45.
43
+ #
44
+ # See http://en.wikipedia.org/wiki/Earth_radius for more information.
45
+ #
46
+ def radius=(kms)
47
+ if kms < 6357.0 || kms > 6378.0
48
+ raise Error, "Proposed radius '#{kms}' is out of range"
49
+ end
50
+ @radius = kms
51
+ end
52
+
53
+ # Returns the formula used to calculate the distance. The default formula
54
+ # is 'haversine'.
55
+ #--
56
+ # See http://en.wikipedia.org/wiki/Haversine_formula for details.
57
+ def formula
58
+ @formula
59
+ end
60
+
61
+ # Sets the formula to be used internally for calculating the distance.
62
+ # The default is 'haversine'.
63
+ #
64
+ # If an unsupported formula is provided a GIS::Distance::Error is raised.
65
+ #
66
+ def formula=(formula)
67
+ case formula.to_s.downcase
68
+ when 'haversine'
69
+ @formula = 'haversine'
70
+ else
71
+ raise Error, "Formula '#{formula}' not supported"
72
+ end
73
+ end
74
+
75
+ # Returns the distance (in kilometers) between the two coordinates
76
+ # provided in the constructor.
77
+ #
78
+ def distance
79
+ @distance =
80
+ case @formula.to_s.downcase
81
+ when 'haversine'
82
+ haversine_formula
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ # Validate the latitude and longitude values. Latitudes must be between
89
+ # 90.0 and -90.0 while longitudes must be between 180.0 and -180.0.
90
+ #
91
+ def validate(lat1, lon1, lat2, lon2)
92
+ [lat1, lat2].each{ |lat|
93
+ if lat > 90 || lat < -90
94
+ msg = "Latitude '#{lat}' is invalid - must be between -90 and 90"
95
+ raise Error, msg
96
+ end
97
+ }
98
+
99
+ [lon1, lon2].each{ |lon|
100
+ if lon > 180 || lon < -180
101
+ msg = "Longitude '#{lon}' is invalid - must be between -180 and 180"
102
+ raise Error, msg
103
+ end
104
+ }
105
+ end
106
+
107
+ # See http://en.wikipedia.org/wiki/Haversine_formula
108
+ #
109
+ def haversine_formula
110
+ lat1 = @latitude1 * Math::PI / 180
111
+ lon1 = @longitude1 * Math::PI / 180
112
+ lat2 = @latitude2 * Math::PI / 180
113
+ lon2 = @longitude2 * Math::PI / 180
114
+
115
+ dlat = lat2 - lat1
116
+ dlon = lon2 - lon1
117
+
118
+ a = ((Math.sin(dlat/2))**2) + (Math.cos(lat1) * Math.cos(lat2) * (Math.sin(dlon/2)) ** 2)
119
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
120
+
121
+ @radius * c
122
+ end
123
+
124
+ # Add a custom method to the base Float class if it isn't already defined.
125
+ class ::Float
126
+ unless self.respond_to?(:mi)
127
+ # Convert miles to kilometers.
128
+ def mi
129
+ self * 0.621371192
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
@@ -0,0 +1,98 @@
1
+ require 'test/unit'
2
+ require 'gis/distance'
3
+
4
+ class TC_GIS_Distance < Test::Unit::TestCase
5
+ def setup
6
+ @gis = GIS::Distance.new(40.47, 73.58, 34.3, 118.15)
7
+ end
8
+
9
+ def test_version
10
+ assert_equal('1.0.0', GIS::Distance::VERSION)
11
+ end
12
+
13
+ def test_distance_basic_functionality
14
+ assert_respond_to(@gis, :distance)
15
+ assert_nothing_raised{ @gis.distance }
16
+ assert_kind_of(Float, @gis.distance)
17
+ end
18
+
19
+ def test_distance
20
+ assert_in_delta(0.01, 3952.39, @gis.distance)
21
+ assert_equal(0.0, GIS::Distance.new(40.47, 73.58, 40.47, 73.58).distance)
22
+ end
23
+
24
+ def test_distance_expected_argument_errors
25
+ assert_raise(ArgumentError){ GIS::Distance.new }
26
+ assert_raise(ArgumentError){ GIS::Distance.new(40.47) }
27
+ assert_raise(ArgumentError){ GIS::Distance.new(40.47, 73.58) }
28
+ assert_raise(ArgumentError){ GIS::Distance.new(40.47, 73.58, 34.3) }
29
+ end
30
+
31
+ def test_distance_expected_range_errors
32
+ assert_raise(GIS::Distance::Error){ GIS::Distance.new(91.0, 100.0, 45.0, 45.0) }
33
+ assert_raise(GIS::Distance::Error){ GIS::Distance.new(90.0, 190.0, 45.0, 45.0) }
34
+ end
35
+
36
+ def test_radius_basic_functionality
37
+ assert_respond_to(@gis, :radius)
38
+ assert_nothing_raised{ @gis.radius }
39
+ assert_kind_of(Float, @gis.radius)
40
+ end
41
+
42
+ def test_default_radius
43
+ assert_equal(6367.45, @gis.radius)
44
+ end
45
+
46
+ def test_radius_expected_errors
47
+ assert_raise(ArgumentError){ @gis.radius(1) }
48
+ end
49
+
50
+ def test_radius_setter_basic_functionality
51
+ assert_respond_to(@gis, :radius=)
52
+ assert_nothing_raised{ @gis.radius = 6368.0 }
53
+ assert_equal(6368.0, @gis.radius)
54
+ end
55
+
56
+ def test_radius_setter_expected_errors
57
+ assert_raise(GIS::Distance::Error){ @gis.radius = 6200 }
58
+ assert_raise(GIS::Distance::Error){ @gis.radius = 6400 }
59
+ end
60
+
61
+ def test_formula_basic_functionality
62
+ assert_respond_to(@gis, :formula)
63
+ assert_nothing_raised{ @gis.formula }
64
+ assert_kind_of(String, @gis.formula)
65
+ end
66
+
67
+ def test_formula
68
+ assert_equal('haversine', @gis.formula)
69
+ end
70
+
71
+ def test_formula_setter_basic_functionality
72
+ assert_respond_to(@gis, :formula=)
73
+ assert_nothing_raised{ @gis.formula = 'haversine' }
74
+ end
75
+
76
+ def test_formula_expected_errors
77
+ assert_raise(ArgumentError){ @gis.formula(1) }
78
+ assert_raise(GIS::Distance::Error){ @gis.formula = 'foo' }
79
+ end
80
+
81
+ def test_mi_basic_functionality
82
+ assert_respond_to(@gis.distance, :mi)
83
+ assert_nothing_raised{ @gis.distance.mi }
84
+ assert_kind_of(Float, @gis.distance.mi)
85
+ end
86
+
87
+ def test_mi
88
+ assert(@gis.distance > @gis.distance.mi)
89
+ end
90
+
91
+ def test_mi_expected_errors
92
+ assert_raise(ArgumentError){ @gis.distance.mi(1) }
93
+ end
94
+
95
+ def teardown
96
+ @gis = nil
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gis-distance
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel J. Berger
8
+ - Ardith Faulkner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-10-10 00:00:00 -06:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Calculate the distance between 2 points on Earth
18
+ email: djberg96@gmail.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README
25
+ - CHANGES
26
+ - MANIFEST
27
+ files:
28
+ - CHANGES
29
+ - gis-distance.gemspec
30
+ - lib/gis/distance.rb
31
+ - MANIFEST
32
+ - Rakefile
33
+ - README
34
+ - test/test_gis_distance.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/djberg96/gis-distance
37
+ licenses:
38
+ - Artistic 2.0
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.5
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: The gis-distance library provides a simple interface for calculating the distance between two points on Earth using latitude and longitude.
63
+ test_files:
64
+ - test/test_gis_distance.rb