geo-distance 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/Gemfile +7 -9
  2. data/Gemfile.lock +30 -13
  3. data/README.textile +28 -8
  4. data/VERSION +1 -1
  5. data/geo-distance.gemspec +40 -32
  6. data/lib/geo-distance.rb +14 -132
  7. data/lib/geo-distance/class_methods.rb +71 -0
  8. data/lib/geo-distance/conversion.rb +67 -0
  9. data/lib/geo-distance/conversion/meters.rb +29 -0
  10. data/lib/geo-distance/conversion/radians.rb +36 -0
  11. data/lib/geo-distance/core_ext.rb +12 -23
  12. data/lib/geo-distance/distance.rb +24 -0
  13. data/lib/geo-distance/formula.rb +53 -7
  14. data/lib/geo-distance/formula/flat.rb +21 -0
  15. data/lib/geo-distance/{haversine.rb → formula/haversine.rb} +18 -14
  16. data/lib/geo-distance/formula/n_vector.rb +30 -0
  17. data/lib/geo-distance/formula/spherical.rb +44 -0
  18. data/lib/geo-distance/formula/vincenty.rb +80 -0
  19. data/lib/geo-distance/scale.rb +18 -0
  20. data/spec/geo_distance/class_methods_spec.rb +70 -0
  21. data/spec/geo_distance/core_ext_spec.rb +65 -0
  22. data/spec/geo_distance/distance_spec.rb +74 -0
  23. data/spec/geo_distance/formula/flat_spec.rb +31 -0
  24. data/spec/geo_distance/formula/haversine_spec.rb +33 -0
  25. data/spec/geo_distance/formula/n_vector.rb +33 -0
  26. data/spec/geo_distance/formula/spherical_spec.rb +33 -0
  27. data/spec/geo_distance/formula/vincenty_spec.rb +33 -0
  28. data/spec/spec_helper.rb +0 -10
  29. metadata +97 -96
  30. data/lib/geo-distance/spherical.rb +0 -24
  31. data/lib/geo-distance/vincenty.rb +0 -79
  32. data/spec/core_ext_spec.rb +0 -9
  33. data/spec/dist_default_spec.rb +0 -23
  34. data/spec/dist_haversine_spec.rb +0 -21
  35. data/spec/dist_spherical_spec.rb +0 -21
  36. data/spec/dist_vincenty_spec.rb +0 -21
data/Gemfile CHANGED
@@ -1,13 +1,11 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
2
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
3
+ gem 'geo_point', '~> 0.2.5'
4
+ gem 'geo_units', '~> 0.2.4.1'
5
+
8
6
  group :development do
9
- gem "rspec", ">= 2.3.0"
10
- gem "bundler", "~> 1.0.0"
11
- gem "jeweler", "~> 1.5.2"
12
- gem "rcov", ">= 0"
7
+ gem "rspec", ">= 2.6.0"
8
+ gem "bundler", "~> 1.0.10"
9
+ gem "jeweler", "~> 1.6.2"
10
+ gem "rcov", ">= 0"
13
11
  end
@@ -1,28 +1,45 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activesupport (3.0.9)
4
5
  diff-lcs (1.1.2)
6
+ geo_calc (0.7.6)
7
+ activesupport (>= 3.0.1)
8
+ geo_units (~> 0.2.1)
9
+ i18n
10
+ require_all (~> 1.2.0)
11
+ sugar-high (~> 0.4.6.3)
12
+ geo_point (0.2.5)
13
+ geo_calc (~> 0.7.5)
14
+ geo_units (~> 0.2.1)
15
+ geo_units (0.2.4.1)
16
+ sugar-high (~> 0.4.6.2)
5
17
  git (1.2.5)
6
- jeweler (1.5.2)
7
- bundler (~> 1.0.0)
18
+ i18n (0.6.0)
19
+ jeweler (1.6.2)
20
+ bundler (~> 1.0)
8
21
  git (>= 1.2.5)
9
22
  rake
10
- rake (0.8.7)
23
+ rake (0.9.2)
11
24
  rcov (0.9.9)
12
- rspec (2.4.0)
13
- rspec-core (~> 2.4.0)
14
- rspec-expectations (~> 2.4.0)
15
- rspec-mocks (~> 2.4.0)
16
- rspec-core (2.4.0)
17
- rspec-expectations (2.4.0)
25
+ require_all (1.2.0)
26
+ rspec (2.6.0)
27
+ rspec-core (~> 2.6.0)
28
+ rspec-expectations (~> 2.6.0)
29
+ rspec-mocks (~> 2.6.0)
30
+ rspec-core (2.6.4)
31
+ rspec-expectations (2.6.0)
18
32
  diff-lcs (~> 1.1.2)
19
- rspec-mocks (2.4.0)
33
+ rspec-mocks (2.6.0)
34
+ sugar-high (0.4.6.4)
20
35
 
21
36
  PLATFORMS
22
37
  ruby
23
38
 
24
39
  DEPENDENCIES
25
- bundler (~> 1.0.0)
26
- jeweler (~> 1.5.2)
40
+ bundler (~> 1.0.10)
41
+ geo_point (~> 0.2.5)
42
+ geo_units (~> 0.2.4.1)
43
+ jeweler (~> 1.6.2)
27
44
  rcov
28
- rspec (>= 2.3.0)
45
+ rspec (>= 2.6.0)
@@ -10,6 +10,7 @@ The formulas curently supported are
10
10
  * _Haversine_
11
11
  * _Spherical_
12
12
  * _Vincenty_
13
+ * _Flat_
13
14
 
14
15
  h2. Install & Usage
15
16
 
@@ -22,17 +23,36 @@ it "should work" do
22
23
  lon2 = -104.80
23
24
  lat2 = lat1
24
25
 
25
- dist = GeoDistance::Haversine.distance( lat1, lon1, lat2, lon2 )
26
+ dist = GeoDistance.distance( lat1, lon1, lat2, lon2 ) # in radians
26
27
 
27
- puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist[:meters].number} meters"
28
+ dist = GeoDistance::Haversine.geo_distance( lat1, lon1, lat2, lon2 ).to_meters
28
29
 
29
- puts "#{dist[:feet]}"
30
- puts "#{dist.meters}"
31
- puts "#{dist[:km]}"
32
- puts "#{dist[:miles]}"
33
- dist[:km].to_s.should match(/7\.376*/)
30
+ # Change to (lng, lat) mode
31
+ GeoPoint.coord_mode = :lng_lat
32
+
33
+ p1, p2 = [[lon1, lat1].geo_point, [lon2, lat2].geo_point]
34
+
35
+ dist = GeoDistance::Haversine.geo_distance( lon1, lat1, lon2, lat2)
36
+ dist = GeoDistance::Haversine.geo_distance( p1, p2).to_miles
37
+
38
+ puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist.meters} meters"
39
+
40
+ dist.feet
41
+ dist.meters
42
+ dist.kms
43
+ dist.miles
34
44
  end
35
- </pre>
45
+ </pre>
46
+
47
+ h2. Distance API
48
+
49
+ The call to distance returns an instance of GeoDistance
50
+
51
+ @dist = GeoDistance::Haversine.distance( lat1, lon1, lat2, lon2 )@
52
+
53
+ The #kms, #meters, #miles and #feet methods return an instance og GeoUnit
54
+
55
+ @dist.kms@
36
56
 
37
57
  h3. Setting default algorithm
38
58
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{geo-distance}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Kristian Mandrup"]
12
- s.date = %q{2011-01-14}
11
+ s.authors = [%q{Kristian Mandrup}]
12
+ s.date = %q{2011-06-23}
13
13
  s.description = %q{Calculates the geo distance between two locations using longitude and latitude using Haversine, Speherical or Vincenty formula.
14
14
  This is done using Math formulas without resorting to Active Record or SQL DB functionality}
15
15
  s.email = %q{kmandrup@gmail.com}
@@ -28,51 +28,59 @@ This is done using Math formulas without resorting to Active Record or SQL DB fu
28
28
  "VERSION",
29
29
  "geo-distance.gemspec",
30
30
  "lib/geo-distance.rb",
31
+ "lib/geo-distance/class_methods.rb",
32
+ "lib/geo-distance/conversion.rb",
33
+ "lib/geo-distance/conversion/meters.rb",
34
+ "lib/geo-distance/conversion/radians.rb",
31
35
  "lib/geo-distance/core_ext.rb",
36
+ "lib/geo-distance/distance.rb",
32
37
  "lib/geo-distance/formula.rb",
33
- "lib/geo-distance/haversine.rb",
34
- "lib/geo-distance/spherical.rb",
35
- "lib/geo-distance/vincenty.rb",
36
- "spec/core_ext_spec.rb",
37
- "spec/dist_default_spec.rb",
38
- "spec/dist_haversine_spec.rb",
39
- "spec/dist_spherical_spec.rb",
40
- "spec/dist_vincenty_spec.rb",
38
+ "lib/geo-distance/formula/flat.rb",
39
+ "lib/geo-distance/formula/haversine.rb",
40
+ "lib/geo-distance/formula/n_vector.rb",
41
+ "lib/geo-distance/formula/spherical.rb",
42
+ "lib/geo-distance/formula/vincenty.rb",
43
+ "lib/geo-distance/scale.rb",
44
+ "spec/geo_distance/class_methods_spec.rb",
45
+ "spec/geo_distance/core_ext_spec.rb",
46
+ "spec/geo_distance/distance_spec.rb",
47
+ "spec/geo_distance/formula/flat_spec.rb",
48
+ "spec/geo_distance/formula/haversine_spec.rb",
49
+ "spec/geo_distance/formula/n_vector.rb",
50
+ "spec/geo_distance/formula/spherical_spec.rb",
51
+ "spec/geo_distance/formula/vincenty_spec.rb",
41
52
  "spec/spec_helper.rb"
42
53
  ]
43
54
  s.homepage = %q{http://github.com/kristianmandrup/geo-distance}
44
- s.licenses = ["MIT"]
45
- s.require_paths = ["lib"]
46
- s.rubygems_version = %q{1.3.7}
55
+ s.licenses = [%q{MIT}]
56
+ s.require_paths = [%q{lib}]
57
+ s.rubygems_version = %q{1.8.5}
47
58
  s.summary = %q{Calculates the geo distance between two locations using longitude and latitude, using Haversine, Speherical or Vincenty formula}
48
- s.test_files = [
49
- "spec/core_ext_spec.rb",
50
- "spec/dist_default_spec.rb",
51
- "spec/dist_haversine_spec.rb",
52
- "spec/dist_spherical_spec.rb",
53
- "spec/dist_vincenty_spec.rb",
54
- "spec/spec_helper.rb"
55
- ]
56
59
 
57
60
  if s.respond_to? :specification_version then
58
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
61
  s.specification_version = 3
60
62
 
61
63
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
- s.add_development_dependency(%q<rspec>, [">= 2.3.0"])
63
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
64
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
64
+ s.add_runtime_dependency(%q<geo_point>, ["~> 0.2.5"])
65
+ s.add_runtime_dependency(%q<geo_units>, ["~> 0.2.4.1"])
66
+ s.add_development_dependency(%q<rspec>, [">= 2.6.0"])
67
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.10"])
68
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
65
69
  s.add_development_dependency(%q<rcov>, [">= 0"])
66
70
  else
67
- s.add_dependency(%q<rspec>, [">= 2.3.0"])
68
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
71
+ s.add_dependency(%q<geo_point>, ["~> 0.2.5"])
72
+ s.add_dependency(%q<geo_units>, ["~> 0.2.4.1"])
73
+ s.add_dependency(%q<rspec>, [">= 2.6.0"])
74
+ s.add_dependency(%q<bundler>, ["~> 1.0.10"])
75
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
70
76
  s.add_dependency(%q<rcov>, [">= 0"])
71
77
  end
72
78
  else
73
- s.add_dependency(%q<rspec>, [">= 2.3.0"])
74
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
79
+ s.add_dependency(%q<geo_point>, ["~> 0.2.5"])
80
+ s.add_dependency(%q<geo_units>, ["~> 0.2.4.1"])
81
+ s.add_dependency(%q<rspec>, [">= 2.6.0"])
82
+ s.add_dependency(%q<bundler>, ["~> 1.0.10"])
83
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
76
84
  s.add_dependency(%q<rcov>, [">= 0"])
77
85
  end
78
86
  end
@@ -1,136 +1,18 @@
1
- module GeoDistance
2
- # this is global because if computing lots of track point distances, it didn't make
3
- # sense to new a Hash each time over potentially 100's of thousands of points
1
+ require 'geo_point'
4
2
 
5
- class << self
6
- # radius of the great circle in miles
7
- # radius in kilometers...some algorithms use 6367
8
- def earth_radius
9
- {:km => 6371, :miles => 3956, :feet => 20895592, :meters => 6371000}
10
- end
3
+ class GeoDistance
4
+ autoload :Conversion, 'geo-distance/conversion'
5
+ autoload :Scale, 'geo-distance/scale'
6
+ autoload :ClassMethods, 'geo-distance/class_methods'
11
7
 
12
- def radians_per_degree
13
- 0.017453293 # PI/180
14
- end
15
-
16
- def units
17
- [:miles, :km, :feet, :meters]
18
- end
19
-
20
- def radians_ratio unit
21
- GeoDistance.radians_per_degree * earth_radius[unit]
22
- end
23
-
24
- def default_algorithm= name
25
- raise ArgumentError, "Not a valid algorithm. Must be one of: #{algorithms}" if !algorithms.include?(name.to_sym)
26
- @default_algorithm = name
27
- end
28
-
29
- def distance( lat1, lon1, lat2, lon2)
30
- klass = case default_algorithm
31
- when :haversine
32
- GeoDistance::Haversine
33
- when :spherical
34
- GeoDistance::Spherical
35
- when :vincenty
36
- GeoDistance::Vincenty
37
- else
38
- raise ArgumentError, "Not a valid algorithm. Must be one of: #{algorithms}"
39
- end
40
- klass.distance lat1, lon1, lat2, lon2
41
- end
42
-
43
- def default_algorithm
44
- @default_algorithm || :haversine
45
- end
46
-
47
- protected
48
-
49
- def algorithms
50
- [:haversine, :spherical, :vincenty]
51
- end
52
- end
53
-
54
- class Distance
55
- attr_reader :distance, :unit
8
+ autoload :Haversine, 'geo-distance/formula/haversine'
9
+ autoload :Spherical, 'geo-distance/formula/spherical'
10
+ autoload :Vincenty, 'geo-distance/formula/vincenty'
11
+ autoload :NVector, 'geo-distance/formula/n_vector'
12
+ autoload :Flat, 'geo-distance/formula/flat'
13
+ end
56
14
 
57
- def initialize distance, unit = nil
58
- @distance = distance
59
- return if !unit
15
+ require 'geo-distance/distance'
16
+ require 'geo-distance/core_ext'
17
+ require 'geo-distance/formula'
60
18
 
61
- raise ArgumentError, "Invalid unit: #{unit} - must be one of #{GeoDistance.units}" if !GeoDistance.units.include?(unit.to_sym)
62
- @unit = unit.to_sym
63
- end
64
-
65
- def [] key
66
- method = :"delta_#{key}"
67
- raise ArgumentError, "Invalid unit key #{key}" if !respond_to? method
68
- Distance.send "in_#{key}", send(method)
69
- end
70
-
71
- GeoDistance.units.each do |unit|
72
- class_eval %{
73
- def #{unit}
74
- self[:#{unit}]
75
- end
76
- }
77
- end
78
-
79
- protected
80
-
81
- # delta between the two points in miles
82
- GeoDistance.units.each do |unit|
83
- class_eval %{
84
- def delta_#{unit}
85
- GeoDistance.earth_radius[:#{unit}] * distance
86
- end
87
- }
88
- end
89
-
90
- class << self
91
- GeoDistance.units.each do |unit|
92
- class_eval %{
93
- def in_#{unit} number
94
- Unit.new :#{unit}, number
95
- end
96
- }
97
- end
98
- end
99
-
100
- class Unit
101
- attr_accessor :name, :number
102
-
103
- def initialize name, number = 0
104
- @name = name
105
- @number = number
106
- end
107
-
108
- def number
109
- @number.round_to(precision[name])
110
- end
111
-
112
- def to_s
113
- "#{number} #{name}"
114
- end
115
-
116
- private
117
-
118
- def precision
119
- {
120
- :feet => 0,
121
- :meters => 2,
122
- :km => 4,
123
- :miles => 4
124
- }
125
- end
126
- end
127
- end
128
-
129
- def self.wants? unit_opts, unit
130
- unit_opts == unit || unit_opts[unit]
131
- end
132
- end
133
-
134
- require 'geo-distance/haversine'
135
- require 'geo-distance/spherical'
136
- require 'geo-distance/vincenty'
@@ -0,0 +1,71 @@
1
+ class GeoDistance
2
+ # this is global because if computing lots of track point distances, it didn't make
3
+ # sense to new a Hash each time over potentially 100's of thousands of points
4
+
5
+ module ClassMethods
6
+ # radius of the great circle in miles
7
+ # radius in kilometers...some algorithms use 6367
8
+
9
+ def distance(*args)
10
+ klass = case default_algorithm
11
+ when :flat
12
+ GeoDistance::Flat
13
+ when :haversine
14
+ GeoDistance::Haversine
15
+ when :spherical
16
+ GeoDistance::Spherical
17
+ when :vincenty
18
+ GeoDistance::Vincenty
19
+ when :nvector
20
+ GeoDistance::NVector
21
+ else
22
+ raise ArgumentError, "Not a valid algorithm. Must be one of: #{algorithms}"
23
+ end
24
+ klass.distance *args
25
+ end
26
+
27
+ def default_units= name
28
+ raise ArgumentError, "Not a valid units. Must be one of: #{all_units}" if !all_units.include?(name.to_sym)
29
+ @default_units = GeoUnits.key(name)
30
+ end
31
+
32
+ def default_units
33
+ @default_units || :kms
34
+ end
35
+
36
+ def default_algorithm= name
37
+ raise ArgumentError, "Not a valid algorithm. Must be one of: #{algorithms}" if !algorithms.include?(name.to_sym)
38
+ @default_algorithm = name
39
+ end
40
+
41
+ def default_algorithm
42
+ @default_algorithm || :haversine
43
+ end
44
+
45
+ def earth_radius units
46
+ GeoUnits.earth_radius units
47
+ end
48
+
49
+ def radians_per_degree
50
+ 0.017453293 # PI/180
51
+ end
52
+
53
+ def radians_ratio unit
54
+ GeoDistance.radians_per_degree * earth_radius[unit]
55
+ end
56
+
57
+ def all_units
58
+ GeoUnits.all_units
59
+ end
60
+
61
+ def units
62
+ GeoUnits.units
63
+ end
64
+
65
+ def algorithms
66
+ [:flat, :haversine, :spherical, :vincenty, :nvector]
67
+ end
68
+ end
69
+
70
+ extend ClassMethods
71
+ end