diff --git a/lib/geocoder/calculations.rb b/lib/geocoder/calculations.rb index 35136960c3a8bba49dae3bf04cf725600c52e9e7..b99e35f0a6add04230c7ff5e0dbacfcd32ac42af 100644 --- a/lib/geocoder/calculations.rb +++ b/lib/geocoder/calculations.rb @@ -88,5 +88,35 @@ module Geocoder def km_in_mi 0.621371192 end + + ## + # Calculate bearing between two sets of co-ordinates + # + def bearing_between(lat1, lon1, lat2, lon2, options = {}) + # Math courtesy of http://www.movable-type.co.uk/scripts/latlong.html + dlon = to_radians((lon1 - lon2).abs) + + y = Math.sin(dlon) * Math.cos(lat2) + x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dlon) + brng = Math.atan2(x,y) + (to_degrees(brng) + 360) % 360 + end + + # If you want more or fewer points simply override Geocoder::Calculations.COMPASS_POINTS with your own array + COMPASS_POINTS = [{:name => "North", :abbr => "N"}, + {:name => "North East", :abbr => "NE"}, + {:name => "East", :abbr => "E"}, + {:name => "South East", :abbr => "SE"}, + {:name => "South", :abbr => "S"}, + {:name => "South West", :abbr => "SW"}, + {:name => "West", :abbr => "W"}, + {:name => "North West", :abbr => "NW"}] + + ## + # Compass direction (North, South, etc.) between two sets of co-ordinates + def compass_point(bearing, points = COMPASS_POINTS) + seg_size = 360/points.length + points[((bearing + (seg_size/2) ) % 360) / seg_size] + end end end diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb index 2d29fc109e399f1033ffe5612eccd1f413e32ebf..458b59ee55683f13a7b6f325a4eefd9a2f857835 100644 --- a/test/geocoder_test.rb +++ b/test/geocoder_test.rb @@ -23,6 +23,19 @@ class GeocoderTest < Test::Unit::TestCase assert_equal 69, Geocoder::Calculations.distance_between(0,0, 0,1).round end + def test_distance_between + hash_north = {:name => "North", :abbr => "N"} + hash_south = {:name => "South", :abbr => "S"} + hash_nw = {:name => "North West", :abbr => "NW"} + assert_equal hash_north, Geocoder::Calculations.compass_point(0) + assert_equal hash_north, Geocoder::Calculations.compass_point(360) + assert_equal hash_north, Geocoder::Calculations.compass_point(361) + assert_equal hash_north, Geocoder::Calculations.compass_point(-22) + assert_equal hash_nw, Geocoder::Calculations.compass_point(-23) + assert_equal hash_south, Geocoder::Calculations.compass_point(180) + assert_equal hash_south, Geocoder::Calculations.compass_point(181) + end + def test_geographic_center_with_arrays assert_equal [0.0, 0.5], Geocoder::Calculations.geographic_center([[0,0], [0,1]])