gis-distance 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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