From b91a54d3baa771b97414202793cb5fd2d2dd20bb Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Thu, 24 Mar 2011 13:20:36 -0400
Subject: [PATCH] Convert bearing to degrees CW from North.

---
 lib/geocoder/calculations.rb |  4 ++-
 test/geocoder_test.rb        | 54 ++++++++++++++++++++++++++++--------
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/lib/geocoder/calculations.rb b/lib/geocoder/calculations.rb
index 5a994406..77c47449 100644
--- a/lib/geocoder/calculations.rb
+++ b/lib/geocoder/calculations.rb
@@ -52,7 +52,9 @@ module Geocoder
       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
+      # brng is in radians counterclockwise from due east.
+      # Convert to degrees clockwise from due north:
+      (90 - to_degrees(brng) + 360) % 360
     end
 
     ##
diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb
index 1b3f7b08..d0f53bbf 100644
--- a/test/geocoder_test.rb
+++ b/test/geocoder_test.rb
@@ -25,17 +25,6 @@ class GeocoderTest < Test::Unit::TestCase
     assert (la_to_ny - 2444).abs < 10
   end
 
-  def test_compass_points
-    assert_equal "N",  Geocoder::Calculations.compass_point(0)
-    assert_equal "N",  Geocoder::Calculations.compass_point(1.0)
-    assert_equal "N",  Geocoder::Calculations.compass_point(360)
-    assert_equal "N",  Geocoder::Calculations.compass_point(361)
-    assert_equal "N",  Geocoder::Calculations.compass_point(-22)
-    assert_equal "NW", Geocoder::Calculations.compass_point(-23)
-    assert_equal "S",  Geocoder::Calculations.compass_point(180)
-    assert_equal "S",  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]])
@@ -183,6 +172,49 @@ class GeocoderTest < Test::Unit::TestCase
   end
 
 
+  # --- bearing ---
+
+  def test_compass_points
+    assert_equal "N",  Geocoder::Calculations.compass_point(0)
+    assert_equal "N",  Geocoder::Calculations.compass_point(1.0)
+    assert_equal "N",  Geocoder::Calculations.compass_point(360)
+    assert_equal "N",  Geocoder::Calculations.compass_point(361)
+    assert_equal "N",  Geocoder::Calculations.compass_point(-22)
+    assert_equal "NW", Geocoder::Calculations.compass_point(-23)
+    assert_equal "S",  Geocoder::Calculations.compass_point(180)
+    assert_equal "S",  Geocoder::Calculations.compass_point(181)
+  end
+
+  def test_bearing_between
+    bearings = {
+      :n => 0,
+      :e => 90,
+      :s => 180,
+      :w => 270
+    }
+    points = {
+      :n => [41, -75],
+      :e => [40, -74],
+      :s => [39, -75],
+      :w => [40, -76]
+    }
+    directions = [:n, :e, :s, :w]
+    types = [:spherical]
+
+    types.each do |t|
+      directions.each_with_index do |d,i|
+        opp = directions[(i + 2) % 4] # opposite direction
+        p1 = points[d]
+        p2 = points[opp]
+
+        b = Geocoder::Calculations.bearing_between(*(p1 + p2))
+        assert (b - bearings[opp]).abs < 1,
+          "Bearing (#{t}) should be close to #{bearings[opp]} but was #{b}."
+      end
+    end
+  end
+
+
   # --- Google ---
 
   def test_google_result_components
-- 
GitLab