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.
- data/Gemfile +7 -9
- data/Gemfile.lock +30 -13
- data/README.textile +28 -8
- data/VERSION +1 -1
- data/geo-distance.gemspec +40 -32
- data/lib/geo-distance.rb +14 -132
- data/lib/geo-distance/class_methods.rb +71 -0
- data/lib/geo-distance/conversion.rb +67 -0
- data/lib/geo-distance/conversion/meters.rb +29 -0
- data/lib/geo-distance/conversion/radians.rb +36 -0
- data/lib/geo-distance/core_ext.rb +12 -23
- data/lib/geo-distance/distance.rb +24 -0
- data/lib/geo-distance/formula.rb +53 -7
- data/lib/geo-distance/formula/flat.rb +21 -0
- data/lib/geo-distance/{haversine.rb → formula/haversine.rb} +18 -14
- data/lib/geo-distance/formula/n_vector.rb +30 -0
- data/lib/geo-distance/formula/spherical.rb +44 -0
- data/lib/geo-distance/formula/vincenty.rb +80 -0
- data/lib/geo-distance/scale.rb +18 -0
- data/spec/geo_distance/class_methods_spec.rb +70 -0
- data/spec/geo_distance/core_ext_spec.rb +65 -0
- data/spec/geo_distance/distance_spec.rb +74 -0
- data/spec/geo_distance/formula/flat_spec.rb +31 -0
- data/spec/geo_distance/formula/haversine_spec.rb +33 -0
- data/spec/geo_distance/formula/n_vector.rb +33 -0
- data/spec/geo_distance/formula/spherical_spec.rb +33 -0
- data/spec/geo_distance/formula/vincenty_spec.rb +33 -0
- data/spec/spec_helper.rb +0 -10
- metadata +97 -96
- data/lib/geo-distance/spherical.rb +0 -24
- data/lib/geo-distance/vincenty.rb +0 -79
- data/spec/core_ext_spec.rb +0 -9
- data/spec/dist_default_spec.rb +0 -23
- data/spec/dist_haversine_spec.rb +0 -21
- data/spec/dist_spherical_spec.rb +0 -21
- 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
|
data/spec/core_ext_spec.rb
DELETED
data/spec/dist_default_spec.rb
DELETED
@@ -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
|
data/spec/dist_haversine_spec.rb
DELETED
@@ -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
|
data/spec/dist_spherical_spec.rb
DELETED
@@ -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
|
data/spec/dist_vincenty_spec.rb
DELETED
@@ -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
|