From e8c17f28243523b5f9c0e21e911cc4b2ff030b2d Mon Sep 17 00:00:00 2001 From: Mat Ellis <mat@tecnh.com> Date: Fri, 18 Mar 2011 14:50:04 -0700 Subject: [PATCH] Adds methods for calculating the bearing between two points and for converting that bearing into a compass point, e.g. North or South West. If you want fewer or additional compass points (e.g. South By South West, or just NESW) provide a second parameter containing your array of points, e.g. Geocoder::Calculations::compass_point(90,['north','east','south','west']) --- lib/geocoder/calculations.rb | 30 ++++++++++++++++++++++++++++++ test/geocoder_test.rb | 13 +++++++++++++ 2 files changed, 43 insertions(+) diff --git a/lib/geocoder/calculations.rb b/lib/geocoder/calculations.rb index 35136960..b99e35f0 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 2d29fc10..458b59ee 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]]) -- GitLab