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
@@ -1,24 +0,0 @@
1
- require 'geo-distance/core_ext'
2
- require 'geo-distance/formula'
3
-
4
- module GeoDistance
5
- class Spherical < DistanceFormula
6
- def self.distance( lat1, lon1, lat2, lon2)
7
- from_longitude = lon1.to_radians
8
- from_latitude = lat1.to_radians
9
- to_longitude = lon2.to_radians
10
- to_latitude = lat2.to_radians
11
-
12
- c = Math.acos(
13
- Math.sin(from_latitude) *
14
- Math.sin(to_latitude) +
15
-
16
- Math.cos(from_latitude) *
17
- Math.cos(to_latitude) *
18
- Math.cos(to_longitude - from_longitude)
19
- ) #* EARTH_RADIUS[units.to_sym]
20
-
21
- GeoDistance::Distance.new c
22
- end
23
- end
24
- end
@@ -1,79 +0,0 @@
1
- require 'geo-distance/core_ext'
2
- require 'geo-distance/formula'
3
-
4
- module GeoDistance
5
- class Vincenty < DistanceFormula
6
-
7
- # Calculate the distance between two Locations using the Vincenty formula
8
- #
9
- # Graticule::Distance::Vincenty.distance(
10
- # Graticule::Location.new(:latitude => 42.7654, :longitude => -86.1085),
11
- # Graticule::Location.new(:latitude => 41.849838, :longitude => -87.648193)
12
- # )
13
- # #=> 101.070118000159
14
- #
15
- def self.distance(lat1, lon1, lat2, lon2)
16
- from_longitude = lon1.to_radians
17
- from_latitude = lat1.to_radians
18
- to_longitude = lon2.to_radians
19
- to_latitude = lat2.to_radians
20
-
21
- earth_major_axis_radius = EARTH_MAJOR_AXIS_RADIUS[:kilometers]
22
- earth_minor_axis_radius = EARTH_MINOR_AXIS_RADIUS[:kilometers]
23
-
24
- f = (earth_major_axis_radius - earth_minor_axis_radius) / earth_major_axis_radius
25
-
26
- l = to_longitude - from_longitude
27
- u1 = atan((1-f) * tan(from_latitude))
28
- u2 = atan((1-f) * tan(to_latitude))
29
- sin_u1 = sin(u1)
30
- cos_u1 = cos(u1)
31
- sin_u2 = sin(u2)
32
- cos_u2 = cos(u2)
33
-
34
- lambda = l
35
- lambda_p = 2 * PI
36
- iteration_limit = 20
37
- while (lambda-lambda_p).abs > 1e-12 && (iteration_limit -= 1) > 0
38
- sin_lambda = sin(lambda)
39
- cos_lambda = cos(lambda)
40
- sin_sigma = sqrt((cos_u2*sin_lambda) * (cos_u2*sin_lambda) +
41
- (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda) * (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda))
42
- return 0 if sin_sigma == 0 # co-incident points
43
- cos_sigma = sin_u1*sin_u2 + cos_u1*cos_u2*cos_lambda
44
- sigma = atan2(sin_sigma, cos_sigma)
45
- sin_alpha = cos_u1 * cos_u2 * sin_lambda / sin_sigma
46
- cosSqAlpha = 1 - sin_alpha*sin_alpha
47
- cos2SigmaM = cos_sigma - 2*sin_u1*sin_u2/cosSqAlpha
48
-
49
- cos2SigmaM = 0 if cos2SigmaM.nan? # equatorial line: cosSqAlpha=0 (§6)
50
-
51
- c = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))
52
- lambda_p = lambda
53
- lambda = l + (1-c) * f * sin_alpha *
54
- (sigma + c*sin_sigma*(cos2SigmaM+c*cos_sigma*(-1+2*cos2SigmaM*cos2SigmaM)))
55
- end
56
- # formula failed to converge (happens on antipodal points)
57
- # We'll call Haversine formula instead.
58
- return Haversine.distance(from, to, units) if iteration_limit == 0
59
-
60
- uSq = cosSqAlpha * (earth_major_axis_radius**2 - earth_minor_axis_radius**2) / (earth_minor_axis_radius**2)
61
- a = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))
62
- b = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)))
63
- delta_sigma = b*sin_sigma*(cos2SigmaM+b/4*(cos_sigma*(-1+2*cos2SigmaM*cos2SigmaM)-
64
- b/6*cos2SigmaM*(-3+4*sin_sigma*sin_sigma)*(-3+4*cos2SigmaM*cos2SigmaM)))
65
-
66
- c = earth_minor_axis_radius * a * (sigma-delta_sigma)
67
-
68
- GeoDistance::Distance.new(c / unkilometer)
69
- end
70
-
71
- private
72
-
73
- def self.unkilometer
74
- 6378.135
75
- end
76
-
77
-
78
- end
79
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "GeoDistance core extensions" do
4
- it "should work" do
5
- 5.km.should be_kind_of GeoDistance::Distance
6
- 5.km.distance.should == 5
7
- 5.km.unit.should == :km
8
- end
9
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "GeoDistance default" do
4
- it "should work" do
5
- lon1 = -104.88544
6
- lat1 = 39.06546
7
-
8
- lon2 = -104.80
9
- lat2 = lat1
10
-
11
- GeoDistance.default_algorithm = :haversine
12
-
13
- dist = GeoDistance.distance( lat1, lon1, lat2, lon2 )
14
-
15
- puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist[:meters].number} meters"
16
-
17
- puts "#{dist[:feet]}"
18
- puts "#{dist.meters}"
19
- puts "#{dist[:km]}"
20
- puts "#{dist[:miles]}"
21
- dist[:km].to_s.should match(/7\.376*/)
22
- end
23
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "GeoDistance::Haversine" do
4
- it "should work" do
5
- lon1 = -104.88544
6
- lat1 = 39.06546
7
-
8
- lon2 = -104.80
9
- lat2 = lat1
10
-
11
- dist = GeoDistance::Haversine.distance( lat1, lon1, lat2, lon2 )
12
-
13
- puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist[:meters].number} meters"
14
-
15
- puts "#{dist[:feet]}"
16
- puts "#{dist.meters}"
17
- puts "#{dist[:km]}"
18
- puts "#{dist[:miles]}"
19
- dist[:km].to_s.should match(/7\.376*/)
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "GeoDistance::Spherical" do
4
- it "should work" do
5
- lon1 = -104.88544
6
- lat1 = 39.06546
7
-
8
- lon2 = -104.80
9
- lat2 = lat1
10
-
11
- dist = GeoDistance::Spherical.distance( lat1, lon1, lat2, lon2 )
12
-
13
- puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist[:meters].number} meters"
14
-
15
- puts "#{dist[:feet]}"
16
- puts "#{dist.meters}"
17
- puts "#{dist[:km]}"
18
- puts "#{dist[:miles]}"
19
- dist[:km].to_s.should match(/7\.376*/)
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "GeoDistance::Vincenty" do
4
- it "should work" do
5
- lon1 = -104.88544
6
- lat1 = 39.06546
7
-
8
- lon2 = -104.80
9
- lat2 = lat1
10
-
11
- dist = GeoDistance::Vincenty.distance( lat1, lon1, lat2, lon2 )
12
-
13
- puts "the distance from #{lat1}, #{lon1} to #{lat2}, #{lon2} is: #{dist[:meters].number} meters"
14
-
15
- puts "#{dist[:feet]}"
16
- puts "#{dist.meters}"
17
- puts "#{dist[:km]}"
18
- puts "#{dist[:miles]}"
19
- dist[:km].to_s.should match(/7\.38*/)
20
- end
21
- end